diff options
| -rw-r--r-- | fs/ubifs/gc.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 399d764f83cb..bf75fdc76fc3 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c | |||
| @@ -365,12 +365,13 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb) | |||
| 365 | 365 | ||
| 366 | /* Write nodes to their new location. Use the first-fit strategy */ | 366 | /* Write nodes to their new location. Use the first-fit strategy */ |
| 367 | while (1) { | 367 | while (1) { |
| 368 | int avail; | 368 | int avail, moved = 0; |
| 369 | struct ubifs_scan_node *snod, *tmp; | 369 | struct ubifs_scan_node *snod, *tmp; |
| 370 | 370 | ||
| 371 | /* Move data nodes */ | 371 | /* Move data nodes */ |
| 372 | list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) { | 372 | list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) { |
| 373 | avail = c->leb_size - wbuf->offs - wbuf->used; | 373 | avail = c->leb_size - wbuf->offs - wbuf->used - |
| 374 | ubifs_auth_node_sz(c); | ||
| 374 | if (snod->len > avail) | 375 | if (snod->len > avail) |
| 375 | /* | 376 | /* |
| 376 | * Do not skip data nodes in order to optimize | 377 | * Do not skip data nodes in order to optimize |
| @@ -378,14 +379,21 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb) | |||
| 378 | */ | 379 | */ |
| 379 | break; | 380 | break; |
| 380 | 381 | ||
| 382 | err = ubifs_shash_update(c, c->jheads[GCHD].log_hash, | ||
| 383 | snod->node, snod->len); | ||
| 384 | if (err) | ||
| 385 | goto out; | ||
| 386 | |||
| 381 | err = move_node(c, sleb, snod, wbuf); | 387 | err = move_node(c, sleb, snod, wbuf); |
| 382 | if (err) | 388 | if (err) |
| 383 | goto out; | 389 | goto out; |
| 390 | moved = 1; | ||
| 384 | } | 391 | } |
| 385 | 392 | ||
| 386 | /* Move non-data nodes */ | 393 | /* Move non-data nodes */ |
| 387 | list_for_each_entry_safe(snod, tmp, &nondata, list) { | 394 | list_for_each_entry_safe(snod, tmp, &nondata, list) { |
| 388 | avail = c->leb_size - wbuf->offs - wbuf->used; | 395 | avail = c->leb_size - wbuf->offs - wbuf->used - |
| 396 | ubifs_auth_node_sz(c); | ||
| 389 | if (avail < min) | 397 | if (avail < min) |
| 390 | break; | 398 | break; |
| 391 | 399 | ||
| @@ -403,9 +411,41 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb) | |||
| 403 | continue; | 411 | continue; |
| 404 | } | 412 | } |
| 405 | 413 | ||
| 414 | err = ubifs_shash_update(c, c->jheads[GCHD].log_hash, | ||
| 415 | snod->node, snod->len); | ||
| 416 | if (err) | ||
| 417 | goto out; | ||
| 418 | |||
| 406 | err = move_node(c, sleb, snod, wbuf); | 419 | err = move_node(c, sleb, snod, wbuf); |
| 407 | if (err) | 420 | if (err) |
| 408 | goto out; | 421 | goto out; |
| 422 | moved = 1; | ||
| 423 | } | ||
| 424 | |||
| 425 | if (ubifs_authenticated(c) && moved) { | ||
| 426 | struct ubifs_auth_node *auth; | ||
| 427 | |||
| 428 | auth = kmalloc(ubifs_auth_node_sz(c), GFP_NOFS); | ||
| 429 | if (!auth) { | ||
| 430 | err = -ENOMEM; | ||
| 431 | goto out; | ||
| 432 | } | ||
| 433 | |||
| 434 | err = ubifs_prepare_auth_node(c, auth, | ||
| 435 | c->jheads[GCHD].log_hash); | ||
| 436 | if (err) { | ||
| 437 | kfree(auth); | ||
| 438 | goto out; | ||
| 439 | } | ||
| 440 | |||
| 441 | err = ubifs_wbuf_write_nolock(wbuf, auth, | ||
| 442 | ubifs_auth_node_sz(c)); | ||
| 443 | if (err) { | ||
| 444 | kfree(auth); | ||
| 445 | goto out; | ||
| 446 | } | ||
| 447 | |||
| 448 | ubifs_add_dirt(c, wbuf->lnum, ubifs_auth_node_sz(c)); | ||
| 409 | } | 449 | } |
| 410 | 450 | ||
| 411 | if (list_empty(&sleb->nodes) && list_empty(&nondata)) | 451 | if (list_empty(&sleb->nodes) && list_empty(&nondata)) |
