18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * JFFS2 -- Journalling Flash File System, Version 2. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright © 2001-2007 Red Hat, Inc. 58c2ecf20Sopenharmony_ci * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Created by David Woodhouse <dwmw2@infradead.org> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * For licensing information, see the file 'LICENCE' in this directory. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/kernel.h> 168c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 198c2ecf20Sopenharmony_ci#include <linux/crc32.h> 208c2ecf20Sopenharmony_ci#include <linux/compiler.h> 218c2ecf20Sopenharmony_ci#include <linux/stat.h> 228c2ecf20Sopenharmony_ci#include "nodelist.h" 238c2ecf20Sopenharmony_ci#include "compr.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, 268c2ecf20Sopenharmony_ci struct jffs2_inode_cache *ic, 278c2ecf20Sopenharmony_ci struct jffs2_raw_node_ref *raw); 288c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 298c2ecf20Sopenharmony_ci struct jffs2_inode_info *f, struct jffs2_full_dnode *fd); 308c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 318c2ecf20Sopenharmony_ci struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); 328c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 338c2ecf20Sopenharmony_ci struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); 348c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 358c2ecf20Sopenharmony_ci struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, 368c2ecf20Sopenharmony_ci uint32_t start, uint32_t end); 378c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 388c2ecf20Sopenharmony_ci struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, 398c2ecf20Sopenharmony_ci uint32_t start, uint32_t end); 408c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 418c2ecf20Sopenharmony_ci struct jffs2_raw_node_ref *raw, struct jffs2_inode_info *f); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* Called with erase_completion_lock held */ 448c2ecf20Sopenharmony_cistatic struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci struct jffs2_eraseblock *ret; 478c2ecf20Sopenharmony_ci struct list_head *nextlist = NULL; 488c2ecf20Sopenharmony_ci int n = jiffies % 128; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci /* Pick an eraseblock to garbage collect next. This is where we'll 518c2ecf20Sopenharmony_ci put the clever wear-levelling algorithms. Eventually. */ 528c2ecf20Sopenharmony_ci /* We possibly want to favour the dirtier blocks more when the 538c2ecf20Sopenharmony_ci number of free blocks is low. */ 548c2ecf20Sopenharmony_ciagain: 558c2ecf20Sopenharmony_ci if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > c->resv_blocks_gcbad) { 568c2ecf20Sopenharmony_ci jffs2_dbg(1, "Picking block from bad_used_list to GC next\n"); 578c2ecf20Sopenharmony_ci nextlist = &c->bad_used_list; 588c2ecf20Sopenharmony_ci } else if (n < 50 && !list_empty(&c->erasable_list)) { 598c2ecf20Sopenharmony_ci /* Note that most of them will have gone directly to be erased. 608c2ecf20Sopenharmony_ci So don't favour the erasable_list _too_ much. */ 618c2ecf20Sopenharmony_ci jffs2_dbg(1, "Picking block from erasable_list to GC next\n"); 628c2ecf20Sopenharmony_ci nextlist = &c->erasable_list; 638c2ecf20Sopenharmony_ci } else if (n < 110 && !list_empty(&c->very_dirty_list)) { 648c2ecf20Sopenharmony_ci /* Most of the time, pick one off the very_dirty list */ 658c2ecf20Sopenharmony_ci jffs2_dbg(1, "Picking block from very_dirty_list to GC next\n"); 668c2ecf20Sopenharmony_ci nextlist = &c->very_dirty_list; 678c2ecf20Sopenharmony_ci } else if (n < 126 && !list_empty(&c->dirty_list)) { 688c2ecf20Sopenharmony_ci jffs2_dbg(1, "Picking block from dirty_list to GC next\n"); 698c2ecf20Sopenharmony_ci nextlist = &c->dirty_list; 708c2ecf20Sopenharmony_ci } else if (!list_empty(&c->clean_list)) { 718c2ecf20Sopenharmony_ci jffs2_dbg(1, "Picking block from clean_list to GC next\n"); 728c2ecf20Sopenharmony_ci nextlist = &c->clean_list; 738c2ecf20Sopenharmony_ci } else if (!list_empty(&c->dirty_list)) { 748c2ecf20Sopenharmony_ci jffs2_dbg(1, "Picking block from dirty_list to GC next (clean_list was empty)\n"); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci nextlist = &c->dirty_list; 778c2ecf20Sopenharmony_ci } else if (!list_empty(&c->very_dirty_list)) { 788c2ecf20Sopenharmony_ci jffs2_dbg(1, "Picking block from very_dirty_list to GC next (clean_list and dirty_list were empty)\n"); 798c2ecf20Sopenharmony_ci nextlist = &c->very_dirty_list; 808c2ecf20Sopenharmony_ci } else if (!list_empty(&c->erasable_list)) { 818c2ecf20Sopenharmony_ci jffs2_dbg(1, "Picking block from erasable_list to GC next (clean_list and {very_,}dirty_list were empty)\n"); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci nextlist = &c->erasable_list; 848c2ecf20Sopenharmony_ci } else if (!list_empty(&c->erasable_pending_wbuf_list)) { 858c2ecf20Sopenharmony_ci /* There are blocks are wating for the wbuf sync */ 868c2ecf20Sopenharmony_ci jffs2_dbg(1, "Synching wbuf in order to reuse erasable_pending_wbuf_list blocks\n"); 878c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 888c2ecf20Sopenharmony_ci jffs2_flush_wbuf_pad(c); 898c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 908c2ecf20Sopenharmony_ci goto again; 918c2ecf20Sopenharmony_ci } else { 928c2ecf20Sopenharmony_ci /* Eep. All were empty */ 938c2ecf20Sopenharmony_ci jffs2_dbg(1, "No clean, dirty _or_ erasable blocks to GC from! Where are they all?\n"); 948c2ecf20Sopenharmony_ci return NULL; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci ret = list_entry(nextlist->next, struct jffs2_eraseblock, list); 988c2ecf20Sopenharmony_ci list_del(&ret->list); 998c2ecf20Sopenharmony_ci c->gcblock = ret; 1008c2ecf20Sopenharmony_ci ret->gc_node = ret->first_node; 1018c2ecf20Sopenharmony_ci if (!ret->gc_node) { 1028c2ecf20Sopenharmony_ci pr_warn("Eep. ret->gc_node for block at 0x%08x is NULL\n", 1038c2ecf20Sopenharmony_ci ret->offset); 1048c2ecf20Sopenharmony_ci BUG(); 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* Have we accidentally picked a clean block with wasted space ? */ 1088c2ecf20Sopenharmony_ci if (ret->wasted_size) { 1098c2ecf20Sopenharmony_ci jffs2_dbg(1, "Converting wasted_size %08x to dirty_size\n", 1108c2ecf20Sopenharmony_ci ret->wasted_size); 1118c2ecf20Sopenharmony_ci ret->dirty_size += ret->wasted_size; 1128c2ecf20Sopenharmony_ci c->wasted_size -= ret->wasted_size; 1138c2ecf20Sopenharmony_ci c->dirty_size += ret->wasted_size; 1148c2ecf20Sopenharmony_ci ret->wasted_size = 0; 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci return ret; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci/* jffs2_garbage_collect_pass 1218c2ecf20Sopenharmony_ci * Make a single attempt to progress GC. Move one node, and possibly 1228c2ecf20Sopenharmony_ci * start erasing one eraseblock. 1238c2ecf20Sopenharmony_ci */ 1248c2ecf20Sopenharmony_ciint jffs2_garbage_collect_pass(struct jffs2_sb_info *c) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci struct jffs2_inode_info *f; 1278c2ecf20Sopenharmony_ci struct jffs2_inode_cache *ic; 1288c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb; 1298c2ecf20Sopenharmony_ci struct jffs2_raw_node_ref *raw; 1308c2ecf20Sopenharmony_ci uint32_t gcblock_dirty; 1318c2ecf20Sopenharmony_ci int ret = 0, inum, nlink; 1328c2ecf20Sopenharmony_ci int xattr = 0; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&c->alloc_sem)) 1358c2ecf20Sopenharmony_ci return -EINTR; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci for (;;) { 1398c2ecf20Sopenharmony_ci /* We can't start doing GC until we've finished checking 1408c2ecf20Sopenharmony_ci the node CRCs etc. */ 1418c2ecf20Sopenharmony_ci int bucket, want_ino; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 1448c2ecf20Sopenharmony_ci if (!c->unchecked_size) 1458c2ecf20Sopenharmony_ci break; 1468c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (!xattr) 1498c2ecf20Sopenharmony_ci xattr = jffs2_verify_xattr(c); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci spin_lock(&c->inocache_lock); 1528c2ecf20Sopenharmony_ci /* Instead of doing the inodes in numeric order, doing a lookup 1538c2ecf20Sopenharmony_ci * in the hash for each possible number, just walk the hash 1548c2ecf20Sopenharmony_ci * buckets of *existing* inodes. This means that we process 1558c2ecf20Sopenharmony_ci * them out-of-order, but it can be a lot faster if there's 1568c2ecf20Sopenharmony_ci * a sparse inode# space. Which there often is. */ 1578c2ecf20Sopenharmony_ci want_ino = c->check_ino; 1588c2ecf20Sopenharmony_ci for (bucket = c->check_ino % c->inocache_hashsize ; bucket < c->inocache_hashsize; bucket++) { 1598c2ecf20Sopenharmony_ci for (ic = c->inocache_list[bucket]; ic; ic = ic->next) { 1608c2ecf20Sopenharmony_ci if (ic->ino < want_ino) 1618c2ecf20Sopenharmony_ci continue; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci if (ic->state != INO_STATE_CHECKEDABSENT && 1648c2ecf20Sopenharmony_ci ic->state != INO_STATE_PRESENT) 1658c2ecf20Sopenharmony_ci goto got_next; /* with inocache_lock held */ 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci jffs2_dbg(1, "Skipping ino #%u already checked\n", 1688c2ecf20Sopenharmony_ci ic->ino); 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci want_ino = 0; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* Point c->check_ino past the end of the last bucket. */ 1748c2ecf20Sopenharmony_ci c->check_ino = ((c->highest_ino + c->inocache_hashsize + 1) & 1758c2ecf20Sopenharmony_ci ~c->inocache_hashsize) - 1; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci spin_unlock(&c->inocache_lock); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci pr_crit("Checked all inodes but still 0x%x bytes of unchecked space?\n", 1808c2ecf20Sopenharmony_ci c->unchecked_size); 1818c2ecf20Sopenharmony_ci jffs2_dbg_dump_block_lists_nolock(c); 1828c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 1838c2ecf20Sopenharmony_ci return -ENOSPC; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci got_next: 1868c2ecf20Sopenharmony_ci /* For next time round the loop, we want c->checked_ino to indicate 1878c2ecf20Sopenharmony_ci * the *next* one we want to check. And since we're walking the 1888c2ecf20Sopenharmony_ci * buckets rather than doing it sequentially, it's: */ 1898c2ecf20Sopenharmony_ci c->check_ino = ic->ino + c->inocache_hashsize; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci if (!ic->pino_nlink) { 1928c2ecf20Sopenharmony_ci jffs2_dbg(1, "Skipping check of ino #%d with nlink/pino zero\n", 1938c2ecf20Sopenharmony_ci ic->ino); 1948c2ecf20Sopenharmony_ci spin_unlock(&c->inocache_lock); 1958c2ecf20Sopenharmony_ci jffs2_xattr_delete_inode(c, ic); 1968c2ecf20Sopenharmony_ci continue; 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci switch(ic->state) { 1998c2ecf20Sopenharmony_ci case INO_STATE_CHECKEDABSENT: 2008c2ecf20Sopenharmony_ci case INO_STATE_PRESENT: 2018c2ecf20Sopenharmony_ci spin_unlock(&c->inocache_lock); 2028c2ecf20Sopenharmony_ci continue; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci case INO_STATE_GC: 2058c2ecf20Sopenharmony_ci case INO_STATE_CHECKING: 2068c2ecf20Sopenharmony_ci pr_warn("Inode #%u is in state %d during CRC check phase!\n", 2078c2ecf20Sopenharmony_ci ic->ino, ic->state); 2088c2ecf20Sopenharmony_ci spin_unlock(&c->inocache_lock); 2098c2ecf20Sopenharmony_ci BUG(); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci case INO_STATE_READING: 2128c2ecf20Sopenharmony_ci /* We need to wait for it to finish, lest we move on 2138c2ecf20Sopenharmony_ci and trigger the BUG() above while we haven't yet 2148c2ecf20Sopenharmony_ci finished checking all its nodes */ 2158c2ecf20Sopenharmony_ci jffs2_dbg(1, "Waiting for ino #%u to finish reading\n", 2168c2ecf20Sopenharmony_ci ic->ino); 2178c2ecf20Sopenharmony_ci /* We need to come back again for the _same_ inode. We've 2188c2ecf20Sopenharmony_ci made no progress in this case, but that should be OK */ 2198c2ecf20Sopenharmony_ci c->check_ino = ic->ino; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 2228c2ecf20Sopenharmony_ci sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); 2238c2ecf20Sopenharmony_ci return 0; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci default: 2268c2ecf20Sopenharmony_ci BUG(); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci case INO_STATE_UNCHECKED: 2298c2ecf20Sopenharmony_ci ; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci ic->state = INO_STATE_CHECKING; 2328c2ecf20Sopenharmony_ci spin_unlock(&c->inocache_lock); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): triggering inode scan of ino#%u\n", 2358c2ecf20Sopenharmony_ci __func__, ic->ino); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci ret = jffs2_do_crccheck_inode(c, ic); 2388c2ecf20Sopenharmony_ci if (ret) 2398c2ecf20Sopenharmony_ci pr_warn("Returned error for crccheck of ino #%u. Expect badness...\n", 2408c2ecf20Sopenharmony_ci ic->ino); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT); 2438c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 2448c2ecf20Sopenharmony_ci return ret; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci /* If there are any blocks which need erasing, erase them now */ 2488c2ecf20Sopenharmony_ci if (!list_empty(&c->erase_complete_list) || 2498c2ecf20Sopenharmony_ci !list_empty(&c->erase_pending_list)) { 2508c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 2518c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 2528c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): erasing pending blocks\n", __func__); 2538c2ecf20Sopenharmony_ci if (jffs2_erase_pending_blocks(c, 1)) 2548c2ecf20Sopenharmony_ci return 0; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci jffs2_dbg(1, "No progress from erasing block; doing GC anyway\n"); 2578c2ecf20Sopenharmony_ci mutex_lock(&c->alloc_sem); 2588c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci /* First, work out which block we're garbage-collecting */ 2628c2ecf20Sopenharmony_ci jeb = c->gcblock; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci if (!jeb) 2658c2ecf20Sopenharmony_ci jeb = jffs2_find_gc_block(c); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci if (!jeb) { 2688c2ecf20Sopenharmony_ci /* Couldn't find a free block. But maybe we can just erase one and make 'progress'? */ 2698c2ecf20Sopenharmony_ci if (c->nr_erasing_blocks) { 2708c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 2718c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 2728c2ecf20Sopenharmony_ci return -EAGAIN; 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci jffs2_dbg(1, "Couldn't find erase block to garbage collect!\n"); 2758c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 2768c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 2778c2ecf20Sopenharmony_ci return -EIO; 2788c2ecf20Sopenharmony_ci } 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci jffs2_dbg(1, "GC from block %08x, used_size %08x, dirty_size %08x, free_size %08x\n", 2818c2ecf20Sopenharmony_ci jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); 2828c2ecf20Sopenharmony_ci D1(if (c->nextblock) 2838c2ecf20Sopenharmony_ci printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size)); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (!jeb->used_size) { 2868c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 2878c2ecf20Sopenharmony_ci goto eraseit; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci raw = jeb->gc_node; 2918c2ecf20Sopenharmony_ci gcblock_dirty = jeb->dirty_size; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci while(ref_obsolete(raw)) { 2948c2ecf20Sopenharmony_ci jffs2_dbg(1, "Node at 0x%08x is obsolete... skipping\n", 2958c2ecf20Sopenharmony_ci ref_offset(raw)); 2968c2ecf20Sopenharmony_ci raw = ref_next(raw); 2978c2ecf20Sopenharmony_ci if (unlikely(!raw)) { 2988c2ecf20Sopenharmony_ci pr_warn("eep. End of raw list while still supposedly nodes to GC\n"); 2998c2ecf20Sopenharmony_ci pr_warn("erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", 3008c2ecf20Sopenharmony_ci jeb->offset, jeb->free_size, 3018c2ecf20Sopenharmony_ci jeb->dirty_size, jeb->used_size); 3028c2ecf20Sopenharmony_ci jeb->gc_node = raw; 3038c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 3048c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 3058c2ecf20Sopenharmony_ci BUG(); 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci jeb->gc_node = raw; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci jffs2_dbg(1, "Going to garbage collect node at 0x%08x\n", 3118c2ecf20Sopenharmony_ci ref_offset(raw)); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci if (!raw->next_in_ino) { 3148c2ecf20Sopenharmony_ci /* Inode-less node. Clean marker, snapshot or something like that */ 3158c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 3168c2ecf20Sopenharmony_ci if (ref_flags(raw) == REF_PRISTINE) { 3178c2ecf20Sopenharmony_ci /* It's an unknown node with JFFS2_FEATURE_RWCOMPAT_COPY */ 3188c2ecf20Sopenharmony_ci jffs2_garbage_collect_pristine(c, NULL, raw); 3198c2ecf20Sopenharmony_ci } else { 3208c2ecf20Sopenharmony_ci /* Just mark it obsolete */ 3218c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, raw); 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 3248c2ecf20Sopenharmony_ci goto eraseit_lock; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci ic = jffs2_raw_ref_to_ic(raw); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_FS_XATTR 3308c2ecf20Sopenharmony_ci /* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr. 3318c2ecf20Sopenharmony_ci * We can decide whether this node is inode or xattr by ic->class. */ 3328c2ecf20Sopenharmony_ci if (ic->class == RAWNODE_CLASS_XATTR_DATUM 3338c2ecf20Sopenharmony_ci || ic->class == RAWNODE_CLASS_XATTR_REF) { 3348c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci if (ic->class == RAWNODE_CLASS_XATTR_DATUM) { 3378c2ecf20Sopenharmony_ci ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic, raw); 3388c2ecf20Sopenharmony_ci } else { 3398c2ecf20Sopenharmony_ci ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw); 3408c2ecf20Sopenharmony_ci } 3418c2ecf20Sopenharmony_ci goto test_gcnode; 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci#endif 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* We need to hold the inocache. Either the erase_completion_lock or 3468c2ecf20Sopenharmony_ci the inocache_lock are sufficient; we trade down since the inocache_lock 3478c2ecf20Sopenharmony_ci causes less contention. */ 3488c2ecf20Sopenharmony_ci spin_lock(&c->inocache_lock); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): collecting from block @0x%08x. Node @0x%08x(%d), ino #%u\n", 3538c2ecf20Sopenharmony_ci __func__, jeb->offset, ref_offset(raw), ref_flags(raw), 3548c2ecf20Sopenharmony_ci ic->ino); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci /* Three possibilities: 3578c2ecf20Sopenharmony_ci 1. Inode is already in-core. We must iget it and do proper 3588c2ecf20Sopenharmony_ci updating to its fragtree, etc. 3598c2ecf20Sopenharmony_ci 2. Inode is not in-core, node is REF_PRISTINE. We lock the 3608c2ecf20Sopenharmony_ci inocache to prevent a read_inode(), copy the node intact. 3618c2ecf20Sopenharmony_ci 3. Inode is not in-core, node is not pristine. We must iget() 3628c2ecf20Sopenharmony_ci and take the slow path. 3638c2ecf20Sopenharmony_ci */ 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci switch(ic->state) { 3668c2ecf20Sopenharmony_ci case INO_STATE_CHECKEDABSENT: 3678c2ecf20Sopenharmony_ci /* It's been checked, but it's not currently in-core. 3688c2ecf20Sopenharmony_ci We can just copy any pristine nodes, but have 3698c2ecf20Sopenharmony_ci to prevent anyone else from doing read_inode() while 3708c2ecf20Sopenharmony_ci we're at it, so we set the state accordingly */ 3718c2ecf20Sopenharmony_ci if (ref_flags(raw) == REF_PRISTINE) 3728c2ecf20Sopenharmony_ci ic->state = INO_STATE_GC; 3738c2ecf20Sopenharmony_ci else { 3748c2ecf20Sopenharmony_ci jffs2_dbg(1, "Ino #%u is absent but node not REF_PRISTINE. Reading.\n", 3758c2ecf20Sopenharmony_ci ic->ino); 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci break; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci case INO_STATE_PRESENT: 3808c2ecf20Sopenharmony_ci /* It's in-core. GC must iget() it. */ 3818c2ecf20Sopenharmony_ci break; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci case INO_STATE_UNCHECKED: 3848c2ecf20Sopenharmony_ci case INO_STATE_CHECKING: 3858c2ecf20Sopenharmony_ci case INO_STATE_GC: 3868c2ecf20Sopenharmony_ci /* Should never happen. We should have finished checking 3878c2ecf20Sopenharmony_ci by the time we actually start doing any GC, and since 3888c2ecf20Sopenharmony_ci we're holding the alloc_sem, no other garbage collection 3898c2ecf20Sopenharmony_ci can happen. 3908c2ecf20Sopenharmony_ci */ 3918c2ecf20Sopenharmony_ci pr_crit("Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n", 3928c2ecf20Sopenharmony_ci ic->ino, ic->state); 3938c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 3948c2ecf20Sopenharmony_ci spin_unlock(&c->inocache_lock); 3958c2ecf20Sopenharmony_ci BUG(); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci case INO_STATE_READING: 3988c2ecf20Sopenharmony_ci /* Someone's currently trying to read it. We must wait for 3998c2ecf20Sopenharmony_ci them to finish and then go through the full iget() route 4008c2ecf20Sopenharmony_ci to do the GC. However, sometimes read_inode() needs to get 4018c2ecf20Sopenharmony_ci the alloc_sem() (for marking nodes invalid) so we must 4028c2ecf20Sopenharmony_ci drop the alloc_sem before sleeping. */ 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 4058c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): waiting for ino #%u in state %d\n", 4068c2ecf20Sopenharmony_ci __func__, ic->ino, ic->state); 4078c2ecf20Sopenharmony_ci sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); 4088c2ecf20Sopenharmony_ci /* And because we dropped the alloc_sem we must start again from the 4098c2ecf20Sopenharmony_ci beginning. Ponder chance of livelock here -- we're returning success 4108c2ecf20Sopenharmony_ci without actually making any progress. 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci Q: What are the chances that the inode is back in INO_STATE_READING 4138c2ecf20Sopenharmony_ci again by the time we next enter this function? And that this happens 4148c2ecf20Sopenharmony_ci enough times to cause a real delay? 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci A: Small enough that I don't care :) 4178c2ecf20Sopenharmony_ci */ 4188c2ecf20Sopenharmony_ci return 0; 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci /* OK. Now if the inode is in state INO_STATE_GC, we are going to copy the 4228c2ecf20Sopenharmony_ci node intact, and we don't have to muck about with the fragtree etc. 4238c2ecf20Sopenharmony_ci because we know it's not in-core. If it _was_ in-core, we go through 4248c2ecf20Sopenharmony_ci all the iget() crap anyway */ 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci if (ic->state == INO_STATE_GC) { 4278c2ecf20Sopenharmony_ci spin_unlock(&c->inocache_lock); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci ret = jffs2_garbage_collect_pristine(c, ic, raw); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci spin_lock(&c->inocache_lock); 4328c2ecf20Sopenharmony_ci ic->state = INO_STATE_CHECKEDABSENT; 4338c2ecf20Sopenharmony_ci wake_up(&c->inocache_wq); 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci if (ret != -EBADFD) { 4368c2ecf20Sopenharmony_ci spin_unlock(&c->inocache_lock); 4378c2ecf20Sopenharmony_ci goto test_gcnode; 4388c2ecf20Sopenharmony_ci } 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci /* Fall through if it wanted us to, with inocache_lock held */ 4418c2ecf20Sopenharmony_ci } 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci /* Prevent the fairly unlikely race where the gcblock is 4448c2ecf20Sopenharmony_ci entirely obsoleted by the final close of a file which had 4458c2ecf20Sopenharmony_ci the only valid nodes in the block, followed by erasure, 4468c2ecf20Sopenharmony_ci followed by freeing of the ic because the erased block(s) 4478c2ecf20Sopenharmony_ci held _all_ the nodes of that inode.... never been seen but 4488c2ecf20Sopenharmony_ci it's vaguely possible. */ 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci inum = ic->ino; 4518c2ecf20Sopenharmony_ci nlink = ic->pino_nlink; 4528c2ecf20Sopenharmony_ci spin_unlock(&c->inocache_lock); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci f = jffs2_gc_fetch_inode(c, inum, !nlink); 4558c2ecf20Sopenharmony_ci if (IS_ERR(f)) { 4568c2ecf20Sopenharmony_ci ret = PTR_ERR(f); 4578c2ecf20Sopenharmony_ci goto release_sem; 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci if (!f) { 4608c2ecf20Sopenharmony_ci ret = 0; 4618c2ecf20Sopenharmony_ci goto release_sem; 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci ret = jffs2_garbage_collect_live(c, jeb, raw, f); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci jffs2_gc_release_inode(c, f); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci test_gcnode: 4698c2ecf20Sopenharmony_ci if (jeb->dirty_size == gcblock_dirty && !ref_obsolete(jeb->gc_node)) { 4708c2ecf20Sopenharmony_ci /* Eep. This really should never happen. GC is broken */ 4718c2ecf20Sopenharmony_ci pr_err("Error garbage collecting node at %08x!\n", 4728c2ecf20Sopenharmony_ci ref_offset(jeb->gc_node)); 4738c2ecf20Sopenharmony_ci ret = -ENOSPC; 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci release_sem: 4768c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci eraseit_lock: 4798c2ecf20Sopenharmony_ci /* If we've finished this block, start it erasing */ 4808c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci eraseit: 4838c2ecf20Sopenharmony_ci if (c->gcblock && !c->gcblock->used_size) { 4848c2ecf20Sopenharmony_ci jffs2_dbg(1, "Block at 0x%08x completely obsoleted by GC. Moving to erase_pending_list\n", 4858c2ecf20Sopenharmony_ci c->gcblock->offset); 4868c2ecf20Sopenharmony_ci /* We're GC'ing an empty block? */ 4878c2ecf20Sopenharmony_ci list_add_tail(&c->gcblock->list, &c->erase_pending_list); 4888c2ecf20Sopenharmony_ci c->gcblock = NULL; 4898c2ecf20Sopenharmony_ci c->nr_erasing_blocks++; 4908c2ecf20Sopenharmony_ci jffs2_garbage_collect_trigger(c); 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci return ret; 4958c2ecf20Sopenharmony_ci} 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 4988c2ecf20Sopenharmony_ci struct jffs2_raw_node_ref *raw, struct jffs2_inode_info *f) 4998c2ecf20Sopenharmony_ci{ 5008c2ecf20Sopenharmony_ci struct jffs2_node_frag *frag; 5018c2ecf20Sopenharmony_ci struct jffs2_full_dnode *fn = NULL; 5028c2ecf20Sopenharmony_ci struct jffs2_full_dirent *fd; 5038c2ecf20Sopenharmony_ci uint32_t start = 0, end = 0, nrfrags = 0; 5048c2ecf20Sopenharmony_ci int ret = 0; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci mutex_lock(&f->sem); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci /* Now we have the lock for this inode. Check that it's still the one at the head 5098c2ecf20Sopenharmony_ci of the list. */ 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci if (c->gcblock != jeb) { 5148c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 5158c2ecf20Sopenharmony_ci jffs2_dbg(1, "GC block is no longer gcblock. Restart\n"); 5168c2ecf20Sopenharmony_ci goto upnout; 5178c2ecf20Sopenharmony_ci } 5188c2ecf20Sopenharmony_ci if (ref_obsolete(raw)) { 5198c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 5208c2ecf20Sopenharmony_ci jffs2_dbg(1, "node to be GC'd was obsoleted in the meantime.\n"); 5218c2ecf20Sopenharmony_ci /* They'll call again */ 5228c2ecf20Sopenharmony_ci goto upnout; 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci /* OK. Looks safe. And nobody can get us now because we have the semaphore. Move the block */ 5278c2ecf20Sopenharmony_ci if (f->metadata && f->metadata->raw == raw) { 5288c2ecf20Sopenharmony_ci fn = f->metadata; 5298c2ecf20Sopenharmony_ci ret = jffs2_garbage_collect_metadata(c, jeb, f, fn); 5308c2ecf20Sopenharmony_ci goto upnout; 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci /* FIXME. Read node and do lookup? */ 5348c2ecf20Sopenharmony_ci for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) { 5358c2ecf20Sopenharmony_ci if (frag->node && frag->node->raw == raw) { 5368c2ecf20Sopenharmony_ci fn = frag->node; 5378c2ecf20Sopenharmony_ci end = frag->ofs + frag->size; 5388c2ecf20Sopenharmony_ci if (!nrfrags++) 5398c2ecf20Sopenharmony_ci start = frag->ofs; 5408c2ecf20Sopenharmony_ci if (nrfrags == frag->node->frags) 5418c2ecf20Sopenharmony_ci break; /* We've found them all */ 5428c2ecf20Sopenharmony_ci } 5438c2ecf20Sopenharmony_ci } 5448c2ecf20Sopenharmony_ci if (fn) { 5458c2ecf20Sopenharmony_ci if (ref_flags(raw) == REF_PRISTINE) { 5468c2ecf20Sopenharmony_ci ret = jffs2_garbage_collect_pristine(c, f->inocache, raw); 5478c2ecf20Sopenharmony_ci if (!ret) { 5488c2ecf20Sopenharmony_ci /* Urgh. Return it sensibly. */ 5498c2ecf20Sopenharmony_ci frag->node->raw = f->inocache->nodes; 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci if (ret != -EBADFD) 5528c2ecf20Sopenharmony_ci goto upnout; 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci /* We found a datanode. Do the GC */ 5558c2ecf20Sopenharmony_ci if((start >> PAGE_SHIFT) < ((end-1) >> PAGE_SHIFT)) { 5568c2ecf20Sopenharmony_ci /* It crosses a page boundary. Therefore, it must be a hole. */ 5578c2ecf20Sopenharmony_ci ret = jffs2_garbage_collect_hole(c, jeb, f, fn, start, end); 5588c2ecf20Sopenharmony_ci } else { 5598c2ecf20Sopenharmony_ci /* It could still be a hole. But we GC the page this way anyway */ 5608c2ecf20Sopenharmony_ci ret = jffs2_garbage_collect_dnode(c, jeb, f, fn, start, end); 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci goto upnout; 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci /* Wasn't a dnode. Try dirent */ 5668c2ecf20Sopenharmony_ci for (fd = f->dents; fd; fd=fd->next) { 5678c2ecf20Sopenharmony_ci if (fd->raw == raw) 5688c2ecf20Sopenharmony_ci break; 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci if (fd && fd->ino) { 5728c2ecf20Sopenharmony_ci ret = jffs2_garbage_collect_dirent(c, jeb, f, fd); 5738c2ecf20Sopenharmony_ci } else if (fd) { 5748c2ecf20Sopenharmony_ci ret = jffs2_garbage_collect_deletion_dirent(c, jeb, f, fd); 5758c2ecf20Sopenharmony_ci } else { 5768c2ecf20Sopenharmony_ci pr_warn("Raw node at 0x%08x wasn't in node lists for ino #%u\n", 5778c2ecf20Sopenharmony_ci ref_offset(raw), f->inocache->ino); 5788c2ecf20Sopenharmony_ci if (ref_obsolete(raw)) { 5798c2ecf20Sopenharmony_ci pr_warn("But it's obsolete so we don't mind too much\n"); 5808c2ecf20Sopenharmony_ci } else { 5818c2ecf20Sopenharmony_ci jffs2_dbg_dump_node(c, ref_offset(raw)); 5828c2ecf20Sopenharmony_ci BUG(); 5838c2ecf20Sopenharmony_ci } 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci upnout: 5868c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci return ret; 5898c2ecf20Sopenharmony_ci} 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, 5928c2ecf20Sopenharmony_ci struct jffs2_inode_cache *ic, 5938c2ecf20Sopenharmony_ci struct jffs2_raw_node_ref *raw) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci union jffs2_node_union *node; 5968c2ecf20Sopenharmony_ci size_t retlen; 5978c2ecf20Sopenharmony_ci int ret; 5988c2ecf20Sopenharmony_ci uint32_t phys_ofs, alloclen; 5998c2ecf20Sopenharmony_ci uint32_t crc, rawlen; 6008c2ecf20Sopenharmony_ci int retried = 0; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci jffs2_dbg(1, "Going to GC REF_PRISTINE node at 0x%08x\n", 6038c2ecf20Sopenharmony_ci ref_offset(raw)); 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci alloclen = rawlen = ref_totlen(c, c->gcblock, raw); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci /* Ask for a small amount of space (or the totlen if smaller) because we 6088c2ecf20Sopenharmony_ci don't want to force wastage of the end of a block if splitting would 6098c2ecf20Sopenharmony_ci work. */ 6108c2ecf20Sopenharmony_ci if (ic && alloclen > sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) 6118c2ecf20Sopenharmony_ci alloclen = sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci ret = jffs2_reserve_space_gc(c, alloclen, &alloclen, rawlen); 6148c2ecf20Sopenharmony_ci /* 'rawlen' is not the exact summary size; it is only an upper estimation */ 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if (ret) 6178c2ecf20Sopenharmony_ci return ret; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci if (alloclen < rawlen) { 6208c2ecf20Sopenharmony_ci /* Doesn't fit untouched. We'll go the old route and split it */ 6218c2ecf20Sopenharmony_ci return -EBADFD; 6228c2ecf20Sopenharmony_ci } 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci node = kmalloc(rawlen, GFP_KERNEL); 6258c2ecf20Sopenharmony_ci if (!node) 6268c2ecf20Sopenharmony_ci return -ENOMEM; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)node); 6298c2ecf20Sopenharmony_ci if (!ret && retlen != rawlen) 6308c2ecf20Sopenharmony_ci ret = -EIO; 6318c2ecf20Sopenharmony_ci if (ret) 6328c2ecf20Sopenharmony_ci goto out_node; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci crc = crc32(0, node, sizeof(struct jffs2_unknown_node)-4); 6358c2ecf20Sopenharmony_ci if (je32_to_cpu(node->u.hdr_crc) != crc) { 6368c2ecf20Sopenharmony_ci pr_warn("Header CRC failed on REF_PRISTINE node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", 6378c2ecf20Sopenharmony_ci ref_offset(raw), je32_to_cpu(node->u.hdr_crc), crc); 6388c2ecf20Sopenharmony_ci goto bail; 6398c2ecf20Sopenharmony_ci } 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci switch(je16_to_cpu(node->u.nodetype)) { 6428c2ecf20Sopenharmony_ci case JFFS2_NODETYPE_INODE: 6438c2ecf20Sopenharmony_ci crc = crc32(0, node, sizeof(node->i)-8); 6448c2ecf20Sopenharmony_ci if (je32_to_cpu(node->i.node_crc) != crc) { 6458c2ecf20Sopenharmony_ci pr_warn("Node CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", 6468c2ecf20Sopenharmony_ci ref_offset(raw), je32_to_cpu(node->i.node_crc), 6478c2ecf20Sopenharmony_ci crc); 6488c2ecf20Sopenharmony_ci goto bail; 6498c2ecf20Sopenharmony_ci } 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci if (je32_to_cpu(node->i.dsize)) { 6528c2ecf20Sopenharmony_ci crc = crc32(0, node->i.data, je32_to_cpu(node->i.csize)); 6538c2ecf20Sopenharmony_ci if (je32_to_cpu(node->i.data_crc) != crc) { 6548c2ecf20Sopenharmony_ci pr_warn("Data CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", 6558c2ecf20Sopenharmony_ci ref_offset(raw), 6568c2ecf20Sopenharmony_ci je32_to_cpu(node->i.data_crc), crc); 6578c2ecf20Sopenharmony_ci goto bail; 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci break; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci case JFFS2_NODETYPE_DIRENT: 6638c2ecf20Sopenharmony_ci crc = crc32(0, node, sizeof(node->d)-8); 6648c2ecf20Sopenharmony_ci if (je32_to_cpu(node->d.node_crc) != crc) { 6658c2ecf20Sopenharmony_ci pr_warn("Node CRC failed on REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", 6668c2ecf20Sopenharmony_ci ref_offset(raw), 6678c2ecf20Sopenharmony_ci je32_to_cpu(node->d.node_crc), crc); 6688c2ecf20Sopenharmony_ci goto bail; 6698c2ecf20Sopenharmony_ci } 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci if (strnlen(node->d.name, node->d.nsize) != node->d.nsize) { 6728c2ecf20Sopenharmony_ci pr_warn("Name in dirent node at 0x%08x contains zeroes\n", 6738c2ecf20Sopenharmony_ci ref_offset(raw)); 6748c2ecf20Sopenharmony_ci goto bail; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci if (node->d.nsize) { 6788c2ecf20Sopenharmony_ci crc = crc32(0, node->d.name, node->d.nsize); 6798c2ecf20Sopenharmony_ci if (je32_to_cpu(node->d.name_crc) != crc) { 6808c2ecf20Sopenharmony_ci pr_warn("Name CRC failed on REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", 6818c2ecf20Sopenharmony_ci ref_offset(raw), 6828c2ecf20Sopenharmony_ci je32_to_cpu(node->d.name_crc), crc); 6838c2ecf20Sopenharmony_ci goto bail; 6848c2ecf20Sopenharmony_ci } 6858c2ecf20Sopenharmony_ci } 6868c2ecf20Sopenharmony_ci break; 6878c2ecf20Sopenharmony_ci default: 6888c2ecf20Sopenharmony_ci /* If it's inode-less, we don't _know_ what it is. Just copy it intact */ 6898c2ecf20Sopenharmony_ci if (ic) { 6908c2ecf20Sopenharmony_ci pr_warn("Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", 6918c2ecf20Sopenharmony_ci ref_offset(raw), je16_to_cpu(node->u.nodetype)); 6928c2ecf20Sopenharmony_ci goto bail; 6938c2ecf20Sopenharmony_ci } 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci /* OK, all the CRCs are good; this node can just be copied as-is. */ 6978c2ecf20Sopenharmony_ci retry: 6988c2ecf20Sopenharmony_ci phys_ofs = write_ofs(c); 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci if (ret || (retlen != rawlen)) { 7038c2ecf20Sopenharmony_ci pr_notice("Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", 7048c2ecf20Sopenharmony_ci rawlen, phys_ofs, ret, retlen); 7058c2ecf20Sopenharmony_ci if (retlen) { 7068c2ecf20Sopenharmony_ci jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL); 7078c2ecf20Sopenharmony_ci } else { 7088c2ecf20Sopenharmony_ci pr_notice("Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", 7098c2ecf20Sopenharmony_ci phys_ofs); 7108c2ecf20Sopenharmony_ci } 7118c2ecf20Sopenharmony_ci if (!retried) { 7128c2ecf20Sopenharmony_ci /* Try to reallocate space and retry */ 7138c2ecf20Sopenharmony_ci uint32_t dummy; 7148c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size]; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci retried = 1; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci jffs2_dbg(1, "Retrying failed write of REF_PRISTINE node.\n"); 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci jffs2_dbg_acct_sanity_check(c,jeb); 7218c2ecf20Sopenharmony_ci jffs2_dbg_acct_paranoia_check(c, jeb); 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci ret = jffs2_reserve_space_gc(c, rawlen, &dummy, rawlen); 7248c2ecf20Sopenharmony_ci /* this is not the exact summary size of it, 7258c2ecf20Sopenharmony_ci it is only an upper estimation */ 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci if (!ret) { 7288c2ecf20Sopenharmony_ci jffs2_dbg(1, "Allocated space at 0x%08x to retry failed write.\n", 7298c2ecf20Sopenharmony_ci phys_ofs); 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci jffs2_dbg_acct_sanity_check(c,jeb); 7328c2ecf20Sopenharmony_ci jffs2_dbg_acct_paranoia_check(c, jeb); 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci goto retry; 7358c2ecf20Sopenharmony_ci } 7368c2ecf20Sopenharmony_ci jffs2_dbg(1, "Failed to allocate space to retry failed write: %d!\n", 7378c2ecf20Sopenharmony_ci ret); 7388c2ecf20Sopenharmony_ci } 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci if (!ret) 7418c2ecf20Sopenharmony_ci ret = -EIO; 7428c2ecf20Sopenharmony_ci goto out_node; 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, raw); 7478c2ecf20Sopenharmony_ci jffs2_dbg(1, "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", 7488c2ecf20Sopenharmony_ci ref_offset(raw)); 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci out_node: 7518c2ecf20Sopenharmony_ci kfree(node); 7528c2ecf20Sopenharmony_ci return ret; 7538c2ecf20Sopenharmony_ci bail: 7548c2ecf20Sopenharmony_ci ret = -EBADFD; 7558c2ecf20Sopenharmony_ci goto out_node; 7568c2ecf20Sopenharmony_ci} 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 7598c2ecf20Sopenharmony_ci struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) 7608c2ecf20Sopenharmony_ci{ 7618c2ecf20Sopenharmony_ci struct jffs2_full_dnode *new_fn; 7628c2ecf20Sopenharmony_ci struct jffs2_raw_inode ri; 7638c2ecf20Sopenharmony_ci struct jffs2_node_frag *last_frag; 7648c2ecf20Sopenharmony_ci union jffs2_device_node dev; 7658c2ecf20Sopenharmony_ci char *mdata = NULL; 7668c2ecf20Sopenharmony_ci int mdatalen = 0; 7678c2ecf20Sopenharmony_ci uint32_t alloclen, ilen; 7688c2ecf20Sopenharmony_ci int ret; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci if (S_ISBLK(JFFS2_F_I_MODE(f)) || 7718c2ecf20Sopenharmony_ci S_ISCHR(JFFS2_F_I_MODE(f)) ) { 7728c2ecf20Sopenharmony_ci /* For these, we don't actually need to read the old node */ 7738c2ecf20Sopenharmony_ci mdatalen = jffs2_encode_dev(&dev, JFFS2_F_I_RDEV(f)); 7748c2ecf20Sopenharmony_ci mdata = (char *)&dev; 7758c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): Writing %d bytes of kdev_t\n", 7768c2ecf20Sopenharmony_ci __func__, mdatalen); 7778c2ecf20Sopenharmony_ci } else if (S_ISLNK(JFFS2_F_I_MODE(f))) { 7788c2ecf20Sopenharmony_ci mdatalen = fn->size; 7798c2ecf20Sopenharmony_ci mdata = kmalloc(fn->size, GFP_KERNEL); 7808c2ecf20Sopenharmony_ci if (!mdata) { 7818c2ecf20Sopenharmony_ci pr_warn("kmalloc of mdata failed in jffs2_garbage_collect_metadata()\n"); 7828c2ecf20Sopenharmony_ci return -ENOMEM; 7838c2ecf20Sopenharmony_ci } 7848c2ecf20Sopenharmony_ci ret = jffs2_read_dnode(c, f, fn, mdata, 0, mdatalen); 7858c2ecf20Sopenharmony_ci if (ret) { 7868c2ecf20Sopenharmony_ci pr_warn("read of old metadata failed in jffs2_garbage_collect_metadata(): %d\n", 7878c2ecf20Sopenharmony_ci ret); 7888c2ecf20Sopenharmony_ci kfree(mdata); 7898c2ecf20Sopenharmony_ci return ret; 7908c2ecf20Sopenharmony_ci } 7918c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): Writing %d bites of symlink target\n", 7928c2ecf20Sopenharmony_ci __func__, mdatalen); 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci } 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &alloclen, 7978c2ecf20Sopenharmony_ci JFFS2_SUMMARY_INODE_SIZE); 7988c2ecf20Sopenharmony_ci if (ret) { 7998c2ecf20Sopenharmony_ci pr_warn("jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n", 8008c2ecf20Sopenharmony_ci sizeof(ri) + mdatalen, ret); 8018c2ecf20Sopenharmony_ci goto out; 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci last_frag = frag_last(&f->fragtree); 8058c2ecf20Sopenharmony_ci if (last_frag) 8068c2ecf20Sopenharmony_ci /* Fetch the inode length from the fragtree rather then 8078c2ecf20Sopenharmony_ci * from i_size since i_size may have not been updated yet */ 8088c2ecf20Sopenharmony_ci ilen = last_frag->ofs + last_frag->size; 8098c2ecf20Sopenharmony_ci else 8108c2ecf20Sopenharmony_ci ilen = JFFS2_F_I_SIZE(f); 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci memset(&ri, 0, sizeof(ri)); 8138c2ecf20Sopenharmony_ci ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 8148c2ecf20Sopenharmony_ci ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); 8158c2ecf20Sopenharmony_ci ri.totlen = cpu_to_je32(sizeof(ri) + mdatalen); 8168c2ecf20Sopenharmony_ci ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci ri.ino = cpu_to_je32(f->inocache->ino); 8198c2ecf20Sopenharmony_ci ri.version = cpu_to_je32(++f->highest_version); 8208c2ecf20Sopenharmony_ci ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); 8218c2ecf20Sopenharmony_ci ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); 8228c2ecf20Sopenharmony_ci ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); 8238c2ecf20Sopenharmony_ci ri.isize = cpu_to_je32(ilen); 8248c2ecf20Sopenharmony_ci ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); 8258c2ecf20Sopenharmony_ci ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); 8268c2ecf20Sopenharmony_ci ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); 8278c2ecf20Sopenharmony_ci ri.offset = cpu_to_je32(0); 8288c2ecf20Sopenharmony_ci ri.csize = cpu_to_je32(mdatalen); 8298c2ecf20Sopenharmony_ci ri.dsize = cpu_to_je32(mdatalen); 8308c2ecf20Sopenharmony_ci ri.compr = JFFS2_COMPR_NONE; 8318c2ecf20Sopenharmony_ci ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); 8328c2ecf20Sopenharmony_ci ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, ALLOC_GC); 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci if (IS_ERR(new_fn)) { 8378c2ecf20Sopenharmony_ci pr_warn("Error writing new dnode: %ld\n", PTR_ERR(new_fn)); 8388c2ecf20Sopenharmony_ci ret = PTR_ERR(new_fn); 8398c2ecf20Sopenharmony_ci goto out; 8408c2ecf20Sopenharmony_ci } 8418c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, fn->raw); 8428c2ecf20Sopenharmony_ci jffs2_free_full_dnode(fn); 8438c2ecf20Sopenharmony_ci f->metadata = new_fn; 8448c2ecf20Sopenharmony_ci out: 8458c2ecf20Sopenharmony_ci if (S_ISLNK(JFFS2_F_I_MODE(f))) 8468c2ecf20Sopenharmony_ci kfree(mdata); 8478c2ecf20Sopenharmony_ci return ret; 8488c2ecf20Sopenharmony_ci} 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 8518c2ecf20Sopenharmony_ci struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) 8528c2ecf20Sopenharmony_ci{ 8538c2ecf20Sopenharmony_ci struct jffs2_full_dirent *new_fd; 8548c2ecf20Sopenharmony_ci struct jffs2_raw_dirent rd; 8558c2ecf20Sopenharmony_ci uint32_t alloclen; 8568c2ecf20Sopenharmony_ci int ret; 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 8598c2ecf20Sopenharmony_ci rd.nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); 8608c2ecf20Sopenharmony_ci rd.nsize = strlen(fd->name); 8618c2ecf20Sopenharmony_ci rd.totlen = cpu_to_je32(sizeof(rd) + rd.nsize); 8628c2ecf20Sopenharmony_ci rd.hdr_crc = cpu_to_je32(crc32(0, &rd, sizeof(struct jffs2_unknown_node)-4)); 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci rd.pino = cpu_to_je32(f->inocache->ino); 8658c2ecf20Sopenharmony_ci rd.version = cpu_to_je32(++f->highest_version); 8668c2ecf20Sopenharmony_ci rd.ino = cpu_to_je32(fd->ino); 8678c2ecf20Sopenharmony_ci /* If the times on this inode were set by explicit utime() they can be different, 8688c2ecf20Sopenharmony_ci so refrain from splatting them. */ 8698c2ecf20Sopenharmony_ci if (JFFS2_F_I_MTIME(f) == JFFS2_F_I_CTIME(f)) 8708c2ecf20Sopenharmony_ci rd.mctime = cpu_to_je32(JFFS2_F_I_MTIME(f)); 8718c2ecf20Sopenharmony_ci else 8728c2ecf20Sopenharmony_ci rd.mctime = cpu_to_je32(0); 8738c2ecf20Sopenharmony_ci rd.type = fd->type; 8748c2ecf20Sopenharmony_ci rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); 8758c2ecf20Sopenharmony_ci rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &alloclen, 8788c2ecf20Sopenharmony_ci JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize)); 8798c2ecf20Sopenharmony_ci if (ret) { 8808c2ecf20Sopenharmony_ci pr_warn("jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n", 8818c2ecf20Sopenharmony_ci sizeof(rd)+rd.nsize, ret); 8828c2ecf20Sopenharmony_ci return ret; 8838c2ecf20Sopenharmony_ci } 8848c2ecf20Sopenharmony_ci new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, ALLOC_GC); 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci if (IS_ERR(new_fd)) { 8878c2ecf20Sopenharmony_ci pr_warn("jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", 8888c2ecf20Sopenharmony_ci PTR_ERR(new_fd)); 8898c2ecf20Sopenharmony_ci return PTR_ERR(new_fd); 8908c2ecf20Sopenharmony_ci } 8918c2ecf20Sopenharmony_ci jffs2_add_fd_to_list(c, new_fd, &f->dents); 8928c2ecf20Sopenharmony_ci return 0; 8938c2ecf20Sopenharmony_ci} 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 8968c2ecf20Sopenharmony_ci struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) 8978c2ecf20Sopenharmony_ci{ 8988c2ecf20Sopenharmony_ci struct jffs2_full_dirent **fdp = &f->dents; 8998c2ecf20Sopenharmony_ci int found = 0; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci /* On a medium where we can't actually mark nodes obsolete 9028c2ecf20Sopenharmony_ci pernamently, such as NAND flash, we need to work out 9038c2ecf20Sopenharmony_ci whether this deletion dirent is still needed to actively 9048c2ecf20Sopenharmony_ci delete a 'real' dirent with the same name that's still 9058c2ecf20Sopenharmony_ci somewhere else on the flash. */ 9068c2ecf20Sopenharmony_ci if (!jffs2_can_mark_obsolete(c)) { 9078c2ecf20Sopenharmony_ci struct jffs2_raw_dirent *rd; 9088c2ecf20Sopenharmony_ci struct jffs2_raw_node_ref *raw; 9098c2ecf20Sopenharmony_ci int ret; 9108c2ecf20Sopenharmony_ci size_t retlen; 9118c2ecf20Sopenharmony_ci int name_len = strlen(fd->name); 9128c2ecf20Sopenharmony_ci uint32_t name_crc = crc32(0, fd->name, name_len); 9138c2ecf20Sopenharmony_ci uint32_t rawlen = ref_totlen(c, jeb, fd->raw); 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci rd = kmalloc(rawlen, GFP_KERNEL); 9168c2ecf20Sopenharmony_ci if (!rd) 9178c2ecf20Sopenharmony_ci return -ENOMEM; 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci /* Prevent the erase code from nicking the obsolete node refs while 9208c2ecf20Sopenharmony_ci we're looking at them. I really don't like this extra lock but 9218c2ecf20Sopenharmony_ci can't see any alternative. Suggestions on a postcard to... */ 9228c2ecf20Sopenharmony_ci mutex_lock(&c->erase_free_sem); 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) { 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci cond_resched(); 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci /* We only care about obsolete ones */ 9298c2ecf20Sopenharmony_ci if (!(ref_obsolete(raw))) 9308c2ecf20Sopenharmony_ci continue; 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci /* Any dirent with the same name is going to have the same length... */ 9338c2ecf20Sopenharmony_ci if (ref_totlen(c, NULL, raw) != rawlen) 9348c2ecf20Sopenharmony_ci continue; 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci /* Doesn't matter if there's one in the same erase block. We're going to 9378c2ecf20Sopenharmony_ci delete it too at the same time. */ 9388c2ecf20Sopenharmony_ci if (SECTOR_ADDR(raw->flash_offset) == SECTOR_ADDR(fd->raw->flash_offset)) 9398c2ecf20Sopenharmony_ci continue; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci jffs2_dbg(1, "Check potential deletion dirent at %08x\n", 9428c2ecf20Sopenharmony_ci ref_offset(raw)); 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci /* This is an obsolete node belonging to the same directory, and it's of the right 9458c2ecf20Sopenharmony_ci length. We need to take a closer look...*/ 9468c2ecf20Sopenharmony_ci ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)rd); 9478c2ecf20Sopenharmony_ci if (ret) { 9488c2ecf20Sopenharmony_ci pr_warn("%s(): Read error (%d) reading obsolete node at %08x\n", 9498c2ecf20Sopenharmony_ci __func__, ret, ref_offset(raw)); 9508c2ecf20Sopenharmony_ci /* If we can't read it, we don't need to continue to obsolete it. Continue */ 9518c2ecf20Sopenharmony_ci continue; 9528c2ecf20Sopenharmony_ci } 9538c2ecf20Sopenharmony_ci if (retlen != rawlen) { 9548c2ecf20Sopenharmony_ci pr_warn("%s(): Short read (%zd not %u) reading header from obsolete node at %08x\n", 9558c2ecf20Sopenharmony_ci __func__, retlen, rawlen, 9568c2ecf20Sopenharmony_ci ref_offset(raw)); 9578c2ecf20Sopenharmony_ci continue; 9588c2ecf20Sopenharmony_ci } 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci if (je16_to_cpu(rd->nodetype) != JFFS2_NODETYPE_DIRENT) 9618c2ecf20Sopenharmony_ci continue; 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci /* If the name CRC doesn't match, skip */ 9648c2ecf20Sopenharmony_ci if (je32_to_cpu(rd->name_crc) != name_crc) 9658c2ecf20Sopenharmony_ci continue; 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci /* If the name length doesn't match, or it's another deletion dirent, skip */ 9688c2ecf20Sopenharmony_ci if (rd->nsize != name_len || !je32_to_cpu(rd->ino)) 9698c2ecf20Sopenharmony_ci continue; 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci /* OK, check the actual name now */ 9728c2ecf20Sopenharmony_ci if (memcmp(rd->name, fd->name, name_len)) 9738c2ecf20Sopenharmony_ci continue; 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci /* OK. The name really does match. There really is still an older node on 9768c2ecf20Sopenharmony_ci the flash which our deletion dirent obsoletes. So we have to write out 9778c2ecf20Sopenharmony_ci a new deletion dirent to replace it */ 9788c2ecf20Sopenharmony_ci mutex_unlock(&c->erase_free_sem); 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci jffs2_dbg(1, "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n", 9818c2ecf20Sopenharmony_ci ref_offset(fd->raw), fd->name, 9828c2ecf20Sopenharmony_ci ref_offset(raw), je32_to_cpu(rd->ino)); 9838c2ecf20Sopenharmony_ci kfree(rd); 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci return jffs2_garbage_collect_dirent(c, jeb, f, fd); 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci mutex_unlock(&c->erase_free_sem); 9898c2ecf20Sopenharmony_ci kfree(rd); 9908c2ecf20Sopenharmony_ci } 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci /* FIXME: If we're deleting a dirent which contains the current mtime and ctime, 9938c2ecf20Sopenharmony_ci we should update the metadata node with those times accordingly */ 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci /* No need for it any more. Just mark it obsolete and remove it from the list */ 9968c2ecf20Sopenharmony_ci while (*fdp) { 9978c2ecf20Sopenharmony_ci if ((*fdp) == fd) { 9988c2ecf20Sopenharmony_ci found = 1; 9998c2ecf20Sopenharmony_ci *fdp = fd->next; 10008c2ecf20Sopenharmony_ci break; 10018c2ecf20Sopenharmony_ci } 10028c2ecf20Sopenharmony_ci fdp = &(*fdp)->next; 10038c2ecf20Sopenharmony_ci } 10048c2ecf20Sopenharmony_ci if (!found) { 10058c2ecf20Sopenharmony_ci pr_warn("Deletion dirent \"%s\" not found in list for ino #%u\n", 10068c2ecf20Sopenharmony_ci fd->name, f->inocache->ino); 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, fd->raw); 10098c2ecf20Sopenharmony_ci jffs2_free_full_dirent(fd); 10108c2ecf20Sopenharmony_ci return 0; 10118c2ecf20Sopenharmony_ci} 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 10148c2ecf20Sopenharmony_ci struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, 10158c2ecf20Sopenharmony_ci uint32_t start, uint32_t end) 10168c2ecf20Sopenharmony_ci{ 10178c2ecf20Sopenharmony_ci struct jffs2_raw_inode ri; 10188c2ecf20Sopenharmony_ci struct jffs2_node_frag *frag; 10198c2ecf20Sopenharmony_ci struct jffs2_full_dnode *new_fn; 10208c2ecf20Sopenharmony_ci uint32_t alloclen, ilen; 10218c2ecf20Sopenharmony_ci int ret; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci jffs2_dbg(1, "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n", 10248c2ecf20Sopenharmony_ci f->inocache->ino, start, end); 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci memset(&ri, 0, sizeof(ri)); 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci if(fn->frags > 1) { 10298c2ecf20Sopenharmony_ci size_t readlen; 10308c2ecf20Sopenharmony_ci uint32_t crc; 10318c2ecf20Sopenharmony_ci /* It's partially obsoleted by a later write. So we have to 10328c2ecf20Sopenharmony_ci write it out again with the _same_ version as before */ 10338c2ecf20Sopenharmony_ci ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(ri), &readlen, (char *)&ri); 10348c2ecf20Sopenharmony_ci if (readlen != sizeof(ri) || ret) { 10358c2ecf20Sopenharmony_ci pr_warn("Node read failed in jffs2_garbage_collect_hole. Ret %d, retlen %zd. Data will be lost by writing new hole node\n", 10368c2ecf20Sopenharmony_ci ret, readlen); 10378c2ecf20Sopenharmony_ci goto fill; 10388c2ecf20Sopenharmony_ci } 10398c2ecf20Sopenharmony_ci if (je16_to_cpu(ri.nodetype) != JFFS2_NODETYPE_INODE) { 10408c2ecf20Sopenharmony_ci pr_warn("%s(): Node at 0x%08x had node type 0x%04x instead of JFFS2_NODETYPE_INODE(0x%04x)\n", 10418c2ecf20Sopenharmony_ci __func__, ref_offset(fn->raw), 10428c2ecf20Sopenharmony_ci je16_to_cpu(ri.nodetype), JFFS2_NODETYPE_INODE); 10438c2ecf20Sopenharmony_ci return -EIO; 10448c2ecf20Sopenharmony_ci } 10458c2ecf20Sopenharmony_ci if (je32_to_cpu(ri.totlen) != sizeof(ri)) { 10468c2ecf20Sopenharmony_ci pr_warn("%s(): Node at 0x%08x had totlen 0x%x instead of expected 0x%zx\n", 10478c2ecf20Sopenharmony_ci __func__, ref_offset(fn->raw), 10488c2ecf20Sopenharmony_ci je32_to_cpu(ri.totlen), sizeof(ri)); 10498c2ecf20Sopenharmony_ci return -EIO; 10508c2ecf20Sopenharmony_ci } 10518c2ecf20Sopenharmony_ci crc = crc32(0, &ri, sizeof(ri)-8); 10528c2ecf20Sopenharmony_ci if (crc != je32_to_cpu(ri.node_crc)) { 10538c2ecf20Sopenharmony_ci pr_warn("%s: Node at 0x%08x had CRC 0x%08x which doesn't match calculated CRC 0x%08x\n", 10548c2ecf20Sopenharmony_ci __func__, ref_offset(fn->raw), 10558c2ecf20Sopenharmony_ci je32_to_cpu(ri.node_crc), crc); 10568c2ecf20Sopenharmony_ci /* FIXME: We could possibly deal with this by writing new holes for each frag */ 10578c2ecf20Sopenharmony_ci pr_warn("Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", 10588c2ecf20Sopenharmony_ci start, end, f->inocache->ino); 10598c2ecf20Sopenharmony_ci goto fill; 10608c2ecf20Sopenharmony_ci } 10618c2ecf20Sopenharmony_ci if (ri.compr != JFFS2_COMPR_ZERO) { 10628c2ecf20Sopenharmony_ci pr_warn("%s(): Node 0x%08x wasn't a hole node!\n", 10638c2ecf20Sopenharmony_ci __func__, ref_offset(fn->raw)); 10648c2ecf20Sopenharmony_ci pr_warn("Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", 10658c2ecf20Sopenharmony_ci start, end, f->inocache->ino); 10668c2ecf20Sopenharmony_ci goto fill; 10678c2ecf20Sopenharmony_ci } 10688c2ecf20Sopenharmony_ci } else { 10698c2ecf20Sopenharmony_ci fill: 10708c2ecf20Sopenharmony_ci ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 10718c2ecf20Sopenharmony_ci ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); 10728c2ecf20Sopenharmony_ci ri.totlen = cpu_to_je32(sizeof(ri)); 10738c2ecf20Sopenharmony_ci ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci ri.ino = cpu_to_je32(f->inocache->ino); 10768c2ecf20Sopenharmony_ci ri.version = cpu_to_je32(++f->highest_version); 10778c2ecf20Sopenharmony_ci ri.offset = cpu_to_je32(start); 10788c2ecf20Sopenharmony_ci ri.dsize = cpu_to_je32(end - start); 10798c2ecf20Sopenharmony_ci ri.csize = cpu_to_je32(0); 10808c2ecf20Sopenharmony_ci ri.compr = JFFS2_COMPR_ZERO; 10818c2ecf20Sopenharmony_ci } 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci frag = frag_last(&f->fragtree); 10848c2ecf20Sopenharmony_ci if (frag) 10858c2ecf20Sopenharmony_ci /* Fetch the inode length from the fragtree rather then 10868c2ecf20Sopenharmony_ci * from i_size since i_size may have not been updated yet */ 10878c2ecf20Sopenharmony_ci ilen = frag->ofs + frag->size; 10888c2ecf20Sopenharmony_ci else 10898c2ecf20Sopenharmony_ci ilen = JFFS2_F_I_SIZE(f); 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); 10928c2ecf20Sopenharmony_ci ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); 10938c2ecf20Sopenharmony_ci ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); 10948c2ecf20Sopenharmony_ci ri.isize = cpu_to_je32(ilen); 10958c2ecf20Sopenharmony_ci ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); 10968c2ecf20Sopenharmony_ci ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); 10978c2ecf20Sopenharmony_ci ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); 10988c2ecf20Sopenharmony_ci ri.data_crc = cpu_to_je32(0); 10998c2ecf20Sopenharmony_ci ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci ret = jffs2_reserve_space_gc(c, sizeof(ri), &alloclen, 11028c2ecf20Sopenharmony_ci JFFS2_SUMMARY_INODE_SIZE); 11038c2ecf20Sopenharmony_ci if (ret) { 11048c2ecf20Sopenharmony_ci pr_warn("jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n", 11058c2ecf20Sopenharmony_ci sizeof(ri), ret); 11068c2ecf20Sopenharmony_ci return ret; 11078c2ecf20Sopenharmony_ci } 11088c2ecf20Sopenharmony_ci new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_GC); 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci if (IS_ERR(new_fn)) { 11118c2ecf20Sopenharmony_ci pr_warn("Error writing new hole node: %ld\n", PTR_ERR(new_fn)); 11128c2ecf20Sopenharmony_ci return PTR_ERR(new_fn); 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci if (je32_to_cpu(ri.version) == f->highest_version) { 11158c2ecf20Sopenharmony_ci jffs2_add_full_dnode_to_inode(c, f, new_fn); 11168c2ecf20Sopenharmony_ci if (f->metadata) { 11178c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, f->metadata->raw); 11188c2ecf20Sopenharmony_ci jffs2_free_full_dnode(f->metadata); 11198c2ecf20Sopenharmony_ci f->metadata = NULL; 11208c2ecf20Sopenharmony_ci } 11218c2ecf20Sopenharmony_ci return 0; 11228c2ecf20Sopenharmony_ci } 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci /* 11258c2ecf20Sopenharmony_ci * We should only get here in the case where the node we are 11268c2ecf20Sopenharmony_ci * replacing had more than one frag, so we kept the same version 11278c2ecf20Sopenharmony_ci * number as before. (Except in case of error -- see 'goto fill;' 11288c2ecf20Sopenharmony_ci * above.) 11298c2ecf20Sopenharmony_ci */ 11308c2ecf20Sopenharmony_ci D1(if(unlikely(fn->frags <= 1)) { 11318c2ecf20Sopenharmony_ci pr_warn("%s(): Replacing fn with %d frag(s) but new ver %d != highest_version %d of ino #%d\n", 11328c2ecf20Sopenharmony_ci __func__, fn->frags, je32_to_cpu(ri.version), 11338c2ecf20Sopenharmony_ci f->highest_version, je32_to_cpu(ri.ino)); 11348c2ecf20Sopenharmony_ci }); 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci /* This is a partially-overlapped hole node. Mark it REF_NORMAL not REF_PRISTINE */ 11378c2ecf20Sopenharmony_ci mark_ref_normal(new_fn->raw); 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs); 11408c2ecf20Sopenharmony_ci frag; frag = frag_next(frag)) { 11418c2ecf20Sopenharmony_ci if (frag->ofs > fn->size + fn->ofs) 11428c2ecf20Sopenharmony_ci break; 11438c2ecf20Sopenharmony_ci if (frag->node == fn) { 11448c2ecf20Sopenharmony_ci frag->node = new_fn; 11458c2ecf20Sopenharmony_ci new_fn->frags++; 11468c2ecf20Sopenharmony_ci fn->frags--; 11478c2ecf20Sopenharmony_ci } 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci if (fn->frags) { 11508c2ecf20Sopenharmony_ci pr_warn("%s(): Old node still has frags!\n", __func__); 11518c2ecf20Sopenharmony_ci BUG(); 11528c2ecf20Sopenharmony_ci } 11538c2ecf20Sopenharmony_ci if (!new_fn->frags) { 11548c2ecf20Sopenharmony_ci pr_warn("%s(): New node has no frags!\n", __func__); 11558c2ecf20Sopenharmony_ci BUG(); 11568c2ecf20Sopenharmony_ci } 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, fn->raw); 11598c2ecf20Sopenharmony_ci jffs2_free_full_dnode(fn); 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci return 0; 11628c2ecf20Sopenharmony_ci} 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_cistatic int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *orig_jeb, 11658c2ecf20Sopenharmony_ci struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, 11668c2ecf20Sopenharmony_ci uint32_t start, uint32_t end) 11678c2ecf20Sopenharmony_ci{ 11688c2ecf20Sopenharmony_ci struct inode *inode = OFNI_EDONI_2SFFJ(f); 11698c2ecf20Sopenharmony_ci struct jffs2_full_dnode *new_fn; 11708c2ecf20Sopenharmony_ci struct jffs2_raw_inode ri; 11718c2ecf20Sopenharmony_ci uint32_t alloclen, offset, orig_end, orig_start; 11728c2ecf20Sopenharmony_ci int ret = 0; 11738c2ecf20Sopenharmony_ci unsigned char *comprbuf = NULL, *writebuf; 11748c2ecf20Sopenharmony_ci struct page *page; 11758c2ecf20Sopenharmony_ci unsigned char *pg_ptr; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci memset(&ri, 0, sizeof(ri)); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci jffs2_dbg(1, "Writing replacement dnode for ino #%u from offset 0x%x to 0x%x\n", 11808c2ecf20Sopenharmony_ci f->inocache->ino, start, end); 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci orig_end = end; 11838c2ecf20Sopenharmony_ci orig_start = start; 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci if (c->nr_free_blocks + c->nr_erasing_blocks > c->resv_blocks_gcmerge) { 11868c2ecf20Sopenharmony_ci /* Attempt to do some merging. But only expand to cover logically 11878c2ecf20Sopenharmony_ci adjacent frags if the block containing them is already considered 11888c2ecf20Sopenharmony_ci to be dirty. Otherwise we end up with GC just going round in 11898c2ecf20Sopenharmony_ci circles dirtying the nodes it already wrote out, especially 11908c2ecf20Sopenharmony_ci on NAND where we have small eraseblocks and hence a much higher 11918c2ecf20Sopenharmony_ci chance of nodes having to be split to cross boundaries. */ 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci struct jffs2_node_frag *frag; 11948c2ecf20Sopenharmony_ci uint32_t min, max; 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci min = start & ~(PAGE_SIZE-1); 11978c2ecf20Sopenharmony_ci max = min + PAGE_SIZE; 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci frag = jffs2_lookup_node_frag(&f->fragtree, start); 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci /* BUG_ON(!frag) but that'll happen anyway... */ 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci BUG_ON(frag->ofs != start); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci /* First grow down... */ 12068c2ecf20Sopenharmony_ci while((frag = frag_prev(frag)) && frag->ofs >= min) { 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci /* If the previous frag doesn't even reach the beginning, there's 12098c2ecf20Sopenharmony_ci excessive fragmentation. Just merge. */ 12108c2ecf20Sopenharmony_ci if (frag->ofs > min) { 12118c2ecf20Sopenharmony_ci jffs2_dbg(1, "Expanding down to cover partial frag (0x%x-0x%x)\n", 12128c2ecf20Sopenharmony_ci frag->ofs, frag->ofs+frag->size); 12138c2ecf20Sopenharmony_ci start = frag->ofs; 12148c2ecf20Sopenharmony_ci continue; 12158c2ecf20Sopenharmony_ci } 12168c2ecf20Sopenharmony_ci /* OK. This frag holds the first byte of the page. */ 12178c2ecf20Sopenharmony_ci if (!frag->node || !frag->node->raw) { 12188c2ecf20Sopenharmony_ci jffs2_dbg(1, "First frag in page is hole (0x%x-0x%x). Not expanding down.\n", 12198c2ecf20Sopenharmony_ci frag->ofs, frag->ofs+frag->size); 12208c2ecf20Sopenharmony_ci break; 12218c2ecf20Sopenharmony_ci } else { 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci /* OK, it's a frag which extends to the beginning of the page. Does it live 12248c2ecf20Sopenharmony_ci in a block which is still considered clean? If so, don't obsolete it. 12258c2ecf20Sopenharmony_ci If not, cover it anyway. */ 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci struct jffs2_raw_node_ref *raw = frag->node->raw; 12288c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb; 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci jeb = &c->blocks[raw->flash_offset / c->sector_size]; 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci if (jeb == c->gcblock) { 12338c2ecf20Sopenharmony_ci jffs2_dbg(1, "Expanding down to cover frag (0x%x-0x%x) in gcblock at %08x\n", 12348c2ecf20Sopenharmony_ci frag->ofs, 12358c2ecf20Sopenharmony_ci frag->ofs + frag->size, 12368c2ecf20Sopenharmony_ci ref_offset(raw)); 12378c2ecf20Sopenharmony_ci start = frag->ofs; 12388c2ecf20Sopenharmony_ci break; 12398c2ecf20Sopenharmony_ci } 12408c2ecf20Sopenharmony_ci if (!ISDIRTY(jeb->dirty_size + jeb->wasted_size)) { 12418c2ecf20Sopenharmony_ci jffs2_dbg(1, "Not expanding down to cover frag (0x%x-0x%x) in clean block %08x\n", 12428c2ecf20Sopenharmony_ci frag->ofs, 12438c2ecf20Sopenharmony_ci frag->ofs + frag->size, 12448c2ecf20Sopenharmony_ci jeb->offset); 12458c2ecf20Sopenharmony_ci break; 12468c2ecf20Sopenharmony_ci } 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci jffs2_dbg(1, "Expanding down to cover frag (0x%x-0x%x) in dirty block %08x\n", 12498c2ecf20Sopenharmony_ci frag->ofs, 12508c2ecf20Sopenharmony_ci frag->ofs + frag->size, 12518c2ecf20Sopenharmony_ci jeb->offset); 12528c2ecf20Sopenharmony_ci start = frag->ofs; 12538c2ecf20Sopenharmony_ci break; 12548c2ecf20Sopenharmony_ci } 12558c2ecf20Sopenharmony_ci } 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci /* ... then up */ 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci /* Find last frag which is actually part of the node we're to GC. */ 12608c2ecf20Sopenharmony_ci frag = jffs2_lookup_node_frag(&f->fragtree, end-1); 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci while((frag = frag_next(frag)) && frag->ofs+frag->size <= max) { 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci /* If the previous frag doesn't even reach the beginning, there's lots 12658c2ecf20Sopenharmony_ci of fragmentation. Just merge. */ 12668c2ecf20Sopenharmony_ci if (frag->ofs+frag->size < max) { 12678c2ecf20Sopenharmony_ci jffs2_dbg(1, "Expanding up to cover partial frag (0x%x-0x%x)\n", 12688c2ecf20Sopenharmony_ci frag->ofs, frag->ofs+frag->size); 12698c2ecf20Sopenharmony_ci end = frag->ofs + frag->size; 12708c2ecf20Sopenharmony_ci continue; 12718c2ecf20Sopenharmony_ci } 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci if (!frag->node || !frag->node->raw) { 12748c2ecf20Sopenharmony_ci jffs2_dbg(1, "Last frag in page is hole (0x%x-0x%x). Not expanding up.\n", 12758c2ecf20Sopenharmony_ci frag->ofs, frag->ofs+frag->size); 12768c2ecf20Sopenharmony_ci break; 12778c2ecf20Sopenharmony_ci } else { 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci /* OK, it's a frag which extends to the beginning of the page. Does it live 12808c2ecf20Sopenharmony_ci in a block which is still considered clean? If so, don't obsolete it. 12818c2ecf20Sopenharmony_ci If not, cover it anyway. */ 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci struct jffs2_raw_node_ref *raw = frag->node->raw; 12848c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb; 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci jeb = &c->blocks[raw->flash_offset / c->sector_size]; 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci if (jeb == c->gcblock) { 12898c2ecf20Sopenharmony_ci jffs2_dbg(1, "Expanding up to cover frag (0x%x-0x%x) in gcblock at %08x\n", 12908c2ecf20Sopenharmony_ci frag->ofs, 12918c2ecf20Sopenharmony_ci frag->ofs + frag->size, 12928c2ecf20Sopenharmony_ci ref_offset(raw)); 12938c2ecf20Sopenharmony_ci end = frag->ofs + frag->size; 12948c2ecf20Sopenharmony_ci break; 12958c2ecf20Sopenharmony_ci } 12968c2ecf20Sopenharmony_ci if (!ISDIRTY(jeb->dirty_size + jeb->wasted_size)) { 12978c2ecf20Sopenharmony_ci jffs2_dbg(1, "Not expanding up to cover frag (0x%x-0x%x) in clean block %08x\n", 12988c2ecf20Sopenharmony_ci frag->ofs, 12998c2ecf20Sopenharmony_ci frag->ofs + frag->size, 13008c2ecf20Sopenharmony_ci jeb->offset); 13018c2ecf20Sopenharmony_ci break; 13028c2ecf20Sopenharmony_ci } 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci jffs2_dbg(1, "Expanding up to cover frag (0x%x-0x%x) in dirty block %08x\n", 13058c2ecf20Sopenharmony_ci frag->ofs, 13068c2ecf20Sopenharmony_ci frag->ofs + frag->size, 13078c2ecf20Sopenharmony_ci jeb->offset); 13088c2ecf20Sopenharmony_ci end = frag->ofs + frag->size; 13098c2ecf20Sopenharmony_ci break; 13108c2ecf20Sopenharmony_ci } 13118c2ecf20Sopenharmony_ci } 13128c2ecf20Sopenharmony_ci jffs2_dbg(1, "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", 13138c2ecf20Sopenharmony_ci orig_start, orig_end, start, end); 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci D1(BUG_ON(end > frag_last(&f->fragtree)->ofs + frag_last(&f->fragtree)->size)); 13168c2ecf20Sopenharmony_ci BUG_ON(end < orig_end); 13178c2ecf20Sopenharmony_ci BUG_ON(start > orig_start); 13188c2ecf20Sopenharmony_ci } 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci /* The rules state that we must obtain the page lock *before* f->sem, so 13218c2ecf20Sopenharmony_ci * drop f->sem temporarily. Since we also hold c->alloc_sem, nothing's 13228c2ecf20Sopenharmony_ci * actually going to *change* so we're safe; we only allow reading. 13238c2ecf20Sopenharmony_ci * 13248c2ecf20Sopenharmony_ci * It is important to note that jffs2_write_begin() will ensure that its 13258c2ecf20Sopenharmony_ci * page is marked Uptodate before allocating space. That means that if we 13268c2ecf20Sopenharmony_ci * end up here trying to GC the *same* page that jffs2_write_begin() is 13278c2ecf20Sopenharmony_ci * trying to write out, read_cache_page() will not deadlock. */ 13288c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 13298c2ecf20Sopenharmony_ci page = read_cache_page(inode->i_mapping, start >> PAGE_SHIFT, 13308c2ecf20Sopenharmony_ci jffs2_do_readpage_unlock, inode); 13318c2ecf20Sopenharmony_ci if (IS_ERR(page)) { 13328c2ecf20Sopenharmony_ci pr_warn("read_cache_page() returned error: %ld\n", 13338c2ecf20Sopenharmony_ci PTR_ERR(page)); 13348c2ecf20Sopenharmony_ci mutex_lock(&f->sem); 13358c2ecf20Sopenharmony_ci return PTR_ERR(page); 13368c2ecf20Sopenharmony_ci } 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci pg_ptr = kmap(page); 13398c2ecf20Sopenharmony_ci mutex_lock(&f->sem); 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci offset = start; 13428c2ecf20Sopenharmony_ci while(offset < orig_end) { 13438c2ecf20Sopenharmony_ci uint32_t datalen; 13448c2ecf20Sopenharmony_ci uint32_t cdatalen; 13458c2ecf20Sopenharmony_ci uint16_t comprtype = JFFS2_COMPR_NONE; 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, 13488c2ecf20Sopenharmony_ci &alloclen, JFFS2_SUMMARY_INODE_SIZE); 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci if (ret) { 13518c2ecf20Sopenharmony_ci pr_warn("jffs2_reserve_space_gc of %zd bytes for garbage_collect_dnode failed: %d\n", 13528c2ecf20Sopenharmony_ci sizeof(ri) + JFFS2_MIN_DATA_LEN, ret); 13538c2ecf20Sopenharmony_ci break; 13548c2ecf20Sopenharmony_ci } 13558c2ecf20Sopenharmony_ci cdatalen = min_t(uint32_t, alloclen - sizeof(ri), end - offset); 13568c2ecf20Sopenharmony_ci datalen = end - offset; 13578c2ecf20Sopenharmony_ci 13588c2ecf20Sopenharmony_ci writebuf = pg_ptr + (offset & (PAGE_SIZE -1)); 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci comprtype = jffs2_compress(c, f, writebuf, &comprbuf, &datalen, &cdatalen); 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 13638c2ecf20Sopenharmony_ci ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); 13648c2ecf20Sopenharmony_ci ri.totlen = cpu_to_je32(sizeof(ri) + cdatalen); 13658c2ecf20Sopenharmony_ci ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci ri.ino = cpu_to_je32(f->inocache->ino); 13688c2ecf20Sopenharmony_ci ri.version = cpu_to_je32(++f->highest_version); 13698c2ecf20Sopenharmony_ci ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); 13708c2ecf20Sopenharmony_ci ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); 13718c2ecf20Sopenharmony_ci ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); 13728c2ecf20Sopenharmony_ci ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); 13738c2ecf20Sopenharmony_ci ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); 13748c2ecf20Sopenharmony_ci ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); 13758c2ecf20Sopenharmony_ci ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); 13768c2ecf20Sopenharmony_ci ri.offset = cpu_to_je32(offset); 13778c2ecf20Sopenharmony_ci ri.csize = cpu_to_je32(cdatalen); 13788c2ecf20Sopenharmony_ci ri.dsize = cpu_to_je32(datalen); 13798c2ecf20Sopenharmony_ci ri.compr = comprtype & 0xff; 13808c2ecf20Sopenharmony_ci ri.usercompr = (comprtype >> 8) & 0xff; 13818c2ecf20Sopenharmony_ci ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); 13828c2ecf20Sopenharmony_ci ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, ALLOC_GC); 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci jffs2_free_comprbuf(comprbuf, writebuf); 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci if (IS_ERR(new_fn)) { 13898c2ecf20Sopenharmony_ci pr_warn("Error writing new dnode: %ld\n", 13908c2ecf20Sopenharmony_ci PTR_ERR(new_fn)); 13918c2ecf20Sopenharmony_ci ret = PTR_ERR(new_fn); 13928c2ecf20Sopenharmony_ci break; 13938c2ecf20Sopenharmony_ci } 13948c2ecf20Sopenharmony_ci ret = jffs2_add_full_dnode_to_inode(c, f, new_fn); 13958c2ecf20Sopenharmony_ci offset += datalen; 13968c2ecf20Sopenharmony_ci if (f->metadata) { 13978c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, f->metadata->raw); 13988c2ecf20Sopenharmony_ci jffs2_free_full_dnode(f->metadata); 13998c2ecf20Sopenharmony_ci f->metadata = NULL; 14008c2ecf20Sopenharmony_ci } 14018c2ecf20Sopenharmony_ci } 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci kunmap(page); 14048c2ecf20Sopenharmony_ci put_page(page); 14058c2ecf20Sopenharmony_ci return ret; 14068c2ecf20Sopenharmony_ci} 1407