aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ubifs/debug.c37
-rw-r--r--fs/ubifs/debug.h6
-rw-r--r--fs/ubifs/lpt.c3
-rw-r--r--fs/ubifs/lpt_commit.c185
-rw-r--r--fs/ubifs/ubifs.h10
5 files changed, 228 insertions, 13 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 32071ec87cd7..7186400750e7 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -655,6 +655,43 @@ void dbg_dump_lprops(struct ubifs_info *c)
655 } 655 }
656} 656}
657 657
658void dbg_dump_lpt_info(struct ubifs_info *c)
659{
660 int i;
661
662 spin_lock(&dbg_lock);
663 printk(KERN_DEBUG "\tlpt_sz: %lld\n", c->lpt_sz);
664 printk(KERN_DEBUG "\tpnode_sz: %d\n", c->pnode_sz);
665 printk(KERN_DEBUG "\tnnode_sz: %d\n", c->nnode_sz);
666 printk(KERN_DEBUG "\tltab_sz: %d\n", c->ltab_sz);
667 printk(KERN_DEBUG "\tlsave_sz: %d\n", c->lsave_sz);
668 printk(KERN_DEBUG "\tbig_lpt: %d\n", c->big_lpt);
669 printk(KERN_DEBUG "\tlpt_hght: %d\n", c->lpt_hght);
670 printk(KERN_DEBUG "\tpnode_cnt: %d\n", c->pnode_cnt);
671 printk(KERN_DEBUG "\tnnode_cnt: %d\n", c->nnode_cnt);
672 printk(KERN_DEBUG "\tdirty_pn_cnt: %d\n", c->dirty_pn_cnt);
673 printk(KERN_DEBUG "\tdirty_nn_cnt: %d\n", c->dirty_nn_cnt);
674 printk(KERN_DEBUG "\tlsave_cnt: %d\n", c->lsave_cnt);
675 printk(KERN_DEBUG "\tspace_bits: %d\n", c->space_bits);
676 printk(KERN_DEBUG "\tlpt_lnum_bits: %d\n", c->lpt_lnum_bits);
677 printk(KERN_DEBUG "\tlpt_offs_bits: %d\n", c->lpt_offs_bits);
678 printk(KERN_DEBUG "\tlpt_spc_bits: %d\n", c->lpt_spc_bits);
679 printk(KERN_DEBUG "\tpcnt_bits: %d\n", c->pcnt_bits);
680 printk(KERN_DEBUG "\tlnum_bits: %d\n", c->lnum_bits);
681 printk(KERN_DEBUG "\tLPT root is at %d:%d\n", c->lpt_lnum, c->lpt_offs);
682 printk(KERN_DEBUG "\tLPT head is at %d:%d\n",
683 c->nhead_lnum, c->nhead_offs);
684 printk(KERN_DEBUG "\tLPT ltab is at %d:%d\n", c->ltab_lnum, c->ltab_offs);
685 if (c->big_lpt)
686 printk(KERN_DEBUG "\tLPT lsave is at %d:%d\n",
687 c->lsave_lnum, c->lsave_offs);
688 for (i = 0; i < c->lpt_lebs; i++)
689 printk(KERN_DEBUG "\tLPT LEB %d free %d dirty %d tgc %d "
690 "cmt %d\n", i + c->lpt_first, c->ltab[i].free,
691 c->ltab[i].dirty, c->ltab[i].tgc, c->ltab[i].cmt);
692 spin_unlock(&dbg_lock);
693}
694
658void dbg_dump_leb(const struct ubifs_info *c, int lnum) 695void dbg_dump_leb(const struct ubifs_info *c, int lnum)
659{ 696{
660 struct ubifs_scan_leb *sleb; 697 struct ubifs_scan_leb *sleb;
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 50315fc57185..33d6b95071e4 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -224,6 +224,7 @@ void dbg_dump_lstats(const struct ubifs_lp_stats *lst);
224void dbg_dump_budg(struct ubifs_info *c); 224void dbg_dump_budg(struct ubifs_info *c);
225void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp); 225void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp);
226void dbg_dump_lprops(struct ubifs_info *c); 226void dbg_dump_lprops(struct ubifs_info *c);
227void dbg_dump_lpt_info(struct ubifs_info *c);
227void dbg_dump_leb(const struct ubifs_info *c, int lnum); 228void dbg_dump_leb(const struct ubifs_info *c, int lnum);
228void dbg_dump_znode(const struct ubifs_info *c, 229void dbg_dump_znode(const struct ubifs_info *c,
229 const struct ubifs_znode *znode); 230 const struct ubifs_znode *znode);
@@ -249,6 +250,8 @@ int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot);
249int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot); 250int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot);
250int dbg_check_cats(struct ubifs_info *c); 251int dbg_check_cats(struct ubifs_info *c);
251int dbg_check_ltab(struct ubifs_info *c); 252int dbg_check_ltab(struct ubifs_info *c);
253int dbg_chk_lpt_free_spc(struct ubifs_info *c);
254int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len);
252int dbg_check_synced_i_size(struct inode *inode); 255int dbg_check_synced_i_size(struct inode *inode);
253int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir); 256int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir);
254int dbg_check_tnc(struct ubifs_info *c, int extra); 257int dbg_check_tnc(struct ubifs_info *c, int extra);
@@ -367,6 +370,7 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
367#define dbg_dump_budg(c) ({}) 370#define dbg_dump_budg(c) ({})
368#define dbg_dump_lprop(c, lp) ({}) 371#define dbg_dump_lprop(c, lp) ({})
369#define dbg_dump_lprops(c) ({}) 372#define dbg_dump_lprops(c) ({})
373#define dbg_dump_lpt_info(c) ({})
370#define dbg_dump_leb(c, lnum) ({}) 374#define dbg_dump_leb(c, lnum) ({})
371#define dbg_dump_znode(c, znode) ({}) 375#define dbg_dump_znode(c, znode) ({})
372#define dbg_dump_heap(c, heap, cat) ({}) 376#define dbg_dump_heap(c, heap, cat) ({})
@@ -379,6 +383,8 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
379#define dbg_check_old_index(c, zroot) 0 383#define dbg_check_old_index(c, zroot) 0
380#define dbg_check_cats(c) 0 384#define dbg_check_cats(c) 0
381#define dbg_check_ltab(c) 0 385#define dbg_check_ltab(c) 0
386#define dbg_chk_lpt_free_spc(c) 0
387#define dbg_chk_lpt_sz(c, action, len) 0
382#define dbg_check_synced_i_size(inode) 0 388#define dbg_check_synced_i_size(inode) 0
383#define dbg_check_dir_size(c, dir) 0 389#define dbg_check_dir_size(c, dir) 0
384#define dbg_check_tnc(c, x) 0 390#define dbg_check_tnc(c, x) 0
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index 9ff2463177e5..cd11b23a1875 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -109,7 +109,8 @@ static void do_calc_lpt_geom(struct ubifs_info *c)
109 c->lpt_sz = (long long)c->pnode_cnt * c->pnode_sz; 109 c->lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
110 c->lpt_sz += (long long)c->nnode_cnt * c->nnode_sz; 110 c->lpt_sz += (long long)c->nnode_cnt * c->nnode_sz;
111 c->lpt_sz += c->ltab_sz; 111 c->lpt_sz += c->ltab_sz;
112 c->lpt_sz += c->lsave_sz; 112 if (c->big_lpt)
113 c->lpt_sz += c->lsave_sz;
113 114
114 /* Add wastage */ 115 /* Add wastage */
115 sz = c->lpt_sz; 116 sz = c->lpt_sz;
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index 5f0b83e20af6..8546865a9104 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -177,8 +177,6 @@ static int alloc_lpt_leb(struct ubifs_info *c, int *lnum)
177 return 0; 177 return 0;
178 } 178 }
179 } 179 }
180 dbg_err("last LEB %d", *lnum);
181 dump_stack();
182 return -ENOSPC; 180 return -ENOSPC;
183} 181}
184 182
@@ -193,6 +191,9 @@ static int layout_cnodes(struct ubifs_info *c)
193 int lnum, offs, len, alen, done_lsave, done_ltab, err; 191 int lnum, offs, len, alen, done_lsave, done_ltab, err;
194 struct ubifs_cnode *cnode; 192 struct ubifs_cnode *cnode;
195 193
194 err = dbg_chk_lpt_sz(c, 0, 0);
195 if (err)
196 return err;
196 cnode = c->lpt_cnext; 197 cnode = c->lpt_cnext;
197 if (!cnode) 198 if (!cnode)
198 return 0; 199 return 0;
@@ -206,6 +207,7 @@ static int layout_cnodes(struct ubifs_info *c)
206 c->lsave_lnum = lnum; 207 c->lsave_lnum = lnum;
207 c->lsave_offs = offs; 208 c->lsave_offs = offs;
208 offs += c->lsave_sz; 209 offs += c->lsave_sz;
210 dbg_chk_lpt_sz(c, 1, c->lsave_sz);
209 } 211 }
210 212
211 if (offs + c->ltab_sz <= c->leb_size) { 213 if (offs + c->ltab_sz <= c->leb_size) {
@@ -213,6 +215,7 @@ static int layout_cnodes(struct ubifs_info *c)
213 c->ltab_lnum = lnum; 215 c->ltab_lnum = lnum;
214 c->ltab_offs = offs; 216 c->ltab_offs = offs;
215 offs += c->ltab_sz; 217 offs += c->ltab_sz;
218 dbg_chk_lpt_sz(c, 1, c->ltab_sz);
216 } 219 }
217 220
218 do { 221 do {
@@ -226,9 +229,10 @@ static int layout_cnodes(struct ubifs_info *c)
226 while (offs + len > c->leb_size) { 229 while (offs + len > c->leb_size) {
227 alen = ALIGN(offs, c->min_io_size); 230 alen = ALIGN(offs, c->min_io_size);
228 upd_ltab(c, lnum, c->leb_size - alen, alen - offs); 231 upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
232 dbg_chk_lpt_sz(c, 2, alen - offs);
229 err = alloc_lpt_leb(c, &lnum); 233 err = alloc_lpt_leb(c, &lnum);
230 if (err) 234 if (err)
231 return err; 235 goto no_space;
232 offs = 0; 236 offs = 0;
233 ubifs_assert(lnum >= c->lpt_first && 237 ubifs_assert(lnum >= c->lpt_first &&
234 lnum <= c->lpt_last); 238 lnum <= c->lpt_last);
@@ -238,6 +242,7 @@ static int layout_cnodes(struct ubifs_info *c)
238 c->lsave_lnum = lnum; 242 c->lsave_lnum = lnum;
239 c->lsave_offs = offs; 243 c->lsave_offs = offs;
240 offs += c->lsave_sz; 244 offs += c->lsave_sz;
245 dbg_chk_lpt_sz(c, 1, c->lsave_sz);
241 continue; 246 continue;
242 } 247 }
243 if (!done_ltab) { 248 if (!done_ltab) {
@@ -245,6 +250,7 @@ static int layout_cnodes(struct ubifs_info *c)
245 c->ltab_lnum = lnum; 250 c->ltab_lnum = lnum;
246 c->ltab_offs = offs; 251 c->ltab_offs = offs;
247 offs += c->ltab_sz; 252 offs += c->ltab_sz;
253 dbg_chk_lpt_sz(c, 1, c->ltab_sz);
248 continue; 254 continue;
249 } 255 }
250 break; 256 break;
@@ -257,6 +263,7 @@ static int layout_cnodes(struct ubifs_info *c)
257 c->lpt_offs = offs; 263 c->lpt_offs = offs;
258 } 264 }
259 offs += len; 265 offs += len;
266 dbg_chk_lpt_sz(c, 1, len);
260 cnode = cnode->cnext; 267 cnode = cnode->cnext;
261 } while (cnode && cnode != c->lpt_cnext); 268 } while (cnode && cnode != c->lpt_cnext);
262 269
@@ -265,9 +272,10 @@ static int layout_cnodes(struct ubifs_info *c)
265 if (offs + c->lsave_sz > c->leb_size) { 272 if (offs + c->lsave_sz > c->leb_size) {
266 alen = ALIGN(offs, c->min_io_size); 273 alen = ALIGN(offs, c->min_io_size);
267 upd_ltab(c, lnum, c->leb_size - alen, alen - offs); 274 upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
275 dbg_chk_lpt_sz(c, 2, alen - offs);
268 err = alloc_lpt_leb(c, &lnum); 276 err = alloc_lpt_leb(c, &lnum);
269 if (err) 277 if (err)
270 return err; 278 goto no_space;
271 offs = 0; 279 offs = 0;
272 ubifs_assert(lnum >= c->lpt_first && 280 ubifs_assert(lnum >= c->lpt_first &&
273 lnum <= c->lpt_last); 281 lnum <= c->lpt_last);
@@ -276,6 +284,7 @@ static int layout_cnodes(struct ubifs_info *c)
276 c->lsave_lnum = lnum; 284 c->lsave_lnum = lnum;
277 c->lsave_offs = offs; 285 c->lsave_offs = offs;
278 offs += c->lsave_sz; 286 offs += c->lsave_sz;
287 dbg_chk_lpt_sz(c, 1, c->lsave_sz);
279 } 288 }
280 289
281 /* Make sure to place LPT's own lprops table */ 290 /* Make sure to place LPT's own lprops table */
@@ -283,9 +292,10 @@ static int layout_cnodes(struct ubifs_info *c)
283 if (offs + c->ltab_sz > c->leb_size) { 292 if (offs + c->ltab_sz > c->leb_size) {
284 alen = ALIGN(offs, c->min_io_size); 293 alen = ALIGN(offs, c->min_io_size);
285 upd_ltab(c, lnum, c->leb_size - alen, alen - offs); 294 upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
295 dbg_chk_lpt_sz(c, 2, alen - offs);
286 err = alloc_lpt_leb(c, &lnum); 296 err = alloc_lpt_leb(c, &lnum);
287 if (err) 297 if (err)
288 return err; 298 goto no_space;
289 offs = 0; 299 offs = 0;
290 ubifs_assert(lnum >= c->lpt_first && 300 ubifs_assert(lnum >= c->lpt_first &&
291 lnum <= c->lpt_last); 301 lnum <= c->lpt_last);
@@ -294,11 +304,23 @@ static int layout_cnodes(struct ubifs_info *c)
294 c->ltab_lnum = lnum; 304 c->ltab_lnum = lnum;
295 c->ltab_offs = offs; 305 c->ltab_offs = offs;
296 offs += c->ltab_sz; 306 offs += c->ltab_sz;
307 dbg_chk_lpt_sz(c, 1, c->ltab_sz);
297 } 308 }
298 309
299 alen = ALIGN(offs, c->min_io_size); 310 alen = ALIGN(offs, c->min_io_size);
300 upd_ltab(c, lnum, c->leb_size - alen, alen - offs); 311 upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
312 dbg_chk_lpt_sz(c, 4, alen - offs);
313 err = dbg_chk_lpt_sz(c, 3, alen);
314 if (err)
315 return err;
301 return 0; 316 return 0;
317
318no_space:
319 ubifs_err("LPT out of space");
320 dbg_err("LPT out of space at LEB %d:%d needing %d, done_ltab %d, "
321 "done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
322 dbg_dump_lpt_info(c);
323 return err;
302} 324}
303 325
304/** 326/**
@@ -333,8 +355,6 @@ static int realloc_lpt_leb(struct ubifs_info *c, int *lnum)
333 *lnum = i + c->lpt_first; 355 *lnum = i + c->lpt_first;
334 return 0; 356 return 0;
335 } 357 }
336 dbg_err("last LEB %d", *lnum);
337 dump_stack();
338 return -ENOSPC; 358 return -ENOSPC;
339} 359}
340 360
@@ -369,12 +389,14 @@ static int write_cnodes(struct ubifs_info *c)
369 done_lsave = 1; 389 done_lsave = 1;
370 ubifs_pack_lsave(c, buf + offs, c->lsave); 390 ubifs_pack_lsave(c, buf + offs, c->lsave);
371 offs += c->lsave_sz; 391 offs += c->lsave_sz;
392 dbg_chk_lpt_sz(c, 1, c->lsave_sz);
372 } 393 }
373 394
374 if (offs + c->ltab_sz <= c->leb_size) { 395 if (offs + c->ltab_sz <= c->leb_size) {
375 done_ltab = 1; 396 done_ltab = 1;
376 ubifs_pack_ltab(c, buf + offs, c->ltab_cmt); 397 ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
377 offs += c->ltab_sz; 398 offs += c->ltab_sz;
399 dbg_chk_lpt_sz(c, 1, c->ltab_sz);
378 } 400 }
379 401
380 /* Loop for each cnode */ 402 /* Loop for each cnode */
@@ -392,10 +414,12 @@ static int write_cnodes(struct ubifs_info *c)
392 alen, UBI_SHORTTERM); 414 alen, UBI_SHORTTERM);
393 if (err) 415 if (err)
394 return err; 416 return err;
417 dbg_chk_lpt_sz(c, 4, alen - wlen);
395 } 418 }
419 dbg_chk_lpt_sz(c, 2, 0);
396 err = realloc_lpt_leb(c, &lnum); 420 err = realloc_lpt_leb(c, &lnum);
397 if (err) 421 if (err)
398 return err; 422 goto no_space;
399 offs = 0; 423 offs = 0;
400 from = 0; 424 from = 0;
401 ubifs_assert(lnum >= c->lpt_first && 425 ubifs_assert(lnum >= c->lpt_first &&
@@ -408,12 +432,14 @@ static int write_cnodes(struct ubifs_info *c)
408 done_lsave = 1; 432 done_lsave = 1;
409 ubifs_pack_lsave(c, buf + offs, c->lsave); 433 ubifs_pack_lsave(c, buf + offs, c->lsave);
410 offs += c->lsave_sz; 434 offs += c->lsave_sz;
435 dbg_chk_lpt_sz(c, 1, c->lsave_sz);
411 continue; 436 continue;
412 } 437 }
413 if (!done_ltab) { 438 if (!done_ltab) {
414 done_ltab = 1; 439 done_ltab = 1;
415 ubifs_pack_ltab(c, buf + offs, c->ltab_cmt); 440 ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
416 offs += c->ltab_sz; 441 offs += c->ltab_sz;
442 dbg_chk_lpt_sz(c, 1, c->ltab_sz);
417 continue; 443 continue;
418 } 444 }
419 break; 445 break;
@@ -435,6 +461,7 @@ static int write_cnodes(struct ubifs_info *c)
435 clear_bit(COW_ZNODE, &cnode->flags); 461 clear_bit(COW_ZNODE, &cnode->flags);
436 smp_mb__after_clear_bit(); 462 smp_mb__after_clear_bit();
437 offs += len; 463 offs += len;
464 dbg_chk_lpt_sz(c, 1, len);
438 cnode = cnode->cnext; 465 cnode = cnode->cnext;
439 } while (cnode && cnode != c->lpt_cnext); 466 } while (cnode && cnode != c->lpt_cnext);
440 467
@@ -448,9 +475,10 @@ static int write_cnodes(struct ubifs_info *c)
448 UBI_SHORTTERM); 475 UBI_SHORTTERM);
449 if (err) 476 if (err)
450 return err; 477 return err;
478 dbg_chk_lpt_sz(c, 2, alen - wlen);
451 err = realloc_lpt_leb(c, &lnum); 479 err = realloc_lpt_leb(c, &lnum);
452 if (err) 480 if (err)
453 return err; 481 goto no_space;
454 offs = 0; 482 offs = 0;
455 ubifs_assert(lnum >= c->lpt_first && 483 ubifs_assert(lnum >= c->lpt_first &&
456 lnum <= c->lpt_last); 484 lnum <= c->lpt_last);
@@ -461,6 +489,7 @@ static int write_cnodes(struct ubifs_info *c)
461 done_lsave = 1; 489 done_lsave = 1;
462 ubifs_pack_lsave(c, buf + offs, c->lsave); 490 ubifs_pack_lsave(c, buf + offs, c->lsave);
463 offs += c->lsave_sz; 491 offs += c->lsave_sz;
492 dbg_chk_lpt_sz(c, 1, c->lsave_sz);
464 } 493 }
465 494
466 /* Make sure to place LPT's own lprops table */ 495 /* Make sure to place LPT's own lprops table */
@@ -473,9 +502,10 @@ static int write_cnodes(struct ubifs_info *c)
473 UBI_SHORTTERM); 502 UBI_SHORTTERM);
474 if (err) 503 if (err)
475 return err; 504 return err;
505 dbg_chk_lpt_sz(c, 2, alen - wlen);
476 err = realloc_lpt_leb(c, &lnum); 506 err = realloc_lpt_leb(c, &lnum);
477 if (err) 507 if (err)
478 return err; 508 goto no_space;
479 offs = 0; 509 offs = 0;
480 ubifs_assert(lnum >= c->lpt_first && 510 ubifs_assert(lnum >= c->lpt_first &&
481 lnum <= c->lpt_last); 511 lnum <= c->lpt_last);
@@ -486,6 +516,7 @@ static int write_cnodes(struct ubifs_info *c)
486 done_ltab = 1; 516 done_ltab = 1;
487 ubifs_pack_ltab(c, buf + offs, c->ltab_cmt); 517 ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
488 offs += c->ltab_sz; 518 offs += c->ltab_sz;
519 dbg_chk_lpt_sz(c, 1, c->ltab_sz);
489 } 520 }
490 521
491 /* Write remaining data in buffer */ 522 /* Write remaining data in buffer */
@@ -495,6 +526,12 @@ static int write_cnodes(struct ubifs_info *c)
495 err = ubifs_leb_write(c, lnum, buf + from, from, alen, UBI_SHORTTERM); 526 err = ubifs_leb_write(c, lnum, buf + from, from, alen, UBI_SHORTTERM);
496 if (err) 527 if (err)
497 return err; 528 return err;
529
530 dbg_chk_lpt_sz(c, 4, alen - wlen);
531 err = dbg_chk_lpt_sz(c, 3, ALIGN(offs, c->min_io_size));
532 if (err)
533 return err;
534
498 c->nhead_lnum = lnum; 535 c->nhead_lnum = lnum;
499 c->nhead_offs = ALIGN(offs, c->min_io_size); 536 c->nhead_offs = ALIGN(offs, c->min_io_size);
500 537
@@ -503,7 +540,15 @@ static int write_cnodes(struct ubifs_info *c)
503 dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs); 540 dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
504 if (c->big_lpt) 541 if (c->big_lpt)
505 dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs); 542 dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs);
543
506 return 0; 544 return 0;
545
546no_space:
547 ubifs_err("LPT out of space mismatch");
548 dbg_err("LPT out of space mismatch at LEB %d:%d needing %d, done_ltab "
549 "%d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
550 dbg_dump_lpt_info(c);
551 return err;
507} 552}
508 553
509/** 554/**
@@ -1156,6 +1201,9 @@ int ubifs_lpt_start_commit(struct ubifs_info *c)
1156 dbg_lp(""); 1201 dbg_lp("");
1157 1202
1158 mutex_lock(&c->lp_mutex); 1203 mutex_lock(&c->lp_mutex);
1204 err = dbg_chk_lpt_free_spc(c);
1205 if (err)
1206 goto out;
1159 err = dbg_check_ltab(c); 1207 err = dbg_check_ltab(c);
1160 if (err) 1208 if (err)
1161 goto out; 1209 goto out;
@@ -1645,4 +1693,121 @@ int dbg_check_ltab(struct ubifs_info *c)
1645 return 0; 1693 return 0;
1646} 1694}
1647 1695
1696/**
1697 * dbg_chk_lpt_free_spc - check LPT free space is enough to write entire LPT.
1698 * @c: the UBIFS file-system description object
1699 *
1700 * This function returns %0 on success and a negative error code on failure.
1701 */
1702int dbg_chk_lpt_free_spc(struct ubifs_info *c)
1703{
1704 long long free = 0;
1705 int i;
1706
1707 for (i = 0; i < c->lpt_lebs; i++) {
1708 if (c->ltab[i].tgc || c->ltab[i].cmt)
1709 continue;
1710 if (i + c->lpt_first == c->nhead_lnum)
1711 free += c->leb_size - c->nhead_offs;
1712 else if (c->ltab[i].free == c->leb_size)
1713 free += c->leb_size;
1714 }
1715 if (free < c->lpt_sz) {
1716 dbg_err("LPT space error: free %lld lpt_sz %lld",
1717 free, c->lpt_sz);
1718 dbg_dump_lpt_info(c);
1719 return -EINVAL;
1720 }
1721 return 0;
1722}
1723
1724/**
1725 * dbg_chk_lpt_sz - check LPT does not write more than LPT size.
1726 * @c: the UBIFS file-system description object
1727 * @action: action
1728 * @len: length written
1729 *
1730 * This function returns %0 on success and a negative error code on failure.
1731 */
1732int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
1733{
1734 long long chk_lpt_sz, lpt_sz;
1735 int err = 0;
1736
1737 switch (action) {
1738 case 0:
1739 c->chk_lpt_sz = 0;
1740 c->chk_lpt_sz2 = 0;
1741 c->chk_lpt_lebs = 0;
1742 c->chk_lpt_wastage = 0;
1743 if (c->dirty_pn_cnt > c->pnode_cnt) {
1744 dbg_err("dirty pnodes %d exceed max %d",
1745 c->dirty_pn_cnt, c->pnode_cnt);
1746 err = -EINVAL;
1747 }
1748 if (c->dirty_nn_cnt > c->nnode_cnt) {
1749 dbg_err("dirty nnodes %d exceed max %d",
1750 c->dirty_nn_cnt, c->nnode_cnt);
1751 err = -EINVAL;
1752 }
1753 return err;
1754 case 1:
1755 c->chk_lpt_sz += len;
1756 return 0;
1757 case 2:
1758 c->chk_lpt_sz += len;
1759 c->chk_lpt_wastage += len;
1760 c->chk_lpt_lebs += 1;
1761 return 0;
1762 case 3:
1763 chk_lpt_sz = c->leb_size;
1764 chk_lpt_sz *= c->chk_lpt_lebs;
1765 chk_lpt_sz += len - c->nhead_offs;
1766 if (c->chk_lpt_sz != chk_lpt_sz) {
1767 dbg_err("LPT wrote %lld but space used was %lld",
1768 c->chk_lpt_sz, chk_lpt_sz);
1769 err = -EINVAL;
1770 }
1771 if (c->chk_lpt_sz > c->lpt_sz) {
1772 dbg_err("LPT wrote %lld but lpt_sz is %lld",
1773 c->chk_lpt_sz, c->lpt_sz);
1774 err = -EINVAL;
1775 }
1776 if (c->chk_lpt_sz2 && c->chk_lpt_sz != c->chk_lpt_sz2) {
1777 dbg_err("LPT layout size %lld but wrote %lld",
1778 c->chk_lpt_sz, c->chk_lpt_sz2);
1779 err = -EINVAL;
1780 }
1781 if (c->chk_lpt_sz2 && c->new_nhead_offs != len) {
1782 dbg_err("LPT new nhead offs: expected %d was %d",
1783 c->new_nhead_offs, len);
1784 err = -EINVAL;
1785 }
1786 lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
1787 lpt_sz += (long long)c->nnode_cnt * c->nnode_sz;
1788 lpt_sz += c->ltab_sz;
1789 if (c->big_lpt)
1790 lpt_sz += c->lsave_sz;
1791 if (c->chk_lpt_sz - c->chk_lpt_wastage > lpt_sz) {
1792 dbg_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
1793 c->chk_lpt_sz, c->chk_lpt_wastage, lpt_sz);
1794 err = -EINVAL;
1795 }
1796 if (err)
1797 dbg_dump_lpt_info(c);
1798 c->chk_lpt_sz2 = c->chk_lpt_sz;
1799 c->chk_lpt_sz = 0;
1800 c->chk_lpt_wastage = 0;
1801 c->chk_lpt_lebs = 0;
1802 c->new_nhead_offs = len;
1803 return err;
1804 case 4:
1805 c->chk_lpt_sz += len;
1806 c->chk_lpt_wastage += len;
1807 return 0;
1808 default:
1809 return -EINVAL;
1810 }
1811}
1812
1648#endif /* CONFIG_UBIFS_FS_DEBUG */ 1813#endif /* CONFIG_UBIFS_FS_DEBUG */
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 49b06c9f675a..a7bd32fa15b9 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -943,7 +943,6 @@ struct ubifs_mount_opts {
943 * 943 *
944 * @fast_unmount: do not run journal commit before un-mounting 944 * @fast_unmount: do not run journal commit before un-mounting
945 * @big_lpt: flag that LPT is too big to write whole during commit 945 * @big_lpt: flag that LPT is too big to write whole during commit
946 * @check_lpt_free: flag that indicates LPT GC may be needed
947 * @no_chk_data_crc: do not check CRCs when reading data nodes (except during 946 * @no_chk_data_crc: do not check CRCs when reading data nodes (except during
948 * recovery) 947 * recovery)
949 * @bulk_read: enable bulk-reads 948 * @bulk_read: enable bulk-reads
@@ -1102,6 +1101,7 @@ struct ubifs_mount_opts {
1102 * @lpt_drty_flgs: dirty flags for LPT special nodes e.g. ltab 1101 * @lpt_drty_flgs: dirty flags for LPT special nodes e.g. ltab
1103 * @dirty_nn_cnt: number of dirty nnodes 1102 * @dirty_nn_cnt: number of dirty nnodes
1104 * @dirty_pn_cnt: number of dirty pnodes 1103 * @dirty_pn_cnt: number of dirty pnodes
1104 * @check_lpt_free: flag that indicates LPT GC may be needed
1105 * @lpt_sz: LPT size 1105 * @lpt_sz: LPT size
1106 * @lpt_nod_buf: buffer for an on-flash nnode or pnode 1106 * @lpt_nod_buf: buffer for an on-flash nnode or pnode
1107 * @lpt_buf: buffer of LEB size used by LPT 1107 * @lpt_buf: buffer of LEB size used by LPT
@@ -1191,7 +1191,6 @@ struct ubifs_info {
1191 1191
1192 unsigned int fast_unmount:1; 1192 unsigned int fast_unmount:1;
1193 unsigned int big_lpt:1; 1193 unsigned int big_lpt:1;
1194 unsigned int check_lpt_free:1;
1195 unsigned int no_chk_data_crc:1; 1194 unsigned int no_chk_data_crc:1;
1196 unsigned int bulk_read:1; 1195 unsigned int bulk_read:1;
1197 1196
@@ -1340,6 +1339,7 @@ struct ubifs_info {
1340 int lpt_drty_flgs; 1339 int lpt_drty_flgs;
1341 int dirty_nn_cnt; 1340 int dirty_nn_cnt;
1342 int dirty_pn_cnt; 1341 int dirty_pn_cnt;
1342 int check_lpt_free;
1343 long long lpt_sz; 1343 long long lpt_sz;
1344 void *lpt_nod_buf; 1344 void *lpt_nod_buf;
1345 void *lpt_buf; 1345 void *lpt_buf;
@@ -1394,6 +1394,12 @@ struct ubifs_info {
1394 unsigned long fail_timeout; 1394 unsigned long fail_timeout;
1395 unsigned int fail_cnt; 1395 unsigned int fail_cnt;
1396 unsigned int fail_cnt_max; 1396 unsigned int fail_cnt_max;
1397 long long chk_lpt_sz;
1398 long long chk_lpt_sz2;
1399 long long chk_lpt_wastage;
1400 int chk_lpt_lebs;
1401 int new_nhead_lnum;
1402 int new_nhead_offs;
1397#endif 1403#endif
1398}; 1404};
1399 1405