| .. | .. | 
|---|
 | 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)) | 
|---|