diff options
Diffstat (limited to 'fs/ubifs')
| -rw-r--r-- | fs/ubifs/commit.c | 4 | ||||
| -rw-r--r-- | fs/ubifs/debug.c | 157 | ||||
| -rw-r--r-- | fs/ubifs/debug.h | 4 | ||||
| -rw-r--r-- | fs/ubifs/file.c | 7 | ||||
| -rw-r--r-- | fs/ubifs/gc.c | 82 | ||||
| -rw-r--r-- | fs/ubifs/io.c | 20 | ||||
| -rw-r--r-- | fs/ubifs/journal.c | 3 | ||||
| -rw-r--r-- | fs/ubifs/key.h | 14 | ||||
| -rw-r--r-- | fs/ubifs/log.c | 6 | ||||
| -rw-r--r-- | fs/ubifs/lpt.c | 7 | ||||
| -rw-r--r-- | fs/ubifs/lpt_commit.c | 3 | ||||
| -rw-r--r-- | fs/ubifs/master.c | 3 | ||||
| -rw-r--r-- | fs/ubifs/misc.h | 9 | ||||
| -rw-r--r-- | fs/ubifs/recovery.c | 11 | ||||
| -rw-r--r-- | fs/ubifs/replay.c | 20 | ||||
| -rw-r--r-- | fs/ubifs/sb.c | 9 | ||||
| -rw-r--r-- | fs/ubifs/scan.c | 6 | ||||
| -rw-r--r-- | fs/ubifs/shrinker.c | 2 | ||||
| -rw-r--r-- | fs/ubifs/super.c | 80 | ||||
| -rw-r--r-- | fs/ubifs/tnc.c | 5 | ||||
| -rw-r--r-- | fs/ubifs/ubifs.h | 23 |
21 files changed, 363 insertions, 112 deletions
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c index 37fa7ed062d..02429d81ca3 100644 --- a/fs/ubifs/commit.c +++ b/fs/ubifs/commit.c | |||
| @@ -63,7 +63,9 @@ static int do_commit(struct ubifs_info *c) | |||
| 63 | struct ubifs_lp_stats lst; | 63 | struct ubifs_lp_stats lst; |
| 64 | 64 | ||
| 65 | dbg_cmt("start"); | 65 | dbg_cmt("start"); |
| 66 | if (c->ro_media) { | 66 | ubifs_assert(!c->ro_media && !c->ro_mount); |
| 67 | |||
| 68 | if (c->ro_error) { | ||
| 67 | err = -EROFS; | 69 | err = -EROFS; |
| 68 | goto out_up; | 70 | goto out_up; |
| 69 | } | 71 | } |
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index c2a68baa782..0bee4dbffc3 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
| @@ -2239,6 +2239,162 @@ out_free: | |||
| 2239 | return err; | 2239 | return err; |
| 2240 | } | 2240 | } |
| 2241 | 2241 | ||
| 2242 | /** | ||
| 2243 | * dbg_check_data_nodes_order - check that list of data nodes is sorted. | ||
| 2244 | * @c: UBIFS file-system description object | ||
| 2245 | * @head: the list of nodes ('struct ubifs_scan_node' objects) | ||
| 2246 | * | ||
| 2247 | * This function returns zero if the list of data nodes is sorted correctly, | ||
| 2248 | * and %-EINVAL if not. | ||
| 2249 | */ | ||
| 2250 | int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head) | ||
| 2251 | { | ||
| 2252 | struct list_head *cur; | ||
| 2253 | struct ubifs_scan_node *sa, *sb; | ||
| 2254 | |||
| 2255 | if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) | ||
| 2256 | return 0; | ||
| 2257 | |||
| 2258 | for (cur = head->next; cur->next != head; cur = cur->next) { | ||
| 2259 | ino_t inuma, inumb; | ||
| 2260 | uint32_t blka, blkb; | ||
| 2261 | |||
| 2262 | cond_resched(); | ||
| 2263 | sa = container_of(cur, struct ubifs_scan_node, list); | ||
| 2264 | sb = container_of(cur->next, struct ubifs_scan_node, list); | ||
| 2265 | |||
| 2266 | if (sa->type != UBIFS_DATA_NODE) { | ||
| 2267 | ubifs_err("bad node type %d", sa->type); | ||
| 2268 | dbg_dump_node(c, sa->node); | ||
| 2269 | return -EINVAL; | ||
| 2270 | } | ||
| 2271 | if (sb->type != UBIFS_DATA_NODE) { | ||
| 2272 | ubifs_err("bad node type %d", sb->type); | ||
| 2273 | dbg_dump_node(c, sb->node); | ||
| 2274 | return -EINVAL; | ||
| 2275 | } | ||
| 2276 | |||
| 2277 | inuma = key_inum(c, &sa->key); | ||
| 2278 | inumb = key_inum(c, &sb->key); | ||
| 2279 | |||
| 2280 | if (inuma < inumb) | ||
| 2281 | continue; | ||
| 2282 | if (inuma > inumb) { | ||
| 2283 | ubifs_err("larger inum %lu goes before inum %lu", | ||
| 2284 | (unsigned long)inuma, (unsigned long)inumb); | ||
| 2285 | goto error_dump; | ||
| 2286 | } | ||
| 2287 | |||
| 2288 | blka = key_block(c, &sa->key); | ||
| 2289 | blkb = key_block(c, &sb->key); | ||
| 2290 | |||
| 2291 | if (blka > blkb) { | ||
| 2292 | ubifs_err("larger block %u goes before %u", blka, blkb); | ||
| 2293 | goto error_dump; | ||
| 2294 | } | ||
| 2295 | if (blka == blkb) { | ||
| 2296 | ubifs_err("two data nodes for the same block"); | ||
| 2297 | goto error_dump; | ||
| 2298 | } | ||
| 2299 | } | ||
| 2300 | |||
| 2301 | return 0; | ||
| 2302 | |||
| 2303 | error_dump: | ||
| 2304 | dbg_dump_node(c, sa->node); | ||
| 2305 | dbg_dump_node(c, sb->node); | ||
| 2306 | return -EINVAL; | ||
| 2307 | } | ||
| 2308 | |||
| 2309 | /** | ||
| 2310 | * dbg_check_nondata_nodes_order - check that list of data nodes is sorted. | ||
| 2311 | * @c: UBIFS file-system description object | ||
| 2312 | * @head: the list of nodes ('struct ubifs_scan_node' objects) | ||
| 2313 | * | ||
| 2314 | * This function returns zero if the list of non-data nodes is sorted correctly, | ||
| 2315 | * and %-EINVAL if not. | ||
| 2316 | */ | ||
| 2317 | int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head) | ||
| 2318 | { | ||
| 2319 | struct list_head *cur; | ||
| 2320 | struct ubifs_scan_node *sa, *sb; | ||
| 2321 | |||
| 2322 | if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) | ||
| 2323 | return 0; | ||
| 2324 | |||
| 2325 | for (cur = head->next; cur->next != head; cur = cur->next) { | ||
| 2326 | ino_t inuma, inumb; | ||
| 2327 | uint32_t hasha, hashb; | ||
| 2328 | |||
| 2329 | cond_resched(); | ||
| 2330 | sa = container_of(cur, struct ubifs_scan_node, list); | ||
| 2331 | sb = container_of(cur->next, struct ubifs_scan_node, list); | ||
| 2332 | |||
| 2333 | if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE && | ||
| 2334 | sa->type != UBIFS_XENT_NODE) { | ||
| 2335 | ubifs_err("bad node type %d", sa->type); | ||
| 2336 | dbg_dump_node(c, sa->node); | ||
| 2337 | return -EINVAL; | ||
| 2338 | } | ||
| 2339 | if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE && | ||
| 2340 | sa->type != UBIFS_XENT_NODE) { | ||
| 2341 | ubifs_err("bad node type %d", sb->type); | ||
| 2342 | dbg_dump_node(c, sb->node); | ||
| 2343 | return -EINVAL; | ||
| 2344 | } | ||
| 2345 | |||
| 2346 | if (sa->type != UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) { | ||
| 2347 | ubifs_err("non-inode node goes before inode node"); | ||
| 2348 | goto error_dump; | ||
| 2349 | } | ||
| 2350 | |||
| 2351 | if (sa->type == UBIFS_INO_NODE && sb->type != UBIFS_INO_NODE) | ||
| 2352 | continue; | ||
| 2353 | |||
| 2354 | if (sa->type == UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) { | ||
| 2355 | /* Inode nodes are sorted in descending size order */ | ||
| 2356 | if (sa->len < sb->len) { | ||
| 2357 | ubifs_err("smaller inode node goes first"); | ||
| 2358 | goto error_dump; | ||
| 2359 | } | ||
| 2360 | continue; | ||
| 2361 | } | ||
| 2362 | |||
| 2363 | /* | ||
| 2364 | * This is either a dentry or xentry, which should be sorted in | ||
| 2365 | * ascending (parent ino, hash) order. | ||
| 2366 | */ | ||
| 2367 | inuma = key_inum(c, &sa->key); | ||
| 2368 | inumb = key_inum(c, &sb->key); | ||
| 2369 | |||
| 2370 | if (inuma < inumb) | ||
| 2371 | continue; | ||
| 2372 | if (inuma > inumb) { | ||
| 2373 | ubifs_err("larger inum %lu goes before inum %lu", | ||
| 2374 | (unsigned long)inuma, (unsigned long)inumb); | ||
| 2375 | goto error_dump; | ||
| 2376 | } | ||
| 2377 | |||
| 2378 | hasha = key_block(c, &sa->key); | ||
| 2379 | hashb = key_block(c, &sb->key); | ||
| 2380 | |||
| 2381 | if (hasha > hashb) { | ||
| 2382 | ubifs_err("larger hash %u goes before %u", hasha, hashb); | ||
| 2383 | goto error_dump; | ||
| 2384 | } | ||
| 2385 | } | ||
| 2386 | |||
| 2387 | return 0; | ||
| 2388 | |||
| 2389 | error_dump: | ||
| 2390 | ubifs_msg("dumping first node"); | ||
| 2391 | dbg_dump_node(c, sa->node); | ||
| 2392 | ubifs_msg("dumping second node"); | ||
| 2393 | dbg_dump_node(c, sb->node); | ||
| 2394 | return -EINVAL; | ||
| 2395 | return 0; | ||
| 2396 | } | ||
| 2397 | |||
| 2242 | static int invocation_cnt; | 2398 | static int invocation_cnt; |
| 2243 | 2399 | ||
| 2244 | int dbg_force_in_the_gaps(void) | 2400 | int dbg_force_in_the_gaps(void) |
| @@ -2625,6 +2781,7 @@ static const struct file_operations dfs_fops = { | |||
| 2625 | .open = open_debugfs_file, | 2781 | .open = open_debugfs_file, |
| 2626 | .write = write_debugfs_file, | 2782 | .write = write_debugfs_file, |
| 2627 | .owner = THIS_MODULE, | 2783 | .owner = THIS_MODULE, |
| 2784 | .llseek = default_llseek, | ||
| 2628 | }; | 2785 | }; |
| 2629 | 2786 | ||
| 2630 | /** | 2787 | /** |
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 29d960101ea..69ebe472915 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h | |||
| @@ -324,6 +324,8 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode, | |||
| 324 | int row, int col); | 324 | int row, int col); |
| 325 | int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode, | 325 | int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode, |
| 326 | loff_t size); | 326 | loff_t size); |
| 327 | int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head); | ||
| 328 | int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head); | ||
| 327 | 329 | ||
| 328 | /* Force the use of in-the-gaps method for testing */ | 330 | /* Force the use of in-the-gaps method for testing */ |
| 329 | 331 | ||
| @@ -465,6 +467,8 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c); | |||
| 465 | #define dbg_check_lprops(c) 0 | 467 | #define dbg_check_lprops(c) 0 |
| 466 | #define dbg_check_lpt_nodes(c, cnode, row, col) 0 | 468 | #define dbg_check_lpt_nodes(c, cnode, row, col) 0 |
| 467 | #define dbg_check_inode_size(c, inode, size) 0 | 469 | #define dbg_check_inode_size(c, inode, size) 0 |
| 470 | #define dbg_check_data_nodes_order(c, head) 0 | ||
| 471 | #define dbg_check_nondata_nodes_order(c, head) 0 | ||
| 468 | #define dbg_force_in_the_gaps_enabled 0 | 472 | #define dbg_force_in_the_gaps_enabled 0 |
| 469 | #define dbg_force_in_the_gaps() 0 | 473 | #define dbg_force_in_the_gaps() 0 |
| 470 | #define dbg_failure_mode 0 | 474 | #define dbg_failure_mode 0 |
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 03ae894c45d..d77db7e3648 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c | |||
| @@ -433,8 +433,9 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping, | |||
| 433 | struct page *page; | 433 | struct page *page; |
| 434 | 434 | ||
| 435 | ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size); | 435 | ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size); |
| 436 | ubifs_assert(!c->ro_media && !c->ro_mount); | ||
| 436 | 437 | ||
| 437 | if (unlikely(c->ro_media)) | 438 | if (unlikely(c->ro_error)) |
| 438 | return -EROFS; | 439 | return -EROFS; |
| 439 | 440 | ||
| 440 | /* Try out the fast-path part first */ | 441 | /* Try out the fast-path part first */ |
| @@ -1439,9 +1440,9 @@ static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vm | |||
| 1439 | 1440 | ||
| 1440 | dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index, | 1441 | dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index, |
| 1441 | i_size_read(inode)); | 1442 | i_size_read(inode)); |
| 1442 | ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY)); | 1443 | ubifs_assert(!c->ro_media && !c->ro_mount); |
| 1443 | 1444 | ||
| 1444 | if (unlikely(c->ro_media)) | 1445 | if (unlikely(c->ro_error)) |
| 1445 | return VM_FAULT_SIGBUS; /* -EROFS */ | 1446 | return VM_FAULT_SIGBUS; /* -EROFS */ |
| 1446 | 1447 | ||
| 1447 | /* | 1448 | /* |
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 918d1582ca0..151f1088282 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c | |||
| @@ -125,10 +125,16 @@ int data_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) | |||
| 125 | struct ubifs_scan_node *sa, *sb; | 125 | struct ubifs_scan_node *sa, *sb; |
| 126 | 126 | ||
| 127 | cond_resched(); | 127 | cond_resched(); |
| 128 | if (a == b) | ||
| 129 | return 0; | ||
| 130 | |||
| 128 | sa = list_entry(a, struct ubifs_scan_node, list); | 131 | sa = list_entry(a, struct ubifs_scan_node, list); |
| 129 | sb = list_entry(b, struct ubifs_scan_node, list); | 132 | sb = list_entry(b, struct ubifs_scan_node, list); |
| 133 | |||
| 130 | ubifs_assert(key_type(c, &sa->key) == UBIFS_DATA_KEY); | 134 | ubifs_assert(key_type(c, &sa->key) == UBIFS_DATA_KEY); |
| 131 | ubifs_assert(key_type(c, &sb->key) == UBIFS_DATA_KEY); | 135 | ubifs_assert(key_type(c, &sb->key) == UBIFS_DATA_KEY); |
| 136 | ubifs_assert(sa->type == UBIFS_DATA_NODE); | ||
| 137 | ubifs_assert(sb->type == UBIFS_DATA_NODE); | ||
| 132 | 138 | ||
| 133 | inuma = key_inum(c, &sa->key); | 139 | inuma = key_inum(c, &sa->key); |
| 134 | inumb = key_inum(c, &sb->key); | 140 | inumb = key_inum(c, &sb->key); |
| @@ -157,28 +163,40 @@ int data_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) | |||
| 157 | */ | 163 | */ |
| 158 | int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) | 164 | int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) |
| 159 | { | 165 | { |
| 160 | int typea, typeb; | ||
| 161 | ino_t inuma, inumb; | 166 | ino_t inuma, inumb; |
| 162 | struct ubifs_info *c = priv; | 167 | struct ubifs_info *c = priv; |
| 163 | struct ubifs_scan_node *sa, *sb; | 168 | struct ubifs_scan_node *sa, *sb; |
| 164 | 169 | ||
| 165 | cond_resched(); | 170 | cond_resched(); |
| 171 | if (a == b) | ||
| 172 | return 0; | ||
| 173 | |||
| 166 | sa = list_entry(a, struct ubifs_scan_node, list); | 174 | sa = list_entry(a, struct ubifs_scan_node, list); |
| 167 | sb = list_entry(b, struct ubifs_scan_node, list); | 175 | sb = list_entry(b, struct ubifs_scan_node, list); |
| 168 | typea = key_type(c, &sa->key); | 176 | |
| 169 | typeb = key_type(c, &sb->key); | 177 | ubifs_assert(key_type(c, &sa->key) != UBIFS_DATA_KEY && |
| 170 | ubifs_assert(typea != UBIFS_DATA_KEY && typeb != UBIFS_DATA_KEY); | 178 | key_type(c, &sb->key) != UBIFS_DATA_KEY); |
| 179 | ubifs_assert(sa->type != UBIFS_DATA_NODE && | ||
| 180 | sb->type != UBIFS_DATA_NODE); | ||
| 171 | 181 | ||
| 172 | /* Inodes go before directory entries */ | 182 | /* Inodes go before directory entries */ |
| 173 | if (typea == UBIFS_INO_KEY) { | 183 | if (sa->type == UBIFS_INO_NODE) { |
| 174 | if (typeb == UBIFS_INO_KEY) | 184 | if (sb->type == UBIFS_INO_NODE) |
| 175 | return sb->len - sa->len; | 185 | return sb->len - sa->len; |
| 176 | return -1; | 186 | return -1; |
| 177 | } | 187 | } |
| 178 | if (typeb == UBIFS_INO_KEY) | 188 | if (sb->type == UBIFS_INO_NODE) |
| 179 | return 1; | 189 | return 1; |
| 180 | 190 | ||
| 181 | ubifs_assert(typea == UBIFS_DENT_KEY && typeb == UBIFS_DENT_KEY); | 191 | ubifs_assert(key_type(c, &sa->key) == UBIFS_DENT_KEY || |
| 192 | key_type(c, &sa->key) == UBIFS_XENT_KEY); | ||
| 193 | ubifs_assert(key_type(c, &sb->key) == UBIFS_DENT_KEY || | ||
| 194 | key_type(c, &sb->key) == UBIFS_XENT_KEY); | ||
| 195 | ubifs_assert(sa->type == UBIFS_DENT_NODE || | ||
| 196 | sa->type == UBIFS_XENT_NODE); | ||
| 197 | ubifs_assert(sb->type == UBIFS_DENT_NODE || | ||
| 198 | sb->type == UBIFS_XENT_NODE); | ||
| 199 | |||
| 182 | inuma = key_inum(c, &sa->key); | 200 | inuma = key_inum(c, &sa->key); |
| 183 | inumb = key_inum(c, &sb->key); | 201 | inumb = key_inum(c, &sb->key); |
| 184 | 202 | ||
| @@ -224,17 +242,33 @@ int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b) | |||
| 224 | static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb, | 242 | static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb, |
| 225 | struct list_head *nondata, int *min) | 243 | struct list_head *nondata, int *min) |
| 226 | { | 244 | { |
| 245 | int err; | ||
| 227 | struct ubifs_scan_node *snod, *tmp; | 246 | struct ubifs_scan_node *snod, *tmp; |
| 228 | 247 | ||
| 229 | *min = INT_MAX; | 248 | *min = INT_MAX; |
| 230 | 249 | ||
| 231 | /* Separate data nodes and non-data nodes */ | 250 | /* Separate data nodes and non-data nodes */ |
| 232 | list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) { | 251 | list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) { |
| 233 | int err; | 252 | ubifs_assert(snod->type == UBIFS_INO_NODE || |
| 253 | snod->type == UBIFS_DATA_NODE || | ||
| 254 | snod->type == UBIFS_DENT_NODE || | ||
| 255 | snod->type == UBIFS_XENT_NODE || | ||
| 256 | snod->type == UBIFS_TRUN_NODE); | ||
| 257 | |||
| 258 | if (snod->type != UBIFS_INO_NODE && | ||
| 259 | snod->type != UBIFS_DATA_NODE && | ||
| 260 | snod->type != UBIFS_DENT_NODE && | ||
| 261 | snod->type != UBIFS_XENT_NODE) { | ||
| 262 | /* Probably truncation node, zap it */ | ||
| 263 | list_del(&snod->list); | ||
| 264 | kfree(snod); | ||
| 265 | continue; | ||
| 266 | } | ||
| 234 | 267 | ||
| 235 | ubifs_assert(snod->type != UBIFS_IDX_NODE); | 268 | ubifs_assert(key_type(c, &snod->key) == UBIFS_DATA_KEY || |
| 236 | ubifs_assert(snod->type != UBIFS_REF_NODE); | 269 | key_type(c, &snod->key) == UBIFS_INO_KEY || |
| 237 | ubifs_assert(snod->type != UBIFS_CS_NODE); | 270 | key_type(c, &snod->key) == UBIFS_DENT_KEY || |
| 271 | key_type(c, &snod->key) == UBIFS_XENT_KEY); | ||
| 238 | 272 | ||
| 239 | err = ubifs_tnc_has_node(c, &snod->key, 0, sleb->lnum, | 273 | err = ubifs_tnc_has_node(c, &snod->key, 0, sleb->lnum, |
| 240 | snod->offs, 0); | 274 | snod->offs, 0); |
| @@ -258,6 +292,13 @@ static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb, | |||
| 258 | /* Sort data and non-data nodes */ | 292 | /* Sort data and non-data nodes */ |
| 259 | list_sort(c, &sleb->nodes, &data_nodes_cmp); | 293 | list_sort(c, &sleb->nodes, &data_nodes_cmp); |
| 260 | list_sort(c, nondata, &nondata_nodes_cmp); | 294 | list_sort(c, nondata, &nondata_nodes_cmp); |
| 295 | |||
| 296 | err = dbg_check_data_nodes_order(c, &sleb->nodes); | ||
| 297 | if (err) | ||
| 298 | return err; | ||
| 299 | err = dbg_check_nondata_nodes_order(c, nondata); | ||
| 300 | if (err) | ||
| 301 | return err; | ||
| 261 | return 0; | 302 | return 0; |
| 262 | } | 303 | } |
| 263 | 304 | ||
| @@ -575,13 +616,14 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway) | |||
| 575 | struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; | 616 | struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; |
| 576 | 617 | ||
| 577 | ubifs_assert_cmt_locked(c); | 618 | ubifs_assert_cmt_locked(c); |
| 619 | ubifs_assert(!c->ro_media && !c->ro_mount); | ||
| 578 | 620 | ||
| 579 | if (ubifs_gc_should_commit(c)) | 621 | if (ubifs_gc_should_commit(c)) |
| 580 | return -EAGAIN; | 622 | return -EAGAIN; |
| 581 | 623 | ||
| 582 | mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); | 624 | mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); |
| 583 | 625 | ||
| 584 | if (c->ro_media) { | 626 | if (c->ro_error) { |
| 585 | ret = -EROFS; | 627 | ret = -EROFS; |
| 586 | goto out_unlock; | 628 | goto out_unlock; |
| 587 | } | 629 | } |
| @@ -677,14 +719,12 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway) | |||
| 677 | 719 | ||
| 678 | ret = ubifs_garbage_collect_leb(c, &lp); | 720 | ret = ubifs_garbage_collect_leb(c, &lp); |
| 679 | if (ret < 0) { | 721 | if (ret < 0) { |
| 680 | if (ret == -EAGAIN || ret == -ENOSPC) { | 722 | if (ret == -EAGAIN) { |
| 681 | /* | 723 | /* |
| 682 | * These codes are not errors, so we have to | 724 | * This is not error, so we have to return the |
| 683 | * return the LEB to lprops. But if the | 725 | * LEB to lprops. But if 'ubifs_return_leb()' |
| 684 | * 'ubifs_return_leb()' function fails, its | 726 | * fails, its failure code is propagated to the |
| 685 | * failure code is propagated to the caller | 727 | * caller instead of the original '-EAGAIN'. |
| 686 | * instead of the original '-EAGAIN' or | ||
| 687 | * '-ENOSPC'. | ||
| 688 | */ | 728 | */ |
| 689 | err = ubifs_return_leb(c, lp.lnum); | 729 | err = ubifs_return_leb(c, lp.lnum); |
| 690 | if (err) | 730 | if (err) |
| @@ -774,8 +814,8 @@ out_unlock: | |||
| 774 | out: | 814 | out: |
| 775 | ubifs_assert(ret < 0); | 815 | ubifs_assert(ret < 0); |
| 776 | ubifs_assert(ret != -ENOSPC && ret != -EAGAIN); | 816 | ubifs_assert(ret != -ENOSPC && ret != -EAGAIN); |
| 777 | ubifs_ro_mode(c, ret); | ||
| 778 | ubifs_wbuf_sync_nolock(wbuf); | 817 | ubifs_wbuf_sync_nolock(wbuf); |
| 818 | ubifs_ro_mode(c, ret); | ||
| 779 | mutex_unlock(&wbuf->io_mutex); | 819 | mutex_unlock(&wbuf->io_mutex); |
| 780 | ubifs_return_leb(c, lp.lnum); | 820 | ubifs_return_leb(c, lp.lnum); |
| 781 | return ret; | 821 | return ret; |
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index bcf5a16f30b..d82173182ee 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c | |||
| @@ -61,8 +61,8 @@ | |||
| 61 | */ | 61 | */ |
| 62 | void ubifs_ro_mode(struct ubifs_info *c, int err) | 62 | void ubifs_ro_mode(struct ubifs_info *c, int err) |
| 63 | { | 63 | { |
| 64 | if (!c->ro_media) { | 64 | if (!c->ro_error) { |
| 65 | c->ro_media = 1; | 65 | c->ro_error = 1; |
| 66 | c->no_chk_data_crc = 0; | 66 | c->no_chk_data_crc = 0; |
| 67 | c->vfs_sb->s_flags |= MS_RDONLY; | 67 | c->vfs_sb->s_flags |= MS_RDONLY; |
| 68 | ubifs_warn("switched to read-only mode, error %d", err); | 68 | ubifs_warn("switched to read-only mode, error %d", err); |
| @@ -356,11 +356,11 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf) | |||
| 356 | 356 | ||
| 357 | dbg_io("LEB %d:%d, %d bytes, jhead %s", | 357 | dbg_io("LEB %d:%d, %d bytes, jhead %s", |
| 358 | wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead)); | 358 | wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead)); |
| 359 | ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY)); | ||
| 360 | ubifs_assert(!(wbuf->avail & 7)); | 359 | ubifs_assert(!(wbuf->avail & 7)); |
| 361 | ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size); | 360 | ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size); |
| 361 | ubifs_assert(!c->ro_media && !c->ro_mount); | ||
| 362 | 362 | ||
| 363 | if (c->ro_media) | 363 | if (c->ro_error) |
| 364 | return -EROFS; | 364 | return -EROFS; |
| 365 | 365 | ||
| 366 | ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail); | 366 | ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail); |
| @@ -440,11 +440,12 @@ int ubifs_bg_wbufs_sync(struct ubifs_info *c) | |||
| 440 | { | 440 | { |
| 441 | int err, i; | 441 | int err, i; |
| 442 | 442 | ||
| 443 | ubifs_assert(!c->ro_media && !c->ro_mount); | ||
| 443 | if (!c->need_wbuf_sync) | 444 | if (!c->need_wbuf_sync) |
| 444 | return 0; | 445 | return 0; |
| 445 | c->need_wbuf_sync = 0; | 446 | c->need_wbuf_sync = 0; |
| 446 | 447 | ||
| 447 | if (c->ro_media) { | 448 | if (c->ro_error) { |
| 448 | err = -EROFS; | 449 | err = -EROFS; |
| 449 | goto out_timers; | 450 | goto out_timers; |
| 450 | } | 451 | } |
| @@ -519,6 +520,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) | |||
| 519 | ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size); | 520 | ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size); |
| 520 | ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size); | 521 | ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size); |
| 521 | ubifs_assert(mutex_is_locked(&wbuf->io_mutex)); | 522 | ubifs_assert(mutex_is_locked(&wbuf->io_mutex)); |
| 523 | ubifs_assert(!c->ro_media && !c->ro_mount); | ||
| 522 | 524 | ||
| 523 | if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) { | 525 | if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) { |
| 524 | err = -ENOSPC; | 526 | err = -ENOSPC; |
| @@ -527,7 +529,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) | |||
| 527 | 529 | ||
| 528 | cancel_wbuf_timer_nolock(wbuf); | 530 | cancel_wbuf_timer_nolock(wbuf); |
| 529 | 531 | ||
| 530 | if (c->ro_media) | 532 | if (c->ro_error) |
| 531 | return -EROFS; | 533 | return -EROFS; |
| 532 | 534 | ||
| 533 | if (aligned_len <= wbuf->avail) { | 535 | if (aligned_len <= wbuf->avail) { |
| @@ -663,8 +665,9 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum, | |||
| 663 | buf_len); | 665 | buf_len); |
| 664 | ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0); | 666 | ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0); |
| 665 | ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size); | 667 | ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size); |
| 668 | ubifs_assert(!c->ro_media && !c->ro_mount); | ||
| 666 | 669 | ||
| 667 | if (c->ro_media) | 670 | if (c->ro_error) |
| 668 | return -EROFS; | 671 | return -EROFS; |
| 669 | 672 | ||
| 670 | ubifs_prepare_node(c, buf, len, 1); | 673 | ubifs_prepare_node(c, buf, len, 1); |
| @@ -815,7 +818,8 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, | |||
| 815 | return 0; | 818 | return 0; |
| 816 | 819 | ||
| 817 | out: | 820 | out: |
| 818 | ubifs_err("bad node at LEB %d:%d", lnum, offs); | 821 | ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs, |
| 822 | ubi_is_mapped(c->ubi, lnum)); | ||
| 819 | dbg_dump_node(c, buf); | 823 | dbg_dump_node(c, buf); |
| 820 | dbg_dump_stack(); | 824 | dbg_dump_stack(); |
| 821 | return -EINVAL; | 825 | return -EINVAL; |
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index d321baeca68..914f1bd89e5 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c | |||
| @@ -122,11 +122,12 @@ static int reserve_space(struct ubifs_info *c, int jhead, int len) | |||
| 122 | * better to try to allocate space at the ends of eraseblocks. This is | 122 | * better to try to allocate space at the ends of eraseblocks. This is |
| 123 | * what the squeeze parameter does. | 123 | * what the squeeze parameter does. |
| 124 | */ | 124 | */ |
| 125 | ubifs_assert(!c->ro_media && !c->ro_mount); | ||
| 125 | squeeze = (jhead == BASEHD); | 126 | squeeze = (jhead == BASEHD); |
| 126 | again: | 127 | again: |
| 127 | mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); | 128 | mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); |
| 128 | 129 | ||
| 129 | if (c->ro_media) { | 130 | if (c->ro_error) { |
| 130 | err = -EROFS; | 131 | err = -EROFS; |
| 131 | goto out_unlock; | 132 | goto out_unlock; |
| 132 | } | 133 | } |
diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h index 0f530c684f0..92a8491a8f8 100644 --- a/fs/ubifs/key.h +++ b/fs/ubifs/key.h | |||
| @@ -306,6 +306,20 @@ static inline void trun_key_init(const struct ubifs_info *c, | |||
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | /** | 308 | /** |
| 309 | * invalid_key_init - initialize invalid node key. | ||
| 310 | * @c: UBIFS file-system description object | ||
| 311 | * @key: key to initialize | ||
| 312 | * | ||
| 313 | * This is a helper function which marks a @key object as invalid. | ||
| 314 | */ | ||
| 315 | static inline void invalid_key_init(const struct ubifs_info *c, | ||
| 316 | union ubifs_key *key) | ||
| 317 | { | ||
| 318 | key->u32[0] = 0xDEADBEAF; | ||
| 319 | key->u32[1] = UBIFS_INVALID_KEY; | ||
| 320 | } | ||
| 321 | |||
| 322 | /** | ||
| 309 | * key_type - get key type. | 323 | * key_type - get key type. |
| 310 | * @c: UBIFS file-system description object | 324 | * @c: UBIFS file-system description object |
| 311 | * @key: key to get type of | 325 | * @key: key to get type of |
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c index c345e125f42..4d0cb124146 100644 --- a/fs/ubifs/log.c +++ b/fs/ubifs/log.c | |||
| @@ -159,7 +159,7 @@ void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud) | |||
| 159 | jhead = &c->jheads[bud->jhead]; | 159 | jhead = &c->jheads[bud->jhead]; |
| 160 | list_add_tail(&bud->list, &jhead->buds_list); | 160 | list_add_tail(&bud->list, &jhead->buds_list); |
| 161 | } else | 161 | } else |
| 162 | ubifs_assert(c->replaying && (c->vfs_sb->s_flags & MS_RDONLY)); | 162 | ubifs_assert(c->replaying && c->ro_mount); |
| 163 | 163 | ||
| 164 | /* | 164 | /* |
| 165 | * Note, although this is a new bud, we anyway account this space now, | 165 | * Note, although this is a new bud, we anyway account this space now, |
| @@ -223,8 +223,8 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs) | |||
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | mutex_lock(&c->log_mutex); | 225 | mutex_lock(&c->log_mutex); |
| 226 | 226 | ubifs_assert(!c->ro_media && !c->ro_mount); | |
| 227 | if (c->ro_media) { | 227 | if (c->ro_error) { |
| 228 | err = -EROFS; | 228 | err = -EROFS; |
| 229 | goto out_unlock; | 229 | goto out_unlock; |
| 230 | } | 230 | } |
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index 0084a33c4c6..72775d35b99 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c | |||
| @@ -1363,6 +1363,7 @@ static int read_lsave(struct ubifs_info *c) | |||
| 1363 | goto out; | 1363 | goto out; |
| 1364 | for (i = 0; i < c->lsave_cnt; i++) { | 1364 | for (i = 0; i < c->lsave_cnt; i++) { |
| 1365 | int lnum = c->lsave[i]; | 1365 | int lnum = c->lsave[i]; |
| 1366 | struct ubifs_lprops *lprops; | ||
| 1366 | 1367 | ||
| 1367 | /* | 1368 | /* |
| 1368 | * Due to automatic resizing, the values in the lsave table | 1369 | * Due to automatic resizing, the values in the lsave table |
| @@ -1370,7 +1371,11 @@ static int read_lsave(struct ubifs_info *c) | |||
| 1370 | */ | 1371 | */ |
| 1371 | if (lnum >= c->leb_cnt) | 1372 | if (lnum >= c->leb_cnt) |
| 1372 | continue; | 1373 | continue; |
| 1373 | ubifs_lpt_lookup(c, lnum); | 1374 | lprops = ubifs_lpt_lookup(c, lnum); |
| 1375 | if (IS_ERR(lprops)) { | ||
| 1376 | err = PTR_ERR(lprops); | ||
| 1377 | goto out; | ||
| 1378 | } | ||
| 1374 | } | 1379 | } |
| 1375 | out: | 1380 | out: |
| 1376 | vfree(buf); | 1381 | vfree(buf); |
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c index d12535b7fc7..5c90dec5db0 100644 --- a/fs/ubifs/lpt_commit.c +++ b/fs/ubifs/lpt_commit.c | |||
| @@ -705,6 +705,9 @@ static int make_tree_dirty(struct ubifs_info *c) | |||
| 705 | struct ubifs_pnode *pnode; | 705 | struct ubifs_pnode *pnode; |
| 706 | 706 | ||
| 707 | pnode = pnode_lookup(c, 0); | 707 | pnode = pnode_lookup(c, 0); |
| 708 | if (IS_ERR(pnode)) | ||
| 709 | return PTR_ERR(pnode); | ||
| 710 | |||
| 708 | while (pnode) { | 711 | while (pnode) { |
| 709 | do_make_pnode_dirty(c, pnode); | 712 | do_make_pnode_dirty(c, pnode); |
| 710 | pnode = next_pnode_to_dirty(c, pnode); | 713 | pnode = next_pnode_to_dirty(c, pnode); |
diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c index 28beaeedadc..21f47afdacf 100644 --- a/fs/ubifs/master.c +++ b/fs/ubifs/master.c | |||
| @@ -361,7 +361,8 @@ int ubifs_write_master(struct ubifs_info *c) | |||
| 361 | { | 361 | { |
| 362 | int err, lnum, offs, len; | 362 | int err, lnum, offs, len; |
| 363 | 363 | ||
| 364 | if (c->ro_media) | 364 | ubifs_assert(!c->ro_media && !c->ro_mount); |
| 365 | if (c->ro_error) | ||
| 365 | return -EROFS; | 366 | return -EROFS; |
| 366 | 367 | ||
| 367 | lnum = UBIFS_MST_LNUM; | 368 | lnum = UBIFS_MST_LNUM; |
diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h index 4fa81d867e4..c3de04dc952 100644 --- a/fs/ubifs/misc.h +++ b/fs/ubifs/misc.h | |||
| @@ -132,7 +132,8 @@ static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum) | |||
| 132 | { | 132 | { |
| 133 | int err; | 133 | int err; |
| 134 | 134 | ||
| 135 | if (c->ro_media) | 135 | ubifs_assert(!c->ro_media && !c->ro_mount); |
| 136 | if (c->ro_error) | ||
| 136 | return -EROFS; | 137 | return -EROFS; |
| 137 | err = ubi_leb_unmap(c->ubi, lnum); | 138 | err = ubi_leb_unmap(c->ubi, lnum); |
| 138 | if (err) { | 139 | if (err) { |
| @@ -159,7 +160,8 @@ static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum, | |||
| 159 | { | 160 | { |
| 160 | int err; | 161 | int err; |
| 161 | 162 | ||
| 162 | if (c->ro_media) | 163 | ubifs_assert(!c->ro_media && !c->ro_mount); |
| 164 | if (c->ro_error) | ||
| 163 | return -EROFS; | 165 | return -EROFS; |
| 164 | err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype); | 166 | err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype); |
| 165 | if (err) { | 167 | if (err) { |
| @@ -186,7 +188,8 @@ static inline int ubifs_leb_change(const struct ubifs_info *c, int lnum, | |||
| 186 | { | 188 | { |
| 187 | int err; | 189 | int err; |
| 188 | 190 | ||
| 189 | if (c->ro_media) | 191 | ubifs_assert(!c->ro_media && !c->ro_mount); |
| 192 | if (c->ro_error) | ||
| 190 | return -EROFS; | 193 | return -EROFS; |
| 191 | err = ubi_leb_change(c->ubi, lnum, buf, len, dtype); | 194 | err = ubi_leb_change(c->ubi, lnum, buf, len, dtype); |
| 192 | if (err) { | 195 | if (err) { |
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index daae9e1f538..77e9b874b6c 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c | |||
| @@ -292,7 +292,7 @@ int ubifs_recover_master_node(struct ubifs_info *c) | |||
| 292 | 292 | ||
| 293 | memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ); | 293 | memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ); |
| 294 | 294 | ||
| 295 | if ((c->vfs_sb->s_flags & MS_RDONLY)) { | 295 | if (c->ro_mount) { |
| 296 | /* Read-only mode. Keep a copy for switching to rw mode */ | 296 | /* Read-only mode. Keep a copy for switching to rw mode */ |
| 297 | c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL); | 297 | c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL); |
| 298 | if (!c->rcvrd_mst_node) { | 298 | if (!c->rcvrd_mst_node) { |
| @@ -469,7 +469,7 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb, | |||
| 469 | endpt = snod->offs + snod->len; | 469 | endpt = snod->offs + snod->len; |
| 470 | } | 470 | } |
| 471 | 471 | ||
| 472 | if ((c->vfs_sb->s_flags & MS_RDONLY) && !c->remounting_rw) { | 472 | if (c->ro_mount && !c->remounting_rw) { |
| 473 | /* Add to recovery list */ | 473 | /* Add to recovery list */ |
| 474 | struct ubifs_unclean_leb *ucleb; | 474 | struct ubifs_unclean_leb *ucleb; |
| 475 | 475 | ||
| @@ -772,7 +772,8 @@ out_free: | |||
| 772 | * @sbuf: LEB-sized buffer to use | 772 | * @sbuf: LEB-sized buffer to use |
| 773 | * | 773 | * |
| 774 | * This function does a scan of a LEB, but caters for errors that might have | 774 | * This function does a scan of a LEB, but caters for errors that might have |
| 775 | * been caused by the unclean unmount from which we are attempting to recover. | 775 | * been caused by unclean reboots from which we are attempting to recover |
| 776 | * (assume that only the last log LEB can be corrupted by an unclean reboot). | ||
| 776 | * | 777 | * |
| 777 | * This function returns %0 on success and a negative error code on failure. | 778 | * This function returns %0 on success and a negative error code on failure. |
| 778 | */ | 779 | */ |
| @@ -883,7 +884,7 @@ int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf) | |||
| 883 | { | 884 | { |
| 884 | int err; | 885 | int err; |
| 885 | 886 | ||
| 886 | ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY) || c->remounting_rw); | 887 | ubifs_assert(!c->ro_mount || c->remounting_rw); |
| 887 | 888 | ||
| 888 | dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs); | 889 | dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs); |
| 889 | err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf); | 890 | err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf); |
| @@ -1461,7 +1462,7 @@ int ubifs_recover_size(struct ubifs_info *c) | |||
| 1461 | } | 1462 | } |
| 1462 | } | 1463 | } |
| 1463 | if (e->exists && e->i_size < e->d_size) { | 1464 | if (e->exists && e->i_size < e->d_size) { |
| 1464 | if (!e->inode && (c->vfs_sb->s_flags & MS_RDONLY)) { | 1465 | if (!e->inode && c->ro_mount) { |
| 1465 | /* Fix the inode size and pin it in memory */ | 1466 | /* Fix the inode size and pin it in memory */ |
| 1466 | struct inode *inode; | 1467 | struct inode *inode; |
| 1467 | 1468 | ||
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index 5c2d6d759a3..eed0fcff8d7 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c | |||
| @@ -627,8 +627,7 @@ static int replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead, | |||
| 627 | ubifs_assert(sleb->endpt - offs >= used); | 627 | ubifs_assert(sleb->endpt - offs >= used); |
| 628 | ubifs_assert(sleb->endpt % c->min_io_size == 0); | 628 | ubifs_assert(sleb->endpt % c->min_io_size == 0); |
| 629 | 629 | ||
| 630 | if (sleb->endpt + c->min_io_size <= c->leb_size && | 630 | if (sleb->endpt + c->min_io_size <= c->leb_size && !c->ro_mount) |
| 631 | !(c->vfs_sb->s_flags & MS_RDONLY)) | ||
| 632 | err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum, | 631 | err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum, |
| 633 | sleb->endpt, UBI_SHORTTERM); | 632 | sleb->endpt, UBI_SHORTTERM); |
| 634 | 633 | ||
| @@ -840,6 +839,11 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) | |||
| 840 | if (IS_ERR(sleb)) { | 839 | if (IS_ERR(sleb)) { |
| 841 | if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery) | 840 | if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery) |
| 842 | return PTR_ERR(sleb); | 841 | return PTR_ERR(sleb); |
| 842 | /* | ||
| 843 | * Note, the below function will recover this log LEB only if | ||
| 844 | * it is the last, because unclean reboots can possibly corrupt | ||
| 845 | * only the tail of the log. | ||
| 846 | */ | ||
| 843 | sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf); | 847 | sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf); |
| 844 | if (IS_ERR(sleb)) | 848 | if (IS_ERR(sleb)) |
| 845 | return PTR_ERR(sleb); | 849 | return PTR_ERR(sleb); |
| @@ -851,7 +855,6 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) | |||
| 851 | } | 855 | } |
| 852 | 856 | ||
| 853 | node = sleb->buf; | 857 | node = sleb->buf; |
| 854 | |||
| 855 | snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list); | 858 | snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list); |
| 856 | if (c->cs_sqnum == 0) { | 859 | if (c->cs_sqnum == 0) { |
| 857 | /* | 860 | /* |
| @@ -898,7 +901,6 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) | |||
| 898 | } | 901 | } |
| 899 | 902 | ||
| 900 | list_for_each_entry(snod, &sleb->nodes, list) { | 903 | list_for_each_entry(snod, &sleb->nodes, list) { |
| 901 | |||
| 902 | cond_resched(); | 904 | cond_resched(); |
| 903 | 905 | ||
| 904 | if (snod->sqnum >= SQNUM_WATERMARK) { | 906 | if (snod->sqnum >= SQNUM_WATERMARK) { |
| @@ -1011,7 +1013,6 @@ out: | |||
| 1011 | int ubifs_replay_journal(struct ubifs_info *c) | 1013 | int ubifs_replay_journal(struct ubifs_info *c) |
| 1012 | { | 1014 | { |
| 1013 | int err, i, lnum, offs, free; | 1015 | int err, i, lnum, offs, free; |
| 1014 | void *sbuf = NULL; | ||
| 1015 | 1016 | ||
| 1016 | BUILD_BUG_ON(UBIFS_TRUN_KEY > 5); | 1017 | BUILD_BUG_ON(UBIFS_TRUN_KEY > 5); |
| 1017 | 1018 | ||
| @@ -1026,14 +1027,8 @@ int ubifs_replay_journal(struct ubifs_info *c) | |||
| 1026 | return -EINVAL; | 1027 | return -EINVAL; |
| 1027 | } | 1028 | } |
| 1028 | 1029 | ||
| 1029 | sbuf = vmalloc(c->leb_size); | ||
| 1030 | if (!sbuf) | ||
| 1031 | return -ENOMEM; | ||
| 1032 | |||
| 1033 | dbg_mnt("start replaying the journal"); | 1030 | dbg_mnt("start replaying the journal"); |
| 1034 | |||
| 1035 | c->replaying = 1; | 1031 | c->replaying = 1; |
| 1036 | |||
| 1037 | lnum = c->ltail_lnum = c->lhead_lnum; | 1032 | lnum = c->ltail_lnum = c->lhead_lnum; |
| 1038 | offs = c->lhead_offs; | 1033 | offs = c->lhead_offs; |
| 1039 | 1034 | ||
| @@ -1046,7 +1041,7 @@ int ubifs_replay_journal(struct ubifs_info *c) | |||
| 1046 | lnum = UBIFS_LOG_LNUM; | 1041 | lnum = UBIFS_LOG_LNUM; |
| 1047 | offs = 0; | 1042 | offs = 0; |
| 1048 | } | 1043 | } |
| 1049 | err = replay_log_leb(c, lnum, offs, sbuf); | 1044 | err = replay_log_leb(c, lnum, offs, c->sbuf); |
| 1050 | if (err == 1) | 1045 | if (err == 1) |
| 1051 | /* We hit the end of the log */ | 1046 | /* We hit the end of the log */ |
| 1052 | break; | 1047 | break; |
| @@ -1079,7 +1074,6 @@ int ubifs_replay_journal(struct ubifs_info *c) | |||
| 1079 | out: | 1074 | out: |
| 1080 | destroy_replay_tree(c); | 1075 | destroy_replay_tree(c); |
| 1081 | destroy_bud_list(c); | 1076 | destroy_bud_list(c); |
| 1082 | vfree(sbuf); | ||
| 1083 | c->replaying = 0; | 1077 | c->replaying = 0; |
| 1084 | return err; | 1078 | return err; |
| 1085 | } | 1079 | } |
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index 96cb62c8a9d..bf31b4729e5 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c | |||
| @@ -542,11 +542,8 @@ int ubifs_read_superblock(struct ubifs_info *c) | |||
| 542 | * due to the unavailability of time-travelling equipment. | 542 | * due to the unavailability of time-travelling equipment. |
| 543 | */ | 543 | */ |
| 544 | if (c->fmt_version > UBIFS_FORMAT_VERSION) { | 544 | if (c->fmt_version > UBIFS_FORMAT_VERSION) { |
| 545 | struct super_block *sb = c->vfs_sb; | 545 | ubifs_assert(!c->ro_media || c->ro_mount); |
| 546 | int mounting_ro = sb->s_flags & MS_RDONLY; | 546 | if (!c->ro_mount || |
| 547 | |||
| 548 | ubifs_assert(!c->ro_media || mounting_ro); | ||
| 549 | if (!mounting_ro || | ||
| 550 | c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) { | 547 | c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) { |
| 551 | ubifs_err("on-flash format version is w%d/r%d, but " | 548 | ubifs_err("on-flash format version is w%d/r%d, but " |
| 552 | "software only supports up to version " | 549 | "software only supports up to version " |
| @@ -624,7 +621,7 @@ int ubifs_read_superblock(struct ubifs_info *c) | |||
| 624 | c->old_leb_cnt = c->leb_cnt; | 621 | c->old_leb_cnt = c->leb_cnt; |
| 625 | if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) { | 622 | if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) { |
| 626 | c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size); | 623 | c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size); |
| 627 | if (c->vfs_sb->s_flags & MS_RDONLY) | 624 | if (c->ro_mount) |
| 628 | dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs", | 625 | dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs", |
| 629 | c->old_leb_cnt, c->leb_cnt); | 626 | c->old_leb_cnt, c->leb_cnt); |
| 630 | else { | 627 | else { |
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c index 96c52538419..3e1ee57dbea 100644 --- a/fs/ubifs/scan.c +++ b/fs/ubifs/scan.c | |||
| @@ -197,7 +197,7 @@ int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb, | |||
| 197 | struct ubifs_ino_node *ino = buf; | 197 | struct ubifs_ino_node *ino = buf; |
| 198 | struct ubifs_scan_node *snod; | 198 | struct ubifs_scan_node *snod; |
| 199 | 199 | ||
| 200 | snod = kzalloc(sizeof(struct ubifs_scan_node), GFP_NOFS); | 200 | snod = kmalloc(sizeof(struct ubifs_scan_node), GFP_NOFS); |
| 201 | if (!snod) | 201 | if (!snod) |
| 202 | return -ENOMEM; | 202 | return -ENOMEM; |
| 203 | 203 | ||
| @@ -212,13 +212,15 @@ int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb, | |||
| 212 | case UBIFS_DENT_NODE: | 212 | case UBIFS_DENT_NODE: |
| 213 | case UBIFS_XENT_NODE: | 213 | case UBIFS_XENT_NODE: |
| 214 | case UBIFS_DATA_NODE: | 214 | case UBIFS_DATA_NODE: |
| 215 | case UBIFS_TRUN_NODE: | ||
| 216 | /* | 215 | /* |
| 217 | * The key is in the same place in all keyed | 216 | * The key is in the same place in all keyed |
| 218 | * nodes. | 217 | * nodes. |
| 219 | */ | 218 | */ |
| 220 | key_read(c, &ino->key, &snod->key); | 219 | key_read(c, &ino->key, &snod->key); |
| 221 | break; | 220 | break; |
| 221 | default: | ||
| 222 | invalid_key_init(c, &snod->key); | ||
| 223 | break; | ||
| 222 | } | 224 | } |
| 223 | list_add_tail(&snod->list, &sleb->nodes); | 225 | list_add_tail(&snod->list, &sleb->nodes); |
| 224 | sleb->nodes_cnt += 1; | 226 | sleb->nodes_cnt += 1; |
diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c index 0b201114a5a..46961c00323 100644 --- a/fs/ubifs/shrinker.c +++ b/fs/ubifs/shrinker.c | |||
| @@ -250,7 +250,7 @@ static int kick_a_thread(void) | |||
| 250 | dirty_zn_cnt = atomic_long_read(&c->dirty_zn_cnt); | 250 | dirty_zn_cnt = atomic_long_read(&c->dirty_zn_cnt); |
| 251 | 251 | ||
| 252 | if (!dirty_zn_cnt || c->cmt_state == COMMIT_BROKEN || | 252 | if (!dirty_zn_cnt || c->cmt_state == COMMIT_BROKEN || |
| 253 | c->ro_media) { | 253 | c->ro_mount || c->ro_error) { |
| 254 | mutex_unlock(&c->umount_mutex); | 254 | mutex_unlock(&c->umount_mutex); |
| 255 | continue; | 255 | continue; |
| 256 | } | 256 | } |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index cd5900b85d3..9a47c9f0ad0 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
| @@ -1137,11 +1137,11 @@ static int check_free_space(struct ubifs_info *c) | |||
| 1137 | */ | 1137 | */ |
| 1138 | static int mount_ubifs(struct ubifs_info *c) | 1138 | static int mount_ubifs(struct ubifs_info *c) |
| 1139 | { | 1139 | { |
| 1140 | struct super_block *sb = c->vfs_sb; | 1140 | int err; |
| 1141 | int err, mounted_read_only = (sb->s_flags & MS_RDONLY); | ||
| 1142 | long long x; | 1141 | long long x; |
| 1143 | size_t sz; | 1142 | size_t sz; |
| 1144 | 1143 | ||
| 1144 | c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY); | ||
| 1145 | err = init_constants_early(c); | 1145 | err = init_constants_early(c); |
| 1146 | if (err) | 1146 | if (err) |
| 1147 | return err; | 1147 | return err; |
| @@ -1154,7 +1154,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1154 | if (err) | 1154 | if (err) |
| 1155 | goto out_free; | 1155 | goto out_free; |
| 1156 | 1156 | ||
| 1157 | if (c->empty && (mounted_read_only || c->ro_media)) { | 1157 | if (c->empty && (c->ro_mount || c->ro_media)) { |
| 1158 | /* | 1158 | /* |
| 1159 | * This UBI volume is empty, and read-only, or the file system | 1159 | * This UBI volume is empty, and read-only, or the file system |
| 1160 | * is mounted read-only - we cannot format it. | 1160 | * is mounted read-only - we cannot format it. |
| @@ -1165,7 +1165,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1165 | goto out_free; | 1165 | goto out_free; |
| 1166 | } | 1166 | } |
| 1167 | 1167 | ||
| 1168 | if (c->ro_media && !mounted_read_only) { | 1168 | if (c->ro_media && !c->ro_mount) { |
| 1169 | ubifs_err("cannot mount read-write - read-only media"); | 1169 | ubifs_err("cannot mount read-write - read-only media"); |
| 1170 | err = -EROFS; | 1170 | err = -EROFS; |
| 1171 | goto out_free; | 1171 | goto out_free; |
| @@ -1185,7 +1185,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1185 | if (!c->sbuf) | 1185 | if (!c->sbuf) |
| 1186 | goto out_free; | 1186 | goto out_free; |
| 1187 | 1187 | ||
| 1188 | if (!mounted_read_only) { | 1188 | if (!c->ro_mount) { |
| 1189 | c->ileb_buf = vmalloc(c->leb_size); | 1189 | c->ileb_buf = vmalloc(c->leb_size); |
| 1190 | if (!c->ileb_buf) | 1190 | if (!c->ileb_buf) |
| 1191 | goto out_free; | 1191 | goto out_free; |
| @@ -1228,7 +1228,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1228 | } | 1228 | } |
| 1229 | 1229 | ||
| 1230 | sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); | 1230 | sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); |
| 1231 | if (!mounted_read_only) { | 1231 | if (!c->ro_mount) { |
| 1232 | err = alloc_wbufs(c); | 1232 | err = alloc_wbufs(c); |
| 1233 | if (err) | 1233 | if (err) |
| 1234 | goto out_cbuf; | 1234 | goto out_cbuf; |
| @@ -1254,12 +1254,12 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1254 | if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) { | 1254 | if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) { |
| 1255 | ubifs_msg("recovery needed"); | 1255 | ubifs_msg("recovery needed"); |
| 1256 | c->need_recovery = 1; | 1256 | c->need_recovery = 1; |
| 1257 | if (!mounted_read_only) { | 1257 | if (!c->ro_mount) { |
| 1258 | err = ubifs_recover_inl_heads(c, c->sbuf); | 1258 | err = ubifs_recover_inl_heads(c, c->sbuf); |
| 1259 | if (err) | 1259 | if (err) |
| 1260 | goto out_master; | 1260 | goto out_master; |
| 1261 | } | 1261 | } |
| 1262 | } else if (!mounted_read_only) { | 1262 | } else if (!c->ro_mount) { |
| 1263 | /* | 1263 | /* |
| 1264 | * Set the "dirty" flag so that if we reboot uncleanly we | 1264 | * Set the "dirty" flag so that if we reboot uncleanly we |
| 1265 | * will notice this immediately on the next mount. | 1265 | * will notice this immediately on the next mount. |
| @@ -1270,7 +1270,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1270 | goto out_master; | 1270 | goto out_master; |
| 1271 | } | 1271 | } |
| 1272 | 1272 | ||
| 1273 | err = ubifs_lpt_init(c, 1, !mounted_read_only); | 1273 | err = ubifs_lpt_init(c, 1, !c->ro_mount); |
| 1274 | if (err) | 1274 | if (err) |
| 1275 | goto out_lpt; | 1275 | goto out_lpt; |
| 1276 | 1276 | ||
| @@ -1285,11 +1285,11 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1285 | /* Calculate 'min_idx_lebs' after journal replay */ | 1285 | /* Calculate 'min_idx_lebs' after journal replay */ |
| 1286 | c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); | 1286 | c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); |
| 1287 | 1287 | ||
| 1288 | err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only); | 1288 | err = ubifs_mount_orphans(c, c->need_recovery, c->ro_mount); |
| 1289 | if (err) | 1289 | if (err) |
| 1290 | goto out_orphans; | 1290 | goto out_orphans; |
| 1291 | 1291 | ||
| 1292 | if (!mounted_read_only) { | 1292 | if (!c->ro_mount) { |
| 1293 | int lnum; | 1293 | int lnum; |
| 1294 | 1294 | ||
| 1295 | err = check_free_space(c); | 1295 | err = check_free_space(c); |
| @@ -1351,7 +1351,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1351 | spin_unlock(&ubifs_infos_lock); | 1351 | spin_unlock(&ubifs_infos_lock); |
| 1352 | 1352 | ||
| 1353 | if (c->need_recovery) { | 1353 | if (c->need_recovery) { |
| 1354 | if (mounted_read_only) | 1354 | if (c->ro_mount) |
| 1355 | ubifs_msg("recovery deferred"); | 1355 | ubifs_msg("recovery deferred"); |
| 1356 | else { | 1356 | else { |
| 1357 | c->need_recovery = 0; | 1357 | c->need_recovery = 0; |
| @@ -1378,7 +1378,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1378 | 1378 | ||
| 1379 | ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"", | 1379 | ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"", |
| 1380 | c->vi.ubi_num, c->vi.vol_id, c->vi.name); | 1380 | c->vi.ubi_num, c->vi.vol_id, c->vi.name); |
| 1381 | if (mounted_read_only) | 1381 | if (c->ro_mount) |
| 1382 | ubifs_msg("mounted read-only"); | 1382 | ubifs_msg("mounted read-only"); |
| 1383 | x = (long long)c->main_lebs * c->leb_size; | 1383 | x = (long long)c->main_lebs * c->leb_size; |
| 1384 | ubifs_msg("file system size: %lld bytes (%lld KiB, %lld MiB, %d " | 1384 | ubifs_msg("file system size: %lld bytes (%lld KiB, %lld MiB, %d " |
| @@ -1640,7 +1640,7 @@ static int ubifs_remount_rw(struct ubifs_info *c) | |||
| 1640 | } | 1640 | } |
| 1641 | 1641 | ||
| 1642 | dbg_gen("re-mounted read-write"); | 1642 | dbg_gen("re-mounted read-write"); |
| 1643 | c->vfs_sb->s_flags &= ~MS_RDONLY; | 1643 | c->ro_mount = 0; |
| 1644 | c->remounting_rw = 0; | 1644 | c->remounting_rw = 0; |
| 1645 | c->always_chk_crc = 0; | 1645 | c->always_chk_crc = 0; |
| 1646 | err = dbg_check_space_info(c); | 1646 | err = dbg_check_space_info(c); |
| @@ -1676,7 +1676,7 @@ static void ubifs_remount_ro(struct ubifs_info *c) | |||
| 1676 | int i, err; | 1676 | int i, err; |
| 1677 | 1677 | ||
| 1678 | ubifs_assert(!c->need_recovery); | 1678 | ubifs_assert(!c->need_recovery); |
| 1679 | ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY)); | 1679 | ubifs_assert(!c->ro_mount); |
| 1680 | 1680 | ||
| 1681 | mutex_lock(&c->umount_mutex); | 1681 | mutex_lock(&c->umount_mutex); |
| 1682 | if (c->bgt) { | 1682 | if (c->bgt) { |
| @@ -1686,10 +1686,8 @@ static void ubifs_remount_ro(struct ubifs_info *c) | |||
| 1686 | 1686 | ||
| 1687 | dbg_save_space_info(c); | 1687 | dbg_save_space_info(c); |
| 1688 | 1688 | ||
| 1689 | for (i = 0; i < c->jhead_cnt; i++) { | 1689 | for (i = 0; i < c->jhead_cnt; i++) |
| 1690 | ubifs_wbuf_sync(&c->jheads[i].wbuf); | 1690 | ubifs_wbuf_sync(&c->jheads[i].wbuf); |
| 1691 | hrtimer_cancel(&c->jheads[i].wbuf.timer); | ||
| 1692 | } | ||
| 1693 | 1691 | ||
| 1694 | c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); | 1692 | c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); |
| 1695 | c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); | 1693 | c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); |
| @@ -1704,6 +1702,7 @@ static void ubifs_remount_ro(struct ubifs_info *c) | |||
| 1704 | vfree(c->ileb_buf); | 1702 | vfree(c->ileb_buf); |
| 1705 | c->ileb_buf = NULL; | 1703 | c->ileb_buf = NULL; |
| 1706 | ubifs_lpt_free(c, 1); | 1704 | ubifs_lpt_free(c, 1); |
| 1705 | c->ro_mount = 1; | ||
| 1707 | err = dbg_check_space_info(c); | 1706 | err = dbg_check_space_info(c); |
| 1708 | if (err) | 1707 | if (err) |
| 1709 | ubifs_ro_mode(c, err); | 1708 | ubifs_ro_mode(c, err); |
| @@ -1735,7 +1734,7 @@ static void ubifs_put_super(struct super_block *sb) | |||
| 1735 | * the mutex is locked. | 1734 | * the mutex is locked. |
| 1736 | */ | 1735 | */ |
| 1737 | mutex_lock(&c->umount_mutex); | 1736 | mutex_lock(&c->umount_mutex); |
| 1738 | if (!(c->vfs_sb->s_flags & MS_RDONLY)) { | 1737 | if (!c->ro_mount) { |
| 1739 | /* | 1738 | /* |
| 1740 | * First of all kill the background thread to make sure it does | 1739 | * First of all kill the background thread to make sure it does |
| 1741 | * not interfere with un-mounting and freeing resources. | 1740 | * not interfere with un-mounting and freeing resources. |
| @@ -1745,23 +1744,22 @@ static void ubifs_put_super(struct super_block *sb) | |||
| 1745 | c->bgt = NULL; | 1744 | c->bgt = NULL; |
| 1746 | } | 1745 | } |
| 1747 | 1746 | ||
| 1748 | /* Synchronize write-buffers */ | ||
| 1749 | if (c->jheads) | ||
| 1750 | for (i = 0; i < c->jhead_cnt; i++) | ||
| 1751 | ubifs_wbuf_sync(&c->jheads[i].wbuf); | ||
| 1752 | |||
| 1753 | /* | 1747 | /* |
| 1754 | * On fatal errors c->ro_media is set to 1, in which case we do | 1748 | * On fatal errors c->ro_error is set to 1, in which case we do |
| 1755 | * not write the master node. | 1749 | * not write the master node. |
| 1756 | */ | 1750 | */ |
| 1757 | if (!c->ro_media) { | 1751 | if (!c->ro_error) { |
| 1752 | int err; | ||
| 1753 | |||
| 1754 | /* Synchronize write-buffers */ | ||
| 1755 | for (i = 0; i < c->jhead_cnt; i++) | ||
| 1756 | ubifs_wbuf_sync(&c->jheads[i].wbuf); | ||
| 1757 | |||
| 1758 | /* | 1758 | /* |
| 1759 | * We are being cleanly unmounted which means the | 1759 | * We are being cleanly unmounted which means the |
| 1760 | * orphans were killed - indicate this in the master | 1760 | * orphans were killed - indicate this in the master |
| 1761 | * node. Also save the reserved GC LEB number. | 1761 | * node. Also save the reserved GC LEB number. |
| 1762 | */ | 1762 | */ |
| 1763 | int err; | ||
| 1764 | |||
| 1765 | c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); | 1763 | c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); |
| 1766 | c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); | 1764 | c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); |
| 1767 | c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); | 1765 | c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); |
| @@ -1774,6 +1772,10 @@ static void ubifs_put_super(struct super_block *sb) | |||
| 1774 | */ | 1772 | */ |
| 1775 | ubifs_err("failed to write master node, " | 1773 | ubifs_err("failed to write master node, " |
| 1776 | "error %d", err); | 1774 | "error %d", err); |
| 1775 | } else { | ||
| 1776 | for (i = 0; i < c->jhead_cnt; i++) | ||
| 1777 | /* Make sure write-buffer timers are canceled */ | ||
| 1778 | hrtimer_cancel(&c->jheads[i].wbuf.timer); | ||
| 1777 | } | 1779 | } |
| 1778 | } | 1780 | } |
| 1779 | 1781 | ||
| @@ -1797,17 +1799,21 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) | |||
| 1797 | return err; | 1799 | return err; |
| 1798 | } | 1800 | } |
| 1799 | 1801 | ||
| 1800 | if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { | 1802 | if (c->ro_mount && !(*flags & MS_RDONLY)) { |
| 1803 | if (c->ro_error) { | ||
| 1804 | ubifs_msg("cannot re-mount R/W due to prior errors"); | ||
| 1805 | return -EROFS; | ||
| 1806 | } | ||
| 1801 | if (c->ro_media) { | 1807 | if (c->ro_media) { |
| 1802 | ubifs_msg("cannot re-mount due to prior errors"); | 1808 | ubifs_msg("cannot re-mount R/W - UBI volume is R/O"); |
| 1803 | return -EROFS; | 1809 | return -EROFS; |
| 1804 | } | 1810 | } |
| 1805 | err = ubifs_remount_rw(c); | 1811 | err = ubifs_remount_rw(c); |
| 1806 | if (err) | 1812 | if (err) |
| 1807 | return err; | 1813 | return err; |
| 1808 | } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) { | 1814 | } else if (!c->ro_mount && (*flags & MS_RDONLY)) { |
| 1809 | if (c->ro_media) { | 1815 | if (c->ro_error) { |
| 1810 | ubifs_msg("cannot re-mount due to prior errors"); | 1816 | ubifs_msg("cannot re-mount R/O due to prior errors"); |
| 1811 | return -EROFS; | 1817 | return -EROFS; |
| 1812 | } | 1818 | } |
| 1813 | ubifs_remount_ro(c); | 1819 | ubifs_remount_ro(c); |
| @@ -2049,8 +2055,8 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 2049 | */ | 2055 | */ |
| 2050 | ubi = open_ubi(name, UBI_READONLY); | 2056 | ubi = open_ubi(name, UBI_READONLY); |
| 2051 | if (IS_ERR(ubi)) { | 2057 | if (IS_ERR(ubi)) { |
| 2052 | ubifs_err("cannot open \"%s\", error %d", | 2058 | dbg_err("cannot open \"%s\", error %d", |
| 2053 | name, (int)PTR_ERR(ubi)); | 2059 | name, (int)PTR_ERR(ubi)); |
| 2054 | return PTR_ERR(ubi); | 2060 | return PTR_ERR(ubi); |
| 2055 | } | 2061 | } |
| 2056 | ubi_get_volume_info(ubi, &vi); | 2062 | ubi_get_volume_info(ubi, &vi); |
| @@ -2064,9 +2070,11 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 2064 | } | 2070 | } |
| 2065 | 2071 | ||
| 2066 | if (sb->s_root) { | 2072 | if (sb->s_root) { |
| 2073 | struct ubifs_info *c1 = sb->s_fs_info; | ||
| 2074 | |||
| 2067 | /* A new mount point for already mounted UBIFS */ | 2075 | /* A new mount point for already mounted UBIFS */ |
| 2068 | dbg_gen("this ubi volume is already mounted"); | 2076 | dbg_gen("this ubi volume is already mounted"); |
| 2069 | if ((flags ^ sb->s_flags) & MS_RDONLY) { | 2077 | if (!!(flags & MS_RDONLY) != c1->ro_mount) { |
| 2070 | err = -EBUSY; | 2078 | err = -EBUSY; |
| 2071 | goto out_deact; | 2079 | goto out_deact; |
| 2072 | } | 2080 | } |
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 2194915220e..ad9cf013362 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c | |||
| @@ -1177,6 +1177,7 @@ int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key, | |||
| 1177 | unsigned long time = get_seconds(); | 1177 | unsigned long time = get_seconds(); |
| 1178 | 1178 | ||
| 1179 | dbg_tnc("search key %s", DBGKEY(key)); | 1179 | dbg_tnc("search key %s", DBGKEY(key)); |
| 1180 | ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY); | ||
| 1180 | 1181 | ||
| 1181 | znode = c->zroot.znode; | 1182 | znode = c->zroot.znode; |
| 1182 | if (unlikely(!znode)) { | 1183 | if (unlikely(!znode)) { |
| @@ -2966,7 +2967,7 @@ static struct ubifs_znode *right_znode(struct ubifs_info *c, | |||
| 2966 | * | 2967 | * |
| 2967 | * This function searches an indexing node by its first key @key and its | 2968 | * This function searches an indexing node by its first key @key and its |
| 2968 | * address @lnum:@offs. It looks up the indexing tree by pulling all indexing | 2969 | * address @lnum:@offs. It looks up the indexing tree by pulling all indexing |
| 2969 | * nodes it traverses to TNC. This function is called fro indexing nodes which | 2970 | * nodes it traverses to TNC. This function is called for indexing nodes which |
| 2970 | * were found on the media by scanning, for example when garbage-collecting or | 2971 | * were found on the media by scanning, for example when garbage-collecting or |
| 2971 | * when doing in-the-gaps commit. This means that the indexing node which is | 2972 | * when doing in-the-gaps commit. This means that the indexing node which is |
| 2972 | * looked for does not have to have exactly the same leftmost key @key, because | 2973 | * looked for does not have to have exactly the same leftmost key @key, because |
| @@ -2988,6 +2989,8 @@ static struct ubifs_znode *lookup_znode(struct ubifs_info *c, | |||
| 2988 | struct ubifs_znode *znode, *zn; | 2989 | struct ubifs_znode *znode, *zn; |
| 2989 | int n, nn; | 2990 | int n, nn; |
| 2990 | 2991 | ||
| 2992 | ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY); | ||
| 2993 | |||
| 2991 | /* | 2994 | /* |
| 2992 | * The arguments have probably been read off flash, so don't assume | 2995 | * The arguments have probably been read off flash, so don't assume |
| 2993 | * they are valid. | 2996 | * they are valid. |
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 0c9876b396d..381d6b207a5 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
| @@ -119,8 +119,12 @@ | |||
| 119 | * in TNC. However, when replaying, it is handy to introduce fake "truncation" | 119 | * in TNC. However, when replaying, it is handy to introduce fake "truncation" |
| 120 | * keys for truncation nodes because the code becomes simpler. So we define | 120 | * keys for truncation nodes because the code becomes simpler. So we define |
| 121 | * %UBIFS_TRUN_KEY type. | 121 | * %UBIFS_TRUN_KEY type. |
| 122 | * | ||
| 123 | * But otherwise, out of the journal reply scope, the truncation keys are | ||
| 124 | * invalid. | ||
| 122 | */ | 125 | */ |
| 123 | #define UBIFS_TRUN_KEY UBIFS_KEY_TYPES_CNT | 126 | #define UBIFS_TRUN_KEY UBIFS_KEY_TYPES_CNT |
| 127 | #define UBIFS_INVALID_KEY UBIFS_KEY_TYPES_CNT | ||
| 124 | 128 | ||
| 125 | /* | 129 | /* |
| 126 | * How much a directory entry/extended attribute entry adds to the parent/host | 130 | * How much a directory entry/extended attribute entry adds to the parent/host |
| @@ -1028,6 +1032,8 @@ struct ubifs_debug_info; | |||
| 1028 | * @max_leb_cnt: maximum count of logical eraseblocks | 1032 | * @max_leb_cnt: maximum count of logical eraseblocks |
| 1029 | * @old_leb_cnt: count of logical eraseblocks before re-size | 1033 | * @old_leb_cnt: count of logical eraseblocks before re-size |
| 1030 | * @ro_media: the underlying UBI volume is read-only | 1034 | * @ro_media: the underlying UBI volume is read-only |
| 1035 | * @ro_mount: the file-system was mounted as read-only | ||
| 1036 | * @ro_error: UBIFS switched to R/O mode because an error happened | ||
| 1031 | * | 1037 | * |
| 1032 | * @dirty_pg_cnt: number of dirty pages (not used) | 1038 | * @dirty_pg_cnt: number of dirty pages (not used) |
| 1033 | * @dirty_zn_cnt: number of dirty znodes | 1039 | * @dirty_zn_cnt: number of dirty znodes |
| @@ -1168,11 +1174,14 @@ struct ubifs_debug_info; | |||
| 1168 | * @replay_sqnum: sequence number of node currently being replayed | 1174 | * @replay_sqnum: sequence number of node currently being replayed |
| 1169 | * @need_recovery: file-system needs recovery | 1175 | * @need_recovery: file-system needs recovery |
| 1170 | * @replaying: set to %1 during journal replay | 1176 | * @replaying: set to %1 during journal replay |
| 1171 | * @unclean_leb_list: LEBs to recover when mounting ro to rw | 1177 | * @unclean_leb_list: LEBs to recover when re-mounting R/O mounted FS to R/W |
| 1172 | * @rcvrd_mst_node: recovered master node to write when mounting ro to rw | 1178 | * mode |
| 1179 | * @rcvrd_mst_node: recovered master node to write when re-mounting R/O mounted | ||
| 1180 | * FS to R/W mode | ||
| 1173 | * @size_tree: inode size information for recovery | 1181 | * @size_tree: inode size information for recovery |
| 1174 | * @remounting_rw: set while remounting from ro to rw (sb flags have MS_RDONLY) | 1182 | * @remounting_rw: set while re-mounting from R/O mode to R/W mode |
| 1175 | * @always_chk_crc: always check CRCs (while mounting and remounting rw) | 1183 | * @always_chk_crc: always check CRCs (while mounting and remounting to R/W |
| 1184 | * mode) | ||
| 1176 | * @mount_opts: UBIFS-specific mount options | 1185 | * @mount_opts: UBIFS-specific mount options |
| 1177 | * | 1186 | * |
| 1178 | * @dbg: debugging-related information | 1187 | * @dbg: debugging-related information |
| @@ -1268,7 +1277,9 @@ struct ubifs_info { | |||
| 1268 | int leb_cnt; | 1277 | int leb_cnt; |
| 1269 | int max_leb_cnt; | 1278 | int max_leb_cnt; |
| 1270 | int old_leb_cnt; | 1279 | int old_leb_cnt; |
| 1271 | int ro_media; | 1280 | unsigned int ro_media:1; |
| 1281 | unsigned int ro_mount:1; | ||
| 1282 | unsigned int ro_error:1; | ||
| 1272 | 1283 | ||
| 1273 | atomic_long_t dirty_pg_cnt; | 1284 | atomic_long_t dirty_pg_cnt; |
| 1274 | atomic_long_t dirty_zn_cnt; | 1285 | atomic_long_t dirty_zn_cnt; |
