162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This file is part of UBIFS. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2006-2008 Nokia Corporation. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Authors: Adrian Hunter 862306a36Sopenharmony_ci * Artem Bityutskiy (Битюцкий Артём) 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* 1262306a36Sopenharmony_ci * This file implements garbage collection. The procedure for garbage collection 1362306a36Sopenharmony_ci * is different depending on whether a LEB as an index LEB (contains index 1462306a36Sopenharmony_ci * nodes) or not. For non-index LEBs, garbage collection finds a LEB which 1562306a36Sopenharmony_ci * contains a lot of dirty space (obsolete nodes), and copies the non-obsolete 1662306a36Sopenharmony_ci * nodes to the journal, at which point the garbage-collected LEB is free to be 1762306a36Sopenharmony_ci * reused. For index LEBs, garbage collection marks the non-obsolete index nodes 1862306a36Sopenharmony_ci * dirty in the TNC, and after the next commit, the garbage-collected LEB is 1962306a36Sopenharmony_ci * to be reused. Garbage collection will cause the number of dirty index nodes 2062306a36Sopenharmony_ci * to grow, however sufficient space is reserved for the index to ensure the 2162306a36Sopenharmony_ci * commit will never run out of space. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Notes about dead watermark. At current UBIFS implementation we assume that 2462306a36Sopenharmony_ci * LEBs which have less than @c->dead_wm bytes of free + dirty space are full 2562306a36Sopenharmony_ci * and not worth garbage-collecting. The dead watermark is one min. I/O unit 2662306a36Sopenharmony_ci * size, or min. UBIFS node size, depending on what is greater. Indeed, UBIFS 2762306a36Sopenharmony_ci * Garbage Collector has to synchronize the GC head's write buffer before 2862306a36Sopenharmony_ci * returning, so this is about wasting one min. I/O unit. However, UBIFS GC can 2962306a36Sopenharmony_ci * actually reclaim even very small pieces of dirty space by garbage collecting 3062306a36Sopenharmony_ci * enough dirty LEBs, but we do not bother doing this at this implementation. 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * Notes about dark watermark. The results of GC work depends on how big are 3362306a36Sopenharmony_ci * the UBIFS nodes GC deals with. Large nodes make GC waste more space. Indeed, 3462306a36Sopenharmony_ci * if GC move data from LEB A to LEB B and nodes in LEB A are large, GC would 3562306a36Sopenharmony_ci * have to waste large pieces of free space at the end of LEB B, because nodes 3662306a36Sopenharmony_ci * from LEB A would not fit. And the worst situation is when all nodes are of 3762306a36Sopenharmony_ci * maximum size. So dark watermark is the amount of free + dirty space in LEB 3862306a36Sopenharmony_ci * which are guaranteed to be reclaimable. If LEB has less space, the GC might 3962306a36Sopenharmony_ci * be unable to reclaim it. So, LEBs with free + dirty greater than dark 4062306a36Sopenharmony_ci * watermark are "good" LEBs from GC's point of view. The other LEBs are not so 4162306a36Sopenharmony_ci * good, and GC takes extra care when moving them. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#include <linux/slab.h> 4562306a36Sopenharmony_ci#include <linux/pagemap.h> 4662306a36Sopenharmony_ci#include <linux/list_sort.h> 4762306a36Sopenharmony_ci#include "ubifs.h" 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* 5062306a36Sopenharmony_ci * GC may need to move more than one LEB to make progress. The below constants 5162306a36Sopenharmony_ci * define "soft" and "hard" limits on the number of LEBs the garbage collector 5262306a36Sopenharmony_ci * may move. 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_ci#define SOFT_LEBS_LIMIT 4 5562306a36Sopenharmony_ci#define HARD_LEBS_LIMIT 32 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/** 5862306a36Sopenharmony_ci * switch_gc_head - switch the garbage collection journal head. 5962306a36Sopenharmony_ci * @c: UBIFS file-system description object 6062306a36Sopenharmony_ci * 6162306a36Sopenharmony_ci * This function switch the GC head to the next LEB which is reserved in 6262306a36Sopenharmony_ci * @c->gc_lnum. Returns %0 in case of success, %-EAGAIN if commit is required, 6362306a36Sopenharmony_ci * and other negative error code in case of failures. 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_cistatic int switch_gc_head(struct ubifs_info *c) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci int err, gc_lnum = c->gc_lnum; 6862306a36Sopenharmony_ci struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci ubifs_assert(c, gc_lnum != -1); 7162306a36Sopenharmony_ci dbg_gc("switch GC head from LEB %d:%d to LEB %d (waste %d bytes)", 7262306a36Sopenharmony_ci wbuf->lnum, wbuf->offs + wbuf->used, gc_lnum, 7362306a36Sopenharmony_ci c->leb_size - wbuf->offs - wbuf->used); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci err = ubifs_wbuf_sync_nolock(wbuf); 7662306a36Sopenharmony_ci if (err) 7762306a36Sopenharmony_ci return err; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci /* 8062306a36Sopenharmony_ci * The GC write-buffer was synchronized, we may safely unmap 8162306a36Sopenharmony_ci * 'c->gc_lnum'. 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ci err = ubifs_leb_unmap(c, gc_lnum); 8462306a36Sopenharmony_ci if (err) 8562306a36Sopenharmony_ci return err; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci err = ubifs_add_bud_to_log(c, GCHD, gc_lnum, 0); 8862306a36Sopenharmony_ci if (err) 8962306a36Sopenharmony_ci return err; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci c->gc_lnum = -1; 9262306a36Sopenharmony_ci err = ubifs_wbuf_seek_nolock(wbuf, gc_lnum, 0); 9362306a36Sopenharmony_ci return err; 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/** 9762306a36Sopenharmony_ci * data_nodes_cmp - compare 2 data nodes. 9862306a36Sopenharmony_ci * @priv: UBIFS file-system description object 9962306a36Sopenharmony_ci * @a: first data node 10062306a36Sopenharmony_ci * @b: second data node 10162306a36Sopenharmony_ci * 10262306a36Sopenharmony_ci * This function compares data nodes @a and @b. Returns %1 if @a has greater 10362306a36Sopenharmony_ci * inode or block number, and %-1 otherwise. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_cistatic int data_nodes_cmp(void *priv, const struct list_head *a, 10662306a36Sopenharmony_ci const struct list_head *b) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci ino_t inuma, inumb; 10962306a36Sopenharmony_ci struct ubifs_info *c = priv; 11062306a36Sopenharmony_ci struct ubifs_scan_node *sa, *sb; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci cond_resched(); 11362306a36Sopenharmony_ci if (a == b) 11462306a36Sopenharmony_ci return 0; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci sa = list_entry(a, struct ubifs_scan_node, list); 11762306a36Sopenharmony_ci sb = list_entry(b, struct ubifs_scan_node, list); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci ubifs_assert(c, key_type(c, &sa->key) == UBIFS_DATA_KEY); 12062306a36Sopenharmony_ci ubifs_assert(c, key_type(c, &sb->key) == UBIFS_DATA_KEY); 12162306a36Sopenharmony_ci ubifs_assert(c, sa->type == UBIFS_DATA_NODE); 12262306a36Sopenharmony_ci ubifs_assert(c, sb->type == UBIFS_DATA_NODE); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci inuma = key_inum(c, &sa->key); 12562306a36Sopenharmony_ci inumb = key_inum(c, &sb->key); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (inuma == inumb) { 12862306a36Sopenharmony_ci unsigned int blka = key_block(c, &sa->key); 12962306a36Sopenharmony_ci unsigned int blkb = key_block(c, &sb->key); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci if (blka <= blkb) 13262306a36Sopenharmony_ci return -1; 13362306a36Sopenharmony_ci } else if (inuma <= inumb) 13462306a36Sopenharmony_ci return -1; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci return 1; 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci/* 14062306a36Sopenharmony_ci * nondata_nodes_cmp - compare 2 non-data nodes. 14162306a36Sopenharmony_ci * @priv: UBIFS file-system description object 14262306a36Sopenharmony_ci * @a: first node 14362306a36Sopenharmony_ci * @a: second node 14462306a36Sopenharmony_ci * 14562306a36Sopenharmony_ci * This function compares nodes @a and @b. It makes sure that inode nodes go 14662306a36Sopenharmony_ci * first and sorted by length in descending order. Directory entry nodes go 14762306a36Sopenharmony_ci * after inode nodes and are sorted in ascending hash valuer order. 14862306a36Sopenharmony_ci */ 14962306a36Sopenharmony_cistatic int nondata_nodes_cmp(void *priv, const struct list_head *a, 15062306a36Sopenharmony_ci const struct list_head *b) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci ino_t inuma, inumb; 15362306a36Sopenharmony_ci struct ubifs_info *c = priv; 15462306a36Sopenharmony_ci struct ubifs_scan_node *sa, *sb; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci cond_resched(); 15762306a36Sopenharmony_ci if (a == b) 15862306a36Sopenharmony_ci return 0; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci sa = list_entry(a, struct ubifs_scan_node, list); 16162306a36Sopenharmony_ci sb = list_entry(b, struct ubifs_scan_node, list); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci ubifs_assert(c, key_type(c, &sa->key) != UBIFS_DATA_KEY && 16462306a36Sopenharmony_ci key_type(c, &sb->key) != UBIFS_DATA_KEY); 16562306a36Sopenharmony_ci ubifs_assert(c, sa->type != UBIFS_DATA_NODE && 16662306a36Sopenharmony_ci sb->type != UBIFS_DATA_NODE); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* Inodes go before directory entries */ 16962306a36Sopenharmony_ci if (sa->type == UBIFS_INO_NODE) { 17062306a36Sopenharmony_ci if (sb->type == UBIFS_INO_NODE) 17162306a36Sopenharmony_ci return sb->len - sa->len; 17262306a36Sopenharmony_ci return -1; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci if (sb->type == UBIFS_INO_NODE) 17562306a36Sopenharmony_ci return 1; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci ubifs_assert(c, key_type(c, &sa->key) == UBIFS_DENT_KEY || 17862306a36Sopenharmony_ci key_type(c, &sa->key) == UBIFS_XENT_KEY); 17962306a36Sopenharmony_ci ubifs_assert(c, key_type(c, &sb->key) == UBIFS_DENT_KEY || 18062306a36Sopenharmony_ci key_type(c, &sb->key) == UBIFS_XENT_KEY); 18162306a36Sopenharmony_ci ubifs_assert(c, sa->type == UBIFS_DENT_NODE || 18262306a36Sopenharmony_ci sa->type == UBIFS_XENT_NODE); 18362306a36Sopenharmony_ci ubifs_assert(c, sb->type == UBIFS_DENT_NODE || 18462306a36Sopenharmony_ci sb->type == UBIFS_XENT_NODE); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci inuma = key_inum(c, &sa->key); 18762306a36Sopenharmony_ci inumb = key_inum(c, &sb->key); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci if (inuma == inumb) { 19062306a36Sopenharmony_ci uint32_t hasha = key_hash(c, &sa->key); 19162306a36Sopenharmony_ci uint32_t hashb = key_hash(c, &sb->key); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (hasha <= hashb) 19462306a36Sopenharmony_ci return -1; 19562306a36Sopenharmony_ci } else if (inuma <= inumb) 19662306a36Sopenharmony_ci return -1; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci return 1; 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/** 20262306a36Sopenharmony_ci * sort_nodes - sort nodes for GC. 20362306a36Sopenharmony_ci * @c: UBIFS file-system description object 20462306a36Sopenharmony_ci * @sleb: describes nodes to sort and contains the result on exit 20562306a36Sopenharmony_ci * @nondata: contains non-data nodes on exit 20662306a36Sopenharmony_ci * @min: minimum node size is returned here 20762306a36Sopenharmony_ci * 20862306a36Sopenharmony_ci * This function sorts the list of inodes to garbage collect. First of all, it 20962306a36Sopenharmony_ci * kills obsolete nodes and separates data and non-data nodes to the 21062306a36Sopenharmony_ci * @sleb->nodes and @nondata lists correspondingly. 21162306a36Sopenharmony_ci * 21262306a36Sopenharmony_ci * Data nodes are then sorted in block number order - this is important for 21362306a36Sopenharmony_ci * bulk-read; data nodes with lower inode number go before data nodes with 21462306a36Sopenharmony_ci * higher inode number, and data nodes with lower block number go before data 21562306a36Sopenharmony_ci * nodes with higher block number; 21662306a36Sopenharmony_ci * 21762306a36Sopenharmony_ci * Non-data nodes are sorted as follows. 21862306a36Sopenharmony_ci * o First go inode nodes - they are sorted in descending length order. 21962306a36Sopenharmony_ci * o Then go directory entry nodes - they are sorted in hash order, which 22062306a36Sopenharmony_ci * should supposedly optimize 'readdir()'. Direntry nodes with lower parent 22162306a36Sopenharmony_ci * inode number go before direntry nodes with higher parent inode number, 22262306a36Sopenharmony_ci * and direntry nodes with lower name hash values go before direntry nodes 22362306a36Sopenharmony_ci * with higher name hash values. 22462306a36Sopenharmony_ci * 22562306a36Sopenharmony_ci * This function returns zero in case of success and a negative error code in 22662306a36Sopenharmony_ci * case of failure. 22762306a36Sopenharmony_ci */ 22862306a36Sopenharmony_cistatic int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb, 22962306a36Sopenharmony_ci struct list_head *nondata, int *min) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci int err; 23262306a36Sopenharmony_ci struct ubifs_scan_node *snod, *tmp; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci *min = INT_MAX; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* Separate data nodes and non-data nodes */ 23762306a36Sopenharmony_ci list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) { 23862306a36Sopenharmony_ci ubifs_assert(c, snod->type == UBIFS_INO_NODE || 23962306a36Sopenharmony_ci snod->type == UBIFS_DATA_NODE || 24062306a36Sopenharmony_ci snod->type == UBIFS_DENT_NODE || 24162306a36Sopenharmony_ci snod->type == UBIFS_XENT_NODE || 24262306a36Sopenharmony_ci snod->type == UBIFS_TRUN_NODE || 24362306a36Sopenharmony_ci snod->type == UBIFS_AUTH_NODE); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci if (snod->type != UBIFS_INO_NODE && 24662306a36Sopenharmony_ci snod->type != UBIFS_DATA_NODE && 24762306a36Sopenharmony_ci snod->type != UBIFS_DENT_NODE && 24862306a36Sopenharmony_ci snod->type != UBIFS_XENT_NODE) { 24962306a36Sopenharmony_ci /* Probably truncation node, zap it */ 25062306a36Sopenharmony_ci list_del(&snod->list); 25162306a36Sopenharmony_ci kfree(snod); 25262306a36Sopenharmony_ci continue; 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci ubifs_assert(c, key_type(c, &snod->key) == UBIFS_DATA_KEY || 25662306a36Sopenharmony_ci key_type(c, &snod->key) == UBIFS_INO_KEY || 25762306a36Sopenharmony_ci key_type(c, &snod->key) == UBIFS_DENT_KEY || 25862306a36Sopenharmony_ci key_type(c, &snod->key) == UBIFS_XENT_KEY); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci err = ubifs_tnc_has_node(c, &snod->key, 0, sleb->lnum, 26162306a36Sopenharmony_ci snod->offs, 0); 26262306a36Sopenharmony_ci if (err < 0) 26362306a36Sopenharmony_ci return err; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci if (!err) { 26662306a36Sopenharmony_ci /* The node is obsolete, remove it from the list */ 26762306a36Sopenharmony_ci list_del(&snod->list); 26862306a36Sopenharmony_ci kfree(snod); 26962306a36Sopenharmony_ci continue; 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (snod->len < *min) 27362306a36Sopenharmony_ci *min = snod->len; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci if (key_type(c, &snod->key) != UBIFS_DATA_KEY) 27662306a36Sopenharmony_ci list_move_tail(&snod->list, nondata); 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* Sort data and non-data nodes */ 28062306a36Sopenharmony_ci list_sort(c, &sleb->nodes, &data_nodes_cmp); 28162306a36Sopenharmony_ci list_sort(c, nondata, &nondata_nodes_cmp); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci err = dbg_check_data_nodes_order(c, &sleb->nodes); 28462306a36Sopenharmony_ci if (err) 28562306a36Sopenharmony_ci return err; 28662306a36Sopenharmony_ci err = dbg_check_nondata_nodes_order(c, nondata); 28762306a36Sopenharmony_ci if (err) 28862306a36Sopenharmony_ci return err; 28962306a36Sopenharmony_ci return 0; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci/** 29362306a36Sopenharmony_ci * move_node - move a node. 29462306a36Sopenharmony_ci * @c: UBIFS file-system description object 29562306a36Sopenharmony_ci * @sleb: describes the LEB to move nodes from 29662306a36Sopenharmony_ci * @snod: the mode to move 29762306a36Sopenharmony_ci * @wbuf: write-buffer to move node to 29862306a36Sopenharmony_ci * 29962306a36Sopenharmony_ci * This function moves node @snod to @wbuf, changes TNC correspondingly, and 30062306a36Sopenharmony_ci * destroys @snod. Returns zero in case of success and a negative error code in 30162306a36Sopenharmony_ci * case of failure. 30262306a36Sopenharmony_ci */ 30362306a36Sopenharmony_cistatic int move_node(struct ubifs_info *c, struct ubifs_scan_leb *sleb, 30462306a36Sopenharmony_ci struct ubifs_scan_node *snod, struct ubifs_wbuf *wbuf) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci int err, new_lnum = wbuf->lnum, new_offs = wbuf->offs + wbuf->used; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci cond_resched(); 30962306a36Sopenharmony_ci err = ubifs_wbuf_write_nolock(wbuf, snod->node, snod->len); 31062306a36Sopenharmony_ci if (err) 31162306a36Sopenharmony_ci return err; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci err = ubifs_tnc_replace(c, &snod->key, sleb->lnum, 31462306a36Sopenharmony_ci snod->offs, new_lnum, new_offs, 31562306a36Sopenharmony_ci snod->len); 31662306a36Sopenharmony_ci list_del(&snod->list); 31762306a36Sopenharmony_ci kfree(snod); 31862306a36Sopenharmony_ci return err; 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci/** 32262306a36Sopenharmony_ci * move_nodes - move nodes. 32362306a36Sopenharmony_ci * @c: UBIFS file-system description object 32462306a36Sopenharmony_ci * @sleb: describes the LEB to move nodes from 32562306a36Sopenharmony_ci * 32662306a36Sopenharmony_ci * This function moves valid nodes from data LEB described by @sleb to the GC 32762306a36Sopenharmony_ci * journal head. This function returns zero in case of success, %-EAGAIN if 32862306a36Sopenharmony_ci * commit is required, and other negative error codes in case of other 32962306a36Sopenharmony_ci * failures. 33062306a36Sopenharmony_ci */ 33162306a36Sopenharmony_cistatic int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci int err, min; 33462306a36Sopenharmony_ci LIST_HEAD(nondata); 33562306a36Sopenharmony_ci struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci if (wbuf->lnum == -1) { 33862306a36Sopenharmony_ci /* 33962306a36Sopenharmony_ci * The GC journal head is not set, because it is the first GC 34062306a36Sopenharmony_ci * invocation since mount. 34162306a36Sopenharmony_ci */ 34262306a36Sopenharmony_ci err = switch_gc_head(c); 34362306a36Sopenharmony_ci if (err) 34462306a36Sopenharmony_ci return err; 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci err = sort_nodes(c, sleb, &nondata, &min); 34862306a36Sopenharmony_ci if (err) 34962306a36Sopenharmony_ci goto out; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci /* Write nodes to their new location. Use the first-fit strategy */ 35262306a36Sopenharmony_ci while (1) { 35362306a36Sopenharmony_ci int avail, moved = 0; 35462306a36Sopenharmony_ci struct ubifs_scan_node *snod, *tmp; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci /* Move data nodes */ 35762306a36Sopenharmony_ci list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) { 35862306a36Sopenharmony_ci avail = c->leb_size - wbuf->offs - wbuf->used - 35962306a36Sopenharmony_ci ubifs_auth_node_sz(c); 36062306a36Sopenharmony_ci if (snod->len > avail) 36162306a36Sopenharmony_ci /* 36262306a36Sopenharmony_ci * Do not skip data nodes in order to optimize 36362306a36Sopenharmony_ci * bulk-read. 36462306a36Sopenharmony_ci */ 36562306a36Sopenharmony_ci break; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci err = ubifs_shash_update(c, c->jheads[GCHD].log_hash, 36862306a36Sopenharmony_ci snod->node, snod->len); 36962306a36Sopenharmony_ci if (err) 37062306a36Sopenharmony_ci goto out; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci err = move_node(c, sleb, snod, wbuf); 37362306a36Sopenharmony_ci if (err) 37462306a36Sopenharmony_ci goto out; 37562306a36Sopenharmony_ci moved = 1; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci /* Move non-data nodes */ 37962306a36Sopenharmony_ci list_for_each_entry_safe(snod, tmp, &nondata, list) { 38062306a36Sopenharmony_ci avail = c->leb_size - wbuf->offs - wbuf->used - 38162306a36Sopenharmony_ci ubifs_auth_node_sz(c); 38262306a36Sopenharmony_ci if (avail < min) 38362306a36Sopenharmony_ci break; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci if (snod->len > avail) { 38662306a36Sopenharmony_ci /* 38762306a36Sopenharmony_ci * Keep going only if this is an inode with 38862306a36Sopenharmony_ci * some data. Otherwise stop and switch the GC 38962306a36Sopenharmony_ci * head. IOW, we assume that data-less inode 39062306a36Sopenharmony_ci * nodes and direntry nodes are roughly of the 39162306a36Sopenharmony_ci * same size. 39262306a36Sopenharmony_ci */ 39362306a36Sopenharmony_ci if (key_type(c, &snod->key) == UBIFS_DENT_KEY || 39462306a36Sopenharmony_ci snod->len == UBIFS_INO_NODE_SZ) 39562306a36Sopenharmony_ci break; 39662306a36Sopenharmony_ci continue; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci err = ubifs_shash_update(c, c->jheads[GCHD].log_hash, 40062306a36Sopenharmony_ci snod->node, snod->len); 40162306a36Sopenharmony_ci if (err) 40262306a36Sopenharmony_ci goto out; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci err = move_node(c, sleb, snod, wbuf); 40562306a36Sopenharmony_ci if (err) 40662306a36Sopenharmony_ci goto out; 40762306a36Sopenharmony_ci moved = 1; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci if (ubifs_authenticated(c) && moved) { 41162306a36Sopenharmony_ci struct ubifs_auth_node *auth; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci auth = kmalloc(ubifs_auth_node_sz(c), GFP_NOFS); 41462306a36Sopenharmony_ci if (!auth) { 41562306a36Sopenharmony_ci err = -ENOMEM; 41662306a36Sopenharmony_ci goto out; 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci err = ubifs_prepare_auth_node(c, auth, 42062306a36Sopenharmony_ci c->jheads[GCHD].log_hash); 42162306a36Sopenharmony_ci if (err) { 42262306a36Sopenharmony_ci kfree(auth); 42362306a36Sopenharmony_ci goto out; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci err = ubifs_wbuf_write_nolock(wbuf, auth, 42762306a36Sopenharmony_ci ubifs_auth_node_sz(c)); 42862306a36Sopenharmony_ci if (err) { 42962306a36Sopenharmony_ci kfree(auth); 43062306a36Sopenharmony_ci goto out; 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci ubifs_add_dirt(c, wbuf->lnum, ubifs_auth_node_sz(c)); 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci if (list_empty(&sleb->nodes) && list_empty(&nondata)) 43762306a36Sopenharmony_ci break; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci /* 44062306a36Sopenharmony_ci * Waste the rest of the space in the LEB and switch to the 44162306a36Sopenharmony_ci * next LEB. 44262306a36Sopenharmony_ci */ 44362306a36Sopenharmony_ci err = switch_gc_head(c); 44462306a36Sopenharmony_ci if (err) 44562306a36Sopenharmony_ci goto out; 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci return 0; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ciout: 45162306a36Sopenharmony_ci list_splice_tail(&nondata, &sleb->nodes); 45262306a36Sopenharmony_ci return err; 45362306a36Sopenharmony_ci} 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci/** 45662306a36Sopenharmony_ci * gc_sync_wbufs - sync write-buffers for GC. 45762306a36Sopenharmony_ci * @c: UBIFS file-system description object 45862306a36Sopenharmony_ci * 45962306a36Sopenharmony_ci * We must guarantee that obsoleting nodes are on flash. Unfortunately they may 46062306a36Sopenharmony_ci * be in a write-buffer instead. That is, a node could be written to a 46162306a36Sopenharmony_ci * write-buffer, obsoleting another node in a LEB that is GC'd. If that LEB is 46262306a36Sopenharmony_ci * erased before the write-buffer is sync'd and then there is an unclean 46362306a36Sopenharmony_ci * unmount, then an existing node is lost. To avoid this, we sync all 46462306a36Sopenharmony_ci * write-buffers. 46562306a36Sopenharmony_ci * 46662306a36Sopenharmony_ci * This function returns %0 on success or a negative error code on failure. 46762306a36Sopenharmony_ci */ 46862306a36Sopenharmony_cistatic int gc_sync_wbufs(struct ubifs_info *c) 46962306a36Sopenharmony_ci{ 47062306a36Sopenharmony_ci int err, i; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci for (i = 0; i < c->jhead_cnt; i++) { 47362306a36Sopenharmony_ci if (i == GCHD) 47462306a36Sopenharmony_ci continue; 47562306a36Sopenharmony_ci err = ubifs_wbuf_sync(&c->jheads[i].wbuf); 47662306a36Sopenharmony_ci if (err) 47762306a36Sopenharmony_ci return err; 47862306a36Sopenharmony_ci } 47962306a36Sopenharmony_ci return 0; 48062306a36Sopenharmony_ci} 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci/** 48362306a36Sopenharmony_ci * ubifs_garbage_collect_leb - garbage-collect a logical eraseblock. 48462306a36Sopenharmony_ci * @c: UBIFS file-system description object 48562306a36Sopenharmony_ci * @lp: describes the LEB to garbage collect 48662306a36Sopenharmony_ci * 48762306a36Sopenharmony_ci * This function garbage-collects an LEB and returns one of the @LEB_FREED, 48862306a36Sopenharmony_ci * @LEB_RETAINED, etc positive codes in case of success, %-EAGAIN if commit is 48962306a36Sopenharmony_ci * required, and other negative error codes in case of failures. 49062306a36Sopenharmony_ci */ 49162306a36Sopenharmony_ciint ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) 49262306a36Sopenharmony_ci{ 49362306a36Sopenharmony_ci struct ubifs_scan_leb *sleb; 49462306a36Sopenharmony_ci struct ubifs_scan_node *snod; 49562306a36Sopenharmony_ci struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; 49662306a36Sopenharmony_ci int err = 0, lnum = lp->lnum; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci ubifs_assert(c, c->gc_lnum != -1 || wbuf->offs + wbuf->used == 0 || 49962306a36Sopenharmony_ci c->need_recovery); 50062306a36Sopenharmony_ci ubifs_assert(c, c->gc_lnum != lnum); 50162306a36Sopenharmony_ci ubifs_assert(c, wbuf->lnum != lnum); 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci if (lp->free + lp->dirty == c->leb_size) { 50462306a36Sopenharmony_ci /* Special case - a free LEB */ 50562306a36Sopenharmony_ci dbg_gc("LEB %d is free, return it", lp->lnum); 50662306a36Sopenharmony_ci ubifs_assert(c, !(lp->flags & LPROPS_INDEX)); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci if (lp->free != c->leb_size) { 50962306a36Sopenharmony_ci /* 51062306a36Sopenharmony_ci * Write buffers must be sync'd before unmapping 51162306a36Sopenharmony_ci * freeable LEBs, because one of them may contain data 51262306a36Sopenharmony_ci * which obsoletes something in 'lp->lnum'. 51362306a36Sopenharmony_ci */ 51462306a36Sopenharmony_ci err = gc_sync_wbufs(c); 51562306a36Sopenharmony_ci if (err) 51662306a36Sopenharmony_ci return err; 51762306a36Sopenharmony_ci err = ubifs_change_one_lp(c, lp->lnum, c->leb_size, 51862306a36Sopenharmony_ci 0, 0, 0, 0); 51962306a36Sopenharmony_ci if (err) 52062306a36Sopenharmony_ci return err; 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci err = ubifs_leb_unmap(c, lp->lnum); 52362306a36Sopenharmony_ci if (err) 52462306a36Sopenharmony_ci return err; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci if (c->gc_lnum == -1) { 52762306a36Sopenharmony_ci c->gc_lnum = lnum; 52862306a36Sopenharmony_ci return LEB_RETAINED; 52962306a36Sopenharmony_ci } 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci return LEB_FREED; 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci /* 53562306a36Sopenharmony_ci * We scan the entire LEB even though we only really need to scan up to 53662306a36Sopenharmony_ci * (c->leb_size - lp->free). 53762306a36Sopenharmony_ci */ 53862306a36Sopenharmony_ci sleb = ubifs_scan(c, lnum, 0, c->sbuf, 0); 53962306a36Sopenharmony_ci if (IS_ERR(sleb)) 54062306a36Sopenharmony_ci return PTR_ERR(sleb); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci ubifs_assert(c, !list_empty(&sleb->nodes)); 54362306a36Sopenharmony_ci snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list); 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci if (snod->type == UBIFS_IDX_NODE) { 54662306a36Sopenharmony_ci struct ubifs_gced_idx_leb *idx_gc; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci dbg_gc("indexing LEB %d (free %d, dirty %d)", 54962306a36Sopenharmony_ci lnum, lp->free, lp->dirty); 55062306a36Sopenharmony_ci list_for_each_entry(snod, &sleb->nodes, list) { 55162306a36Sopenharmony_ci struct ubifs_idx_node *idx = snod->node; 55262306a36Sopenharmony_ci int level = le16_to_cpu(idx->level); 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci ubifs_assert(c, snod->type == UBIFS_IDX_NODE); 55562306a36Sopenharmony_ci key_read(c, ubifs_idx_key(c, idx), &snod->key); 55662306a36Sopenharmony_ci err = ubifs_dirty_idx_node(c, &snod->key, level, lnum, 55762306a36Sopenharmony_ci snod->offs); 55862306a36Sopenharmony_ci if (err) 55962306a36Sopenharmony_ci goto out; 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci idx_gc = kmalloc(sizeof(struct ubifs_gced_idx_leb), GFP_NOFS); 56362306a36Sopenharmony_ci if (!idx_gc) { 56462306a36Sopenharmony_ci err = -ENOMEM; 56562306a36Sopenharmony_ci goto out; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci idx_gc->lnum = lnum; 56962306a36Sopenharmony_ci idx_gc->unmap = 0; 57062306a36Sopenharmony_ci list_add(&idx_gc->list, &c->idx_gc); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci /* 57362306a36Sopenharmony_ci * Don't release the LEB until after the next commit, because 57462306a36Sopenharmony_ci * it may contain data which is needed for recovery. So 57562306a36Sopenharmony_ci * although we freed this LEB, it will become usable only after 57662306a36Sopenharmony_ci * the commit. 57762306a36Sopenharmony_ci */ 57862306a36Sopenharmony_ci err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 57962306a36Sopenharmony_ci LPROPS_INDEX, 1); 58062306a36Sopenharmony_ci if (err) 58162306a36Sopenharmony_ci goto out; 58262306a36Sopenharmony_ci err = LEB_FREED_IDX; 58362306a36Sopenharmony_ci } else { 58462306a36Sopenharmony_ci dbg_gc("data LEB %d (free %d, dirty %d)", 58562306a36Sopenharmony_ci lnum, lp->free, lp->dirty); 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci err = move_nodes(c, sleb); 58862306a36Sopenharmony_ci if (err) 58962306a36Sopenharmony_ci goto out_inc_seq; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci err = gc_sync_wbufs(c); 59262306a36Sopenharmony_ci if (err) 59362306a36Sopenharmony_ci goto out_inc_seq; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 0, 0); 59662306a36Sopenharmony_ci if (err) 59762306a36Sopenharmony_ci goto out_inc_seq; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci /* Allow for races with TNC */ 60062306a36Sopenharmony_ci c->gced_lnum = lnum; 60162306a36Sopenharmony_ci smp_wmb(); 60262306a36Sopenharmony_ci c->gc_seq += 1; 60362306a36Sopenharmony_ci smp_wmb(); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci if (c->gc_lnum == -1) { 60662306a36Sopenharmony_ci c->gc_lnum = lnum; 60762306a36Sopenharmony_ci err = LEB_RETAINED; 60862306a36Sopenharmony_ci } else { 60962306a36Sopenharmony_ci err = ubifs_wbuf_sync_nolock(wbuf); 61062306a36Sopenharmony_ci if (err) 61162306a36Sopenharmony_ci goto out; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci err = ubifs_leb_unmap(c, lnum); 61462306a36Sopenharmony_ci if (err) 61562306a36Sopenharmony_ci goto out; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci err = LEB_FREED; 61862306a36Sopenharmony_ci } 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ciout: 62262306a36Sopenharmony_ci ubifs_scan_destroy(sleb); 62362306a36Sopenharmony_ci return err; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ciout_inc_seq: 62662306a36Sopenharmony_ci /* We may have moved at least some nodes so allow for races with TNC */ 62762306a36Sopenharmony_ci c->gced_lnum = lnum; 62862306a36Sopenharmony_ci smp_wmb(); 62962306a36Sopenharmony_ci c->gc_seq += 1; 63062306a36Sopenharmony_ci smp_wmb(); 63162306a36Sopenharmony_ci goto out; 63262306a36Sopenharmony_ci} 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci/** 63562306a36Sopenharmony_ci * ubifs_garbage_collect - UBIFS garbage collector. 63662306a36Sopenharmony_ci * @c: UBIFS file-system description object 63762306a36Sopenharmony_ci * @anyway: do GC even if there are free LEBs 63862306a36Sopenharmony_ci * 63962306a36Sopenharmony_ci * This function does out-of-place garbage collection. The return codes are: 64062306a36Sopenharmony_ci * o positive LEB number if the LEB has been freed and may be used; 64162306a36Sopenharmony_ci * o %-EAGAIN if the caller has to run commit; 64262306a36Sopenharmony_ci * o %-ENOSPC if GC failed to make any progress; 64362306a36Sopenharmony_ci * o other negative error codes in case of other errors. 64462306a36Sopenharmony_ci * 64562306a36Sopenharmony_ci * Garbage collector writes data to the journal when GC'ing data LEBs, and just 64662306a36Sopenharmony_ci * marking indexing nodes dirty when GC'ing indexing LEBs. Thus, at some point 64762306a36Sopenharmony_ci * commit may be required. But commit cannot be run from inside GC, because the 64862306a36Sopenharmony_ci * caller might be holding the commit lock, so %-EAGAIN is returned instead; 64962306a36Sopenharmony_ci * And this error code means that the caller has to run commit, and re-run GC 65062306a36Sopenharmony_ci * if there is still no free space. 65162306a36Sopenharmony_ci * 65262306a36Sopenharmony_ci * There are many reasons why this function may return %-EAGAIN: 65362306a36Sopenharmony_ci * o the log is full and there is no space to write an LEB reference for 65462306a36Sopenharmony_ci * @c->gc_lnum; 65562306a36Sopenharmony_ci * o the journal is too large and exceeds size limitations; 65662306a36Sopenharmony_ci * o GC moved indexing LEBs, but they can be used only after the commit; 65762306a36Sopenharmony_ci * o the shrinker fails to find clean znodes to free and requests the commit; 65862306a36Sopenharmony_ci * o etc. 65962306a36Sopenharmony_ci * 66062306a36Sopenharmony_ci * Note, if the file-system is close to be full, this function may return 66162306a36Sopenharmony_ci * %-EAGAIN infinitely, so the caller has to limit amount of re-invocations of 66262306a36Sopenharmony_ci * the function. E.g., this happens if the limits on the journal size are too 66362306a36Sopenharmony_ci * tough and GC writes too much to the journal before an LEB is freed. This 66462306a36Sopenharmony_ci * might also mean that the journal is too large, and the TNC becomes to big, 66562306a36Sopenharmony_ci * so that the shrinker is constantly called, finds not clean znodes to free, 66662306a36Sopenharmony_ci * and requests commit. Well, this may also happen if the journal is all right, 66762306a36Sopenharmony_ci * but another kernel process consumes too much memory. Anyway, infinite 66862306a36Sopenharmony_ci * %-EAGAIN may happen, but in some extreme/misconfiguration cases. 66962306a36Sopenharmony_ci */ 67062306a36Sopenharmony_ciint ubifs_garbage_collect(struct ubifs_info *c, int anyway) 67162306a36Sopenharmony_ci{ 67262306a36Sopenharmony_ci int i, err, ret, min_space = c->dead_wm; 67362306a36Sopenharmony_ci struct ubifs_lprops lp; 67462306a36Sopenharmony_ci struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci ubifs_assert_cmt_locked(c); 67762306a36Sopenharmony_ci ubifs_assert(c, !c->ro_media && !c->ro_mount); 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci if (ubifs_gc_should_commit(c)) 68062306a36Sopenharmony_ci return -EAGAIN; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci if (c->ro_error) { 68562306a36Sopenharmony_ci ret = -EROFS; 68662306a36Sopenharmony_ci goto out_unlock; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci /* We expect the write-buffer to be empty on entry */ 69062306a36Sopenharmony_ci ubifs_assert(c, !wbuf->used); 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci for (i = 0; ; i++) { 69362306a36Sopenharmony_ci int space_before, space_after; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci /* Maybe continue after find and break before find */ 69662306a36Sopenharmony_ci lp.lnum = -1; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci cond_resched(); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci /* Give the commit an opportunity to run */ 70162306a36Sopenharmony_ci if (ubifs_gc_should_commit(c)) { 70262306a36Sopenharmony_ci ret = -EAGAIN; 70362306a36Sopenharmony_ci break; 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci if (i > SOFT_LEBS_LIMIT && !list_empty(&c->idx_gc)) { 70762306a36Sopenharmony_ci /* 70862306a36Sopenharmony_ci * We've done enough iterations. Indexing LEBs were 70962306a36Sopenharmony_ci * moved and will be available after the commit. 71062306a36Sopenharmony_ci */ 71162306a36Sopenharmony_ci dbg_gc("soft limit, some index LEBs GC'ed, -EAGAIN"); 71262306a36Sopenharmony_ci ubifs_commit_required(c); 71362306a36Sopenharmony_ci ret = -EAGAIN; 71462306a36Sopenharmony_ci break; 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci if (i > HARD_LEBS_LIMIT) { 71862306a36Sopenharmony_ci /* 71962306a36Sopenharmony_ci * We've moved too many LEBs and have not made 72062306a36Sopenharmony_ci * progress, give up. 72162306a36Sopenharmony_ci */ 72262306a36Sopenharmony_ci dbg_gc("hard limit, -ENOSPC"); 72362306a36Sopenharmony_ci ret = -ENOSPC; 72462306a36Sopenharmony_ci break; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci /* 72862306a36Sopenharmony_ci * Empty and freeable LEBs can turn up while we waited for 72962306a36Sopenharmony_ci * the wbuf lock, or while we have been running GC. In that 73062306a36Sopenharmony_ci * case, we should just return one of those instead of 73162306a36Sopenharmony_ci * continuing to GC dirty LEBs. Hence we request 73262306a36Sopenharmony_ci * 'ubifs_find_dirty_leb()' to return an empty LEB if it can. 73362306a36Sopenharmony_ci */ 73462306a36Sopenharmony_ci ret = ubifs_find_dirty_leb(c, &lp, min_space, anyway ? 0 : 1); 73562306a36Sopenharmony_ci if (ret) { 73662306a36Sopenharmony_ci if (ret == -ENOSPC) 73762306a36Sopenharmony_ci dbg_gc("no more dirty LEBs"); 73862306a36Sopenharmony_ci break; 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci dbg_gc("found LEB %d: free %d, dirty %d, sum %d (min. space %d)", 74262306a36Sopenharmony_ci lp.lnum, lp.free, lp.dirty, lp.free + lp.dirty, 74362306a36Sopenharmony_ci min_space); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci space_before = c->leb_size - wbuf->offs - wbuf->used; 74662306a36Sopenharmony_ci if (wbuf->lnum == -1) 74762306a36Sopenharmony_ci space_before = 0; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci ret = ubifs_garbage_collect_leb(c, &lp); 75062306a36Sopenharmony_ci if (ret < 0) { 75162306a36Sopenharmony_ci if (ret == -EAGAIN) { 75262306a36Sopenharmony_ci /* 75362306a36Sopenharmony_ci * This is not error, so we have to return the 75462306a36Sopenharmony_ci * LEB to lprops. But if 'ubifs_return_leb()' 75562306a36Sopenharmony_ci * fails, its failure code is propagated to the 75662306a36Sopenharmony_ci * caller instead of the original '-EAGAIN'. 75762306a36Sopenharmony_ci */ 75862306a36Sopenharmony_ci err = ubifs_return_leb(c, lp.lnum); 75962306a36Sopenharmony_ci if (err) { 76062306a36Sopenharmony_ci ret = err; 76162306a36Sopenharmony_ci /* 76262306a36Sopenharmony_ci * An LEB may always be "taken", 76362306a36Sopenharmony_ci * so setting ubifs to read-only, 76462306a36Sopenharmony_ci * and then executing sync wbuf will 76562306a36Sopenharmony_ci * return -EROFS and enter the "out" 76662306a36Sopenharmony_ci * error branch. 76762306a36Sopenharmony_ci */ 76862306a36Sopenharmony_ci ubifs_ro_mode(c, ret); 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci /* Maybe double return LEB if goto out */ 77162306a36Sopenharmony_ci lp.lnum = -1; 77262306a36Sopenharmony_ci break; 77362306a36Sopenharmony_ci } 77462306a36Sopenharmony_ci goto out; 77562306a36Sopenharmony_ci } 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci if (ret == LEB_FREED) { 77862306a36Sopenharmony_ci /* An LEB has been freed and is ready for use */ 77962306a36Sopenharmony_ci dbg_gc("LEB %d freed, return", lp.lnum); 78062306a36Sopenharmony_ci ret = lp.lnum; 78162306a36Sopenharmony_ci break; 78262306a36Sopenharmony_ci } 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci if (ret == LEB_FREED_IDX) { 78562306a36Sopenharmony_ci /* 78662306a36Sopenharmony_ci * This was an indexing LEB and it cannot be 78762306a36Sopenharmony_ci * immediately used. And instead of requesting the 78862306a36Sopenharmony_ci * commit straight away, we try to garbage collect some 78962306a36Sopenharmony_ci * more. 79062306a36Sopenharmony_ci */ 79162306a36Sopenharmony_ci dbg_gc("indexing LEB %d freed, continue", lp.lnum); 79262306a36Sopenharmony_ci continue; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci ubifs_assert(c, ret == LEB_RETAINED); 79662306a36Sopenharmony_ci space_after = c->leb_size - wbuf->offs - wbuf->used; 79762306a36Sopenharmony_ci dbg_gc("LEB %d retained, freed %d bytes", lp.lnum, 79862306a36Sopenharmony_ci space_after - space_before); 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci if (space_after > space_before) { 80162306a36Sopenharmony_ci /* GC makes progress, keep working */ 80262306a36Sopenharmony_ci min_space >>= 1; 80362306a36Sopenharmony_ci if (min_space < c->dead_wm) 80462306a36Sopenharmony_ci min_space = c->dead_wm; 80562306a36Sopenharmony_ci continue; 80662306a36Sopenharmony_ci } 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci dbg_gc("did not make progress"); 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci /* 81162306a36Sopenharmony_ci * GC moved an LEB bud have not done any progress. This means 81262306a36Sopenharmony_ci * that the previous GC head LEB contained too few free space 81362306a36Sopenharmony_ci * and the LEB which was GC'ed contained only large nodes which 81462306a36Sopenharmony_ci * did not fit that space. 81562306a36Sopenharmony_ci * 81662306a36Sopenharmony_ci * We can do 2 things: 81762306a36Sopenharmony_ci * 1. pick another LEB in a hope it'll contain a small node 81862306a36Sopenharmony_ci * which will fit the space we have at the end of current GC 81962306a36Sopenharmony_ci * head LEB, but there is no guarantee, so we try this out 82062306a36Sopenharmony_ci * unless we have already been working for too long; 82162306a36Sopenharmony_ci * 2. request an LEB with more dirty space, which will force 82262306a36Sopenharmony_ci * 'ubifs_find_dirty_leb()' to start scanning the lprops 82362306a36Sopenharmony_ci * table, instead of just picking one from the heap 82462306a36Sopenharmony_ci * (previously it already picked the dirtiest LEB). 82562306a36Sopenharmony_ci */ 82662306a36Sopenharmony_ci if (i < SOFT_LEBS_LIMIT) { 82762306a36Sopenharmony_ci dbg_gc("try again"); 82862306a36Sopenharmony_ci continue; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci min_space <<= 1; 83262306a36Sopenharmony_ci if (min_space > c->dark_wm) 83362306a36Sopenharmony_ci min_space = c->dark_wm; 83462306a36Sopenharmony_ci dbg_gc("set min. space to %d", min_space); 83562306a36Sopenharmony_ci } 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci if (ret == -ENOSPC && !list_empty(&c->idx_gc)) { 83862306a36Sopenharmony_ci dbg_gc("no space, some index LEBs GC'ed, -EAGAIN"); 83962306a36Sopenharmony_ci ubifs_commit_required(c); 84062306a36Sopenharmony_ci ret = -EAGAIN; 84162306a36Sopenharmony_ci } 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci err = ubifs_wbuf_sync_nolock(wbuf); 84462306a36Sopenharmony_ci if (!err) 84562306a36Sopenharmony_ci err = ubifs_leb_unmap(c, c->gc_lnum); 84662306a36Sopenharmony_ci if (err) { 84762306a36Sopenharmony_ci ret = err; 84862306a36Sopenharmony_ci goto out; 84962306a36Sopenharmony_ci } 85062306a36Sopenharmony_ciout_unlock: 85162306a36Sopenharmony_ci mutex_unlock(&wbuf->io_mutex); 85262306a36Sopenharmony_ci return ret; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ciout: 85562306a36Sopenharmony_ci ubifs_assert(c, ret < 0); 85662306a36Sopenharmony_ci ubifs_assert(c, ret != -ENOSPC && ret != -EAGAIN); 85762306a36Sopenharmony_ci ubifs_wbuf_sync_nolock(wbuf); 85862306a36Sopenharmony_ci ubifs_ro_mode(c, ret); 85962306a36Sopenharmony_ci mutex_unlock(&wbuf->io_mutex); 86062306a36Sopenharmony_ci if (lp.lnum != -1) 86162306a36Sopenharmony_ci ubifs_return_leb(c, lp.lnum); 86262306a36Sopenharmony_ci return ret; 86362306a36Sopenharmony_ci} 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci/** 86662306a36Sopenharmony_ci * ubifs_gc_start_commit - garbage collection at start of commit. 86762306a36Sopenharmony_ci * @c: UBIFS file-system description object 86862306a36Sopenharmony_ci * 86962306a36Sopenharmony_ci * If a LEB has only dirty and free space, then we may safely unmap it and make 87062306a36Sopenharmony_ci * it free. Note, we cannot do this with indexing LEBs because dirty space may 87162306a36Sopenharmony_ci * correspond index nodes that are required for recovery. In that case, the 87262306a36Sopenharmony_ci * LEB cannot be unmapped until after the next commit. 87362306a36Sopenharmony_ci * 87462306a36Sopenharmony_ci * This function returns %0 upon success and a negative error code upon failure. 87562306a36Sopenharmony_ci */ 87662306a36Sopenharmony_ciint ubifs_gc_start_commit(struct ubifs_info *c) 87762306a36Sopenharmony_ci{ 87862306a36Sopenharmony_ci struct ubifs_gced_idx_leb *idx_gc; 87962306a36Sopenharmony_ci const struct ubifs_lprops *lp; 88062306a36Sopenharmony_ci int err = 0, flags; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci ubifs_get_lprops(c); 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci /* 88562306a36Sopenharmony_ci * Unmap (non-index) freeable LEBs. Note that recovery requires that all 88662306a36Sopenharmony_ci * wbufs are sync'd before this, which is done in 'do_commit()'. 88762306a36Sopenharmony_ci */ 88862306a36Sopenharmony_ci while (1) { 88962306a36Sopenharmony_ci lp = ubifs_fast_find_freeable(c); 89062306a36Sopenharmony_ci if (!lp) 89162306a36Sopenharmony_ci break; 89262306a36Sopenharmony_ci ubifs_assert(c, !(lp->flags & LPROPS_TAKEN)); 89362306a36Sopenharmony_ci ubifs_assert(c, !(lp->flags & LPROPS_INDEX)); 89462306a36Sopenharmony_ci err = ubifs_leb_unmap(c, lp->lnum); 89562306a36Sopenharmony_ci if (err) 89662306a36Sopenharmony_ci goto out; 89762306a36Sopenharmony_ci lp = ubifs_change_lp(c, lp, c->leb_size, 0, lp->flags, 0); 89862306a36Sopenharmony_ci if (IS_ERR(lp)) { 89962306a36Sopenharmony_ci err = PTR_ERR(lp); 90062306a36Sopenharmony_ci goto out; 90162306a36Sopenharmony_ci } 90262306a36Sopenharmony_ci ubifs_assert(c, !(lp->flags & LPROPS_TAKEN)); 90362306a36Sopenharmony_ci ubifs_assert(c, !(lp->flags & LPROPS_INDEX)); 90462306a36Sopenharmony_ci } 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci /* Mark GC'd index LEBs OK to unmap after this commit finishes */ 90762306a36Sopenharmony_ci list_for_each_entry(idx_gc, &c->idx_gc, list) 90862306a36Sopenharmony_ci idx_gc->unmap = 1; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci /* Record index freeable LEBs for unmapping after commit */ 91162306a36Sopenharmony_ci while (1) { 91262306a36Sopenharmony_ci lp = ubifs_fast_find_frdi_idx(c); 91362306a36Sopenharmony_ci if (IS_ERR(lp)) { 91462306a36Sopenharmony_ci err = PTR_ERR(lp); 91562306a36Sopenharmony_ci goto out; 91662306a36Sopenharmony_ci } 91762306a36Sopenharmony_ci if (!lp) 91862306a36Sopenharmony_ci break; 91962306a36Sopenharmony_ci idx_gc = kmalloc(sizeof(struct ubifs_gced_idx_leb), GFP_NOFS); 92062306a36Sopenharmony_ci if (!idx_gc) { 92162306a36Sopenharmony_ci err = -ENOMEM; 92262306a36Sopenharmony_ci goto out; 92362306a36Sopenharmony_ci } 92462306a36Sopenharmony_ci ubifs_assert(c, !(lp->flags & LPROPS_TAKEN)); 92562306a36Sopenharmony_ci ubifs_assert(c, lp->flags & LPROPS_INDEX); 92662306a36Sopenharmony_ci /* Don't release the LEB until after the next commit */ 92762306a36Sopenharmony_ci flags = (lp->flags | LPROPS_TAKEN) ^ LPROPS_INDEX; 92862306a36Sopenharmony_ci lp = ubifs_change_lp(c, lp, c->leb_size, 0, flags, 1); 92962306a36Sopenharmony_ci if (IS_ERR(lp)) { 93062306a36Sopenharmony_ci err = PTR_ERR(lp); 93162306a36Sopenharmony_ci kfree(idx_gc); 93262306a36Sopenharmony_ci goto out; 93362306a36Sopenharmony_ci } 93462306a36Sopenharmony_ci ubifs_assert(c, lp->flags & LPROPS_TAKEN); 93562306a36Sopenharmony_ci ubifs_assert(c, !(lp->flags & LPROPS_INDEX)); 93662306a36Sopenharmony_ci idx_gc->lnum = lp->lnum; 93762306a36Sopenharmony_ci idx_gc->unmap = 1; 93862306a36Sopenharmony_ci list_add(&idx_gc->list, &c->idx_gc); 93962306a36Sopenharmony_ci } 94062306a36Sopenharmony_ciout: 94162306a36Sopenharmony_ci ubifs_release_lprops(c); 94262306a36Sopenharmony_ci return err; 94362306a36Sopenharmony_ci} 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci/** 94662306a36Sopenharmony_ci * ubifs_gc_end_commit - garbage collection at end of commit. 94762306a36Sopenharmony_ci * @c: UBIFS file-system description object 94862306a36Sopenharmony_ci * 94962306a36Sopenharmony_ci * This function completes out-of-place garbage collection of index LEBs. 95062306a36Sopenharmony_ci */ 95162306a36Sopenharmony_ciint ubifs_gc_end_commit(struct ubifs_info *c) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci struct ubifs_gced_idx_leb *idx_gc, *tmp; 95462306a36Sopenharmony_ci struct ubifs_wbuf *wbuf; 95562306a36Sopenharmony_ci int err = 0; 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci wbuf = &c->jheads[GCHD].wbuf; 95862306a36Sopenharmony_ci mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); 95962306a36Sopenharmony_ci list_for_each_entry_safe(idx_gc, tmp, &c->idx_gc, list) 96062306a36Sopenharmony_ci if (idx_gc->unmap) { 96162306a36Sopenharmony_ci dbg_gc("LEB %d", idx_gc->lnum); 96262306a36Sopenharmony_ci err = ubifs_leb_unmap(c, idx_gc->lnum); 96362306a36Sopenharmony_ci if (err) 96462306a36Sopenharmony_ci goto out; 96562306a36Sopenharmony_ci err = ubifs_change_one_lp(c, idx_gc->lnum, LPROPS_NC, 96662306a36Sopenharmony_ci LPROPS_NC, 0, LPROPS_TAKEN, -1); 96762306a36Sopenharmony_ci if (err) 96862306a36Sopenharmony_ci goto out; 96962306a36Sopenharmony_ci list_del(&idx_gc->list); 97062306a36Sopenharmony_ci kfree(idx_gc); 97162306a36Sopenharmony_ci } 97262306a36Sopenharmony_ciout: 97362306a36Sopenharmony_ci mutex_unlock(&wbuf->io_mutex); 97462306a36Sopenharmony_ci return err; 97562306a36Sopenharmony_ci} 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci/** 97862306a36Sopenharmony_ci * ubifs_destroy_idx_gc - destroy idx_gc list. 97962306a36Sopenharmony_ci * @c: UBIFS file-system description object 98062306a36Sopenharmony_ci * 98162306a36Sopenharmony_ci * This function destroys the @c->idx_gc list. It is called when unmounting 98262306a36Sopenharmony_ci * so locks are not needed. Returns zero in case of success and a negative 98362306a36Sopenharmony_ci * error code in case of failure. 98462306a36Sopenharmony_ci */ 98562306a36Sopenharmony_civoid ubifs_destroy_idx_gc(struct ubifs_info *c) 98662306a36Sopenharmony_ci{ 98762306a36Sopenharmony_ci while (!list_empty(&c->idx_gc)) { 98862306a36Sopenharmony_ci struct ubifs_gced_idx_leb *idx_gc; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb, 99162306a36Sopenharmony_ci list); 99262306a36Sopenharmony_ci c->idx_gc_cnt -= 1; 99362306a36Sopenharmony_ci list_del(&idx_gc->list); 99462306a36Sopenharmony_ci kfree(idx_gc); 99562306a36Sopenharmony_ci } 99662306a36Sopenharmony_ci} 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci/** 99962306a36Sopenharmony_ci * ubifs_get_idx_gc_leb - get a LEB from GC'd index LEB list. 100062306a36Sopenharmony_ci * @c: UBIFS file-system description object 100162306a36Sopenharmony_ci * 100262306a36Sopenharmony_ci * Called during start commit so locks are not needed. 100362306a36Sopenharmony_ci */ 100462306a36Sopenharmony_ciint ubifs_get_idx_gc_leb(struct ubifs_info *c) 100562306a36Sopenharmony_ci{ 100662306a36Sopenharmony_ci struct ubifs_gced_idx_leb *idx_gc; 100762306a36Sopenharmony_ci int lnum; 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci if (list_empty(&c->idx_gc)) 101062306a36Sopenharmony_ci return -ENOSPC; 101162306a36Sopenharmony_ci idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb, list); 101262306a36Sopenharmony_ci lnum = idx_gc->lnum; 101362306a36Sopenharmony_ci /* c->idx_gc_cnt is updated by the caller when lprops are updated */ 101462306a36Sopenharmony_ci list_del(&idx_gc->list); 101562306a36Sopenharmony_ci kfree(idx_gc); 101662306a36Sopenharmony_ci return lnum; 101762306a36Sopenharmony_ci} 1018