| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * This file is part of UBIFS. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2006-2008 Nokia Corporation. |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 7 | | - * under the terms of the GNU General Public License version 2 as published by |
|---|
| 8 | | - * the Free Software Foundation. |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
|---|
| 11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 13 | | - * more details. |
|---|
| 14 | | - * |
|---|
| 15 | | - * You should have received a copy of the GNU General Public License along with |
|---|
| 16 | | - * this program; if not, write to the Free Software Foundation, Inc., 51 |
|---|
| 17 | | - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|---|
| 18 | 6 | * |
|---|
| 19 | 7 | * Authors: Adrian Hunter |
|---|
| 20 | 8 | * Artem Bityutskiy (Битюцкий Артём) |
|---|
| .. | .. |
|---|
| 69 | 57 | /** |
|---|
| 70 | 58 | * switch_gc_head - switch the garbage collection journal head. |
|---|
| 71 | 59 | * @c: UBIFS file-system description object |
|---|
| 72 | | - * @buf: buffer to write |
|---|
| 73 | | - * @len: length of the buffer to write |
|---|
| 74 | | - * @lnum: LEB number written is returned here |
|---|
| 75 | | - * @offs: offset written is returned here |
|---|
| 76 | 60 | * |
|---|
| 77 | 61 | * This function switch the GC head to the next LEB which is reserved in |
|---|
| 78 | 62 | * @c->gc_lnum. Returns %0 in case of success, %-EAGAIN if commit is required, |
|---|
| .. | .. |
|---|
| 254 | 238 | snod->type == UBIFS_DATA_NODE || |
|---|
| 255 | 239 | snod->type == UBIFS_DENT_NODE || |
|---|
| 256 | 240 | snod->type == UBIFS_XENT_NODE || |
|---|
| 257 | | - snod->type == UBIFS_TRUN_NODE); |
|---|
| 241 | + snod->type == UBIFS_TRUN_NODE || |
|---|
| 242 | + snod->type == UBIFS_AUTH_NODE); |
|---|
| 258 | 243 | |
|---|
| 259 | 244 | if (snod->type != UBIFS_INO_NODE && |
|---|
| 260 | 245 | snod->type != UBIFS_DATA_NODE && |
|---|
| .. | .. |
|---|
| 364 | 349 | |
|---|
| 365 | 350 | /* Write nodes to their new location. Use the first-fit strategy */ |
|---|
| 366 | 351 | while (1) { |
|---|
| 367 | | - int avail; |
|---|
| 352 | + int avail, moved = 0; |
|---|
| 368 | 353 | struct ubifs_scan_node *snod, *tmp; |
|---|
| 369 | 354 | |
|---|
| 370 | 355 | /* Move data nodes */ |
|---|
| 371 | 356 | list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) { |
|---|
| 372 | | - avail = c->leb_size - wbuf->offs - wbuf->used; |
|---|
| 357 | + avail = c->leb_size - wbuf->offs - wbuf->used - |
|---|
| 358 | + ubifs_auth_node_sz(c); |
|---|
| 373 | 359 | if (snod->len > avail) |
|---|
| 374 | 360 | /* |
|---|
| 375 | 361 | * Do not skip data nodes in order to optimize |
|---|
| .. | .. |
|---|
| 377 | 363 | */ |
|---|
| 378 | 364 | break; |
|---|
| 379 | 365 | |
|---|
| 366 | + err = ubifs_shash_update(c, c->jheads[GCHD].log_hash, |
|---|
| 367 | + snod->node, snod->len); |
|---|
| 368 | + if (err) |
|---|
| 369 | + goto out; |
|---|
| 370 | + |
|---|
| 380 | 371 | err = move_node(c, sleb, snod, wbuf); |
|---|
| 381 | 372 | if (err) |
|---|
| 382 | 373 | goto out; |
|---|
| 374 | + moved = 1; |
|---|
| 383 | 375 | } |
|---|
| 384 | 376 | |
|---|
| 385 | 377 | /* Move non-data nodes */ |
|---|
| 386 | 378 | list_for_each_entry_safe(snod, tmp, &nondata, list) { |
|---|
| 387 | | - avail = c->leb_size - wbuf->offs - wbuf->used; |
|---|
| 379 | + avail = c->leb_size - wbuf->offs - wbuf->used - |
|---|
| 380 | + ubifs_auth_node_sz(c); |
|---|
| 388 | 381 | if (avail < min) |
|---|
| 389 | 382 | break; |
|---|
| 390 | 383 | |
|---|
| .. | .. |
|---|
| 402 | 395 | continue; |
|---|
| 403 | 396 | } |
|---|
| 404 | 397 | |
|---|
| 398 | + err = ubifs_shash_update(c, c->jheads[GCHD].log_hash, |
|---|
| 399 | + snod->node, snod->len); |
|---|
| 400 | + if (err) |
|---|
| 401 | + goto out; |
|---|
| 402 | + |
|---|
| 405 | 403 | err = move_node(c, sleb, snod, wbuf); |
|---|
| 406 | 404 | if (err) |
|---|
| 407 | 405 | goto out; |
|---|
| 406 | + moved = 1; |
|---|
| 407 | + } |
|---|
| 408 | + |
|---|
| 409 | + if (ubifs_authenticated(c) && moved) { |
|---|
| 410 | + struct ubifs_auth_node *auth; |
|---|
| 411 | + |
|---|
| 412 | + auth = kmalloc(ubifs_auth_node_sz(c), GFP_NOFS); |
|---|
| 413 | + if (!auth) { |
|---|
| 414 | + err = -ENOMEM; |
|---|
| 415 | + goto out; |
|---|
| 416 | + } |
|---|
| 417 | + |
|---|
| 418 | + err = ubifs_prepare_auth_node(c, auth, |
|---|
| 419 | + c->jheads[GCHD].log_hash); |
|---|
| 420 | + if (err) { |
|---|
| 421 | + kfree(auth); |
|---|
| 422 | + goto out; |
|---|
| 423 | + } |
|---|
| 424 | + |
|---|
| 425 | + err = ubifs_wbuf_write_nolock(wbuf, auth, |
|---|
| 426 | + ubifs_auth_node_sz(c)); |
|---|
| 427 | + if (err) { |
|---|
| 428 | + kfree(auth); |
|---|
| 429 | + goto out; |
|---|
| 430 | + } |
|---|
| 431 | + |
|---|
| 432 | + ubifs_add_dirt(c, wbuf->lnum, ubifs_auth_node_sz(c)); |
|---|
| 408 | 433 | } |
|---|
| 409 | 434 | |
|---|
| 410 | 435 | if (list_empty(&sleb->nodes) && list_empty(&nondata)) |
|---|