diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-24 22:57:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-24 22:57:15 -0400 |
commit | 8f40842e4260f73792c156aded004197a19135ee (patch) | |
tree | b192ed354a34839a8c1607883d1ebc09b06a76c0 /fs/jffs2/gc.c | |
parent | 88875667ebbcb95da3f93a4cf657d5dad7db9673 (diff) | |
parent | 6871c1b96de88d3576d935b528fd1b0ec70e81f5 (diff) |
Merge tag 'for-linus-20160324' of git://git.infradead.org/linux-mtd
Pull MTD updates from Brian Norris:
"NAND:
- Add sunxi_nand randomizer support
- begin refactoring NAND ecclayout structs
- fix pxa3xx_nand dmaengine usage
- brcmnand: fix support for v7.1 controller
- add Qualcomm NAND controller driver
SPI NOR:
- add new ls1021a, ls2080a support to Freescale QuadSPI
- add new flash ID entries
- support bottom-block protection for Winbond flash
- support Status Register Write Protect
- remove broken QPI support for Micron SPI flash
JFFS2:
- improve post-mount CRC scan efficiency
General:
- refactor bcm63xxpart parser, to later extend for NAND
- add writebuf size parameter to mtdram
Other minor code quality improvements"
* tag 'for-linus-20160324' of git://git.infradead.org/linux-mtd: (72 commits)
mtd: nand: remove kerneldoc for removed function parameter
mtd: nand: Qualcomm NAND controller driver
dt/bindings: qcom_nandc: Add DT bindings
mtd: nand: don't select chip in nand_chip's block_bad op
mtd: spi-nor: support lock/unlock for a few Winbond chips
mtd: spi-nor: add TB (Top/Bottom) protect support
mtd: spi-nor: add SPI_NOR_HAS_LOCK flag
mtd: spi-nor: use BIT() for flash_info flags
mtd: spi-nor: disallow further writes to SR if WP# is low
mtd: spi-nor: make lock/unlock bounds checks more obvious and robust
mtd: spi-nor: silently drop lock/unlock for already locked/unlocked region
mtd: spi-nor: wait for SR_WIP to clear on initial unlock
mtd: nand: simplify nand_bch_init() usage
mtd: mtdswap: remove useless if (!mtd->ecclayout) test
mtd: create an mtd_oobavail() helper and make use of it
mtd: kill the ecclayout->oobavail field
mtd: nand: check status before reporting timeout
mtd: bcm63xxpart: give width specifier an 'int', not 'size_t'
mtd: mtdram: Add parameter for setting writebuf size
mtd: nand: pxa3xx_nand: kill unused field 'drcmr_cmd'
...
Diffstat (limited to 'fs/jffs2/gc.c')
-rw-r--r-- | fs/jffs2/gc.c | 64 |
1 files changed, 42 insertions, 22 deletions
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 95d5880a63ee..7e553f286775 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c | |||
@@ -134,37 +134,59 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
134 | if (mutex_lock_interruptible(&c->alloc_sem)) | 134 | if (mutex_lock_interruptible(&c->alloc_sem)) |
135 | return -EINTR; | 135 | return -EINTR; |
136 | 136 | ||
137 | |||
137 | for (;;) { | 138 | for (;;) { |
139 | /* We can't start doing GC until we've finished checking | ||
140 | the node CRCs etc. */ | ||
141 | int bucket, want_ino; | ||
142 | |||
138 | spin_lock(&c->erase_completion_lock); | 143 | spin_lock(&c->erase_completion_lock); |
139 | if (!c->unchecked_size) | 144 | if (!c->unchecked_size) |
140 | break; | 145 | break; |
141 | |||
142 | /* We can't start doing GC yet. We haven't finished checking | ||
143 | the node CRCs etc. Do it now. */ | ||
144 | |||
145 | /* checked_ino is protected by the alloc_sem */ | ||
146 | if (c->checked_ino > c->highest_ino && xattr) { | ||
147 | pr_crit("Checked all inodes but still 0x%x bytes of unchecked space?\n", | ||
148 | c->unchecked_size); | ||
149 | jffs2_dbg_dump_block_lists_nolock(c); | ||
150 | spin_unlock(&c->erase_completion_lock); | ||
151 | mutex_unlock(&c->alloc_sem); | ||
152 | return -ENOSPC; | ||
153 | } | ||
154 | |||
155 | spin_unlock(&c->erase_completion_lock); | 146 | spin_unlock(&c->erase_completion_lock); |
156 | 147 | ||
157 | if (!xattr) | 148 | if (!xattr) |
158 | xattr = jffs2_verify_xattr(c); | 149 | xattr = jffs2_verify_xattr(c); |
159 | 150 | ||
160 | spin_lock(&c->inocache_lock); | 151 | spin_lock(&c->inocache_lock); |
152 | /* Instead of doing the inodes in numeric order, doing a lookup | ||
153 | * in the hash for each possible number, just walk the hash | ||
154 | * buckets of *existing* inodes. This means that we process | ||
155 | * them out-of-order, but it can be a lot faster if there's | ||
156 | * a sparse inode# space. Which there often is. */ | ||
157 | want_ino = c->check_ino; | ||
158 | for (bucket = c->check_ino % c->inocache_hashsize ; bucket < c->inocache_hashsize; bucket++) { | ||
159 | for (ic = c->inocache_list[bucket]; ic; ic = ic->next) { | ||
160 | if (ic->ino < want_ino) | ||
161 | continue; | ||
162 | |||
163 | if (ic->state != INO_STATE_CHECKEDABSENT && | ||
164 | ic->state != INO_STATE_PRESENT) | ||
165 | goto got_next; /* with inocache_lock held */ | ||
166 | |||
167 | jffs2_dbg(1, "Skipping ino #%u already checked\n", | ||
168 | ic->ino); | ||
169 | } | ||
170 | want_ino = 0; | ||
171 | } | ||
161 | 172 | ||
162 | ic = jffs2_get_ino_cache(c, c->checked_ino++); | 173 | /* Point c->check_ino past the end of the last bucket. */ |
174 | c->check_ino = ((c->highest_ino + c->inocache_hashsize + 1) & | ||
175 | ~c->inocache_hashsize) - 1; | ||
163 | 176 | ||
164 | if (!ic) { | 177 | spin_unlock(&c->inocache_lock); |
165 | spin_unlock(&c->inocache_lock); | 178 | |
166 | continue; | 179 | pr_crit("Checked all inodes but still 0x%x bytes of unchecked space?\n", |
167 | } | 180 | c->unchecked_size); |
181 | jffs2_dbg_dump_block_lists_nolock(c); | ||
182 | mutex_unlock(&c->alloc_sem); | ||
183 | return -ENOSPC; | ||
184 | |||
185 | got_next: | ||
186 | /* For next time round the loop, we want c->checked_ino to indicate | ||
187 | * the *next* one we want to check. And since we're walking the | ||
188 | * buckets rather than doing it sequentially, it's: */ | ||
189 | c->check_ino = ic->ino + c->inocache_hashsize; | ||
168 | 190 | ||
169 | if (!ic->pino_nlink) { | 191 | if (!ic->pino_nlink) { |
170 | jffs2_dbg(1, "Skipping check of ino #%d with nlink/pino zero\n", | 192 | jffs2_dbg(1, "Skipping check of ino #%d with nlink/pino zero\n", |
@@ -176,8 +198,6 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
176 | switch(ic->state) { | 198 | switch(ic->state) { |
177 | case INO_STATE_CHECKEDABSENT: | 199 | case INO_STATE_CHECKEDABSENT: |
178 | case INO_STATE_PRESENT: | 200 | case INO_STATE_PRESENT: |
179 | jffs2_dbg(1, "Skipping ino #%u already checked\n", | ||
180 | ic->ino); | ||
181 | spin_unlock(&c->inocache_lock); | 201 | spin_unlock(&c->inocache_lock); |
182 | continue; | 202 | continue; |
183 | 203 | ||
@@ -196,7 +216,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
196 | ic->ino); | 216 | ic->ino); |
197 | /* We need to come back again for the _same_ inode. We've | 217 | /* We need to come back again for the _same_ inode. We've |
198 | made no progress in this case, but that should be OK */ | 218 | made no progress in this case, but that should be OK */ |
199 | c->checked_ino--; | 219 | c->check_ino = ic->ino; |
200 | 220 | ||
201 | mutex_unlock(&c->alloc_sem); | 221 | mutex_unlock(&c->alloc_sem); |
202 | sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); | 222 | sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); |