| .. | .. | 
|---|
| 11 | 11 | #include "xfs_trans_resv.h" | 
|---|
| 12 | 12 | #include "xfs_sb.h" | 
|---|
| 13 | 13 | #include "xfs_mount.h" | 
|---|
| 14 |  | -#include "xfs_defer.h" | 
|---|
| 15 | 14 | #include "xfs_trans.h" | 
|---|
| 16 | 15 | #include "xfs_error.h" | 
|---|
| 17 |  | -#include "xfs_btree.h" | 
|---|
| 18 | 16 | #include "xfs_alloc.h" | 
|---|
| 19 | 17 | #include "xfs_fsops.h" | 
|---|
| 20 | 18 | #include "xfs_trans_space.h" | 
|---|
| 21 |  | -#include "xfs_rtalloc.h" | 
|---|
| 22 |  | -#include "xfs_trace.h" | 
|---|
| 23 | 19 | #include "xfs_log.h" | 
|---|
| 24 | 20 | #include "xfs_ag.h" | 
|---|
| 25 | 21 | #include "xfs_ag_resv.h" | 
|---|
| .. | .. | 
|---|
| 40 | 36 | xfs_rfsblock_t		new; | 
|---|
| 41 | 37 | xfs_agnumber_t		oagcount; | 
|---|
| 42 | 38 | xfs_trans_t		*tp; | 
|---|
| 43 |  | -	LIST_HEAD		(buffer_list); | 
|---|
| 44 | 39 | struct aghdr_init_data	id = {}; | 
|---|
| 45 | 40 |  | 
|---|
| 46 | 41 | nb = in->newblocks; | 
|---|
| .. | .. | 
|---|
| 252 | 247 | if (mp->m_sb.sb_imax_pct) { | 
|---|
| 253 | 248 | uint64_t icount = mp->m_sb.sb_dblocks * mp->m_sb.sb_imax_pct; | 
|---|
| 254 | 249 | do_div(icount, 100); | 
|---|
| 255 |  | -		mp->m_maxicount = icount << mp->m_sb.sb_inopblog; | 
|---|
|  | 250 | +		M_IGEO(mp)->maxicount = XFS_FSB_TO_INO(mp, icount); | 
|---|
| 256 | 251 | } else | 
|---|
| 257 |  | -		mp->m_maxicount = 0; | 
|---|
|  | 252 | +		M_IGEO(mp)->maxicount = 0; | 
|---|
| 258 | 253 |  | 
|---|
| 259 | 254 | /* Update secondary superblocks now the physical grow has completed */ | 
|---|
| 260 | 255 | error = xfs_update_secondary_sbs(mp); | 
|---|
| .. | .. | 
|---|
| 290 | 285 | * exported through ioctl XFS_IOC_FSCOUNTS | 
|---|
| 291 | 286 | */ | 
|---|
| 292 | 287 |  | 
|---|
| 293 |  | -int | 
|---|
|  | 288 | +void | 
|---|
| 294 | 289 | xfs_fs_counts( | 
|---|
| 295 | 290 | xfs_mount_t		*mp, | 
|---|
| 296 | 291 | xfs_fsop_counts_t	*cnt) | 
|---|
| .. | .. | 
|---|
| 303 | 298 | spin_lock(&mp->m_sb_lock); | 
|---|
| 304 | 299 | cnt->freertx = mp->m_sb.sb_frextents; | 
|---|
| 305 | 300 | spin_unlock(&mp->m_sb_lock); | 
|---|
| 306 |  | -	return 0; | 
|---|
| 307 | 301 | } | 
|---|
| 308 | 302 |  | 
|---|
| 309 | 303 | /* | 
|---|
| .. | .. | 
|---|
| 382 | 376 | * If the request is larger than the current reservation, reserve the | 
|---|
| 383 | 377 | * blocks before we update the reserve counters. Sample m_fdblocks and | 
|---|
| 384 | 378 | * perform a partial reservation if the request exceeds free space. | 
|---|
|  | 379 | +	 * | 
|---|
|  | 380 | +	 * The code below estimates how many blocks it can request from | 
|---|
|  | 381 | +	 * fdblocks to stash in the reserve pool.  This is a classic TOCTOU | 
|---|
|  | 382 | +	 * race since fdblocks updates are not always coordinated via | 
|---|
|  | 383 | +	 * m_sb_lock.  Set the reserve size even if there's not enough free | 
|---|
|  | 384 | +	 * space to fill it because mod_fdblocks will refill an undersized | 
|---|
|  | 385 | +	 * reserve when it can. | 
|---|
| 385 | 386 | */ | 
|---|
| 386 |  | -	error = -ENOSPC; | 
|---|
| 387 |  | -	do { | 
|---|
| 388 |  | -		free = percpu_counter_sum(&mp->m_fdblocks) - | 
|---|
| 389 |  | -						mp->m_alloc_set_aside; | 
|---|
| 390 |  | -		if (free <= 0) | 
|---|
| 391 |  | -			break; | 
|---|
| 392 |  | - | 
|---|
| 393 |  | -		delta = request - mp->m_resblks; | 
|---|
| 394 |  | -		lcounter = free - delta; | 
|---|
| 395 |  | -		if (lcounter < 0) | 
|---|
| 396 |  | -			/* We can't satisfy the request, just get what we can */ | 
|---|
| 397 |  | -			fdblks_delta = free; | 
|---|
| 398 |  | -		else | 
|---|
| 399 |  | -			fdblks_delta = delta; | 
|---|
| 400 |  | - | 
|---|
|  | 387 | +	free = percpu_counter_sum(&mp->m_fdblocks) - | 
|---|
|  | 388 | +						xfs_fdblocks_unavailable(mp); | 
|---|
|  | 389 | +	delta = request - mp->m_resblks; | 
|---|
|  | 390 | +	mp->m_resblks = request; | 
|---|
|  | 391 | +	if (delta > 0 && free > 0) { | 
|---|
| 401 | 392 | /* | 
|---|
| 402 | 393 | * We'll either succeed in getting space from the free block | 
|---|
| 403 |  | -		 * count or we'll get an ENOSPC. If we get a ENOSPC, it means | 
|---|
| 404 |  | -		 * things changed while we were calculating fdblks_delta and so | 
|---|
| 405 |  | -		 * we should try again to see if there is anything left to | 
|---|
| 406 |  | -		 * reserve. | 
|---|
|  | 394 | +		 * count or we'll get an ENOSPC.  Don't set the reserved flag | 
|---|
|  | 395 | +		 * here - we don't want to reserve the extra reserve blocks | 
|---|
|  | 396 | +		 * from the reserve. | 
|---|
| 407 | 397 | * | 
|---|
| 408 |  | -		 * Don't set the reserved flag here - we don't want to reserve | 
|---|
| 409 |  | -		 * the extra reserve blocks from the reserve..... | 
|---|
|  | 398 | +		 * The desired reserve size can change after we drop the lock. | 
|---|
|  | 399 | +		 * Use mod_fdblocks to put the space into the reserve or into | 
|---|
|  | 400 | +		 * fdblocks as appropriate. | 
|---|
| 410 | 401 | */ | 
|---|
|  | 402 | +		fdblks_delta = min(free, delta); | 
|---|
| 411 | 403 | spin_unlock(&mp->m_sb_lock); | 
|---|
| 412 | 404 | error = xfs_mod_fdblocks(mp, -fdblks_delta, 0); | 
|---|
|  | 405 | +		if (!error) | 
|---|
|  | 406 | +			xfs_mod_fdblocks(mp, fdblks_delta, 0); | 
|---|
| 413 | 407 | spin_lock(&mp->m_sb_lock); | 
|---|
| 414 |  | -	} while (error == -ENOSPC); | 
|---|
| 415 |  | - | 
|---|
| 416 |  | -	/* | 
|---|
| 417 |  | -	 * Update the reserve counters if blocks have been successfully | 
|---|
| 418 |  | -	 * allocated. | 
|---|
| 419 |  | -	 */ | 
|---|
| 420 |  | -	if (!error && fdblks_delta) { | 
|---|
| 421 |  | -		mp->m_resblks += fdblks_delta; | 
|---|
| 422 |  | -		mp->m_resblks_avail += fdblks_delta; | 
|---|
| 423 | 408 | } | 
|---|
| 424 |  | - | 
|---|
| 425 | 409 | out: | 
|---|
| 426 | 410 | if (outval) { | 
|---|
| 427 | 411 | outval->resblks = mp->m_resblks; | 
|---|
| .. | .. | 
|---|
| 439 | 423 | { | 
|---|
| 440 | 424 | switch (inflags) { | 
|---|
| 441 | 425 | case XFS_FSOP_GOING_FLAGS_DEFAULT: { | 
|---|
| 442 |  | -		struct super_block *sb = freeze_bdev(mp->m_super->s_bdev); | 
|---|
| 443 |  | - | 
|---|
| 444 |  | -		if (sb && !IS_ERR(sb)) { | 
|---|
|  | 426 | +		if (!freeze_bdev(mp->m_super->s_bdev)) { | 
|---|
| 445 | 427 | xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT); | 
|---|
| 446 |  | -			thaw_bdev(sb->s_bdev, sb); | 
|---|
|  | 428 | +			thaw_bdev(mp->m_super->s_bdev); | 
|---|
| 447 | 429 | } | 
|---|
| 448 |  | - | 
|---|
| 449 | 430 | break; | 
|---|
| 450 | 431 | } | 
|---|
| 451 | 432 | case XFS_FSOP_GOING_FLAGS_LOGFLUSH: | 
|---|
| .. | .. | 
|---|
| 470 | 451 | */ | 
|---|
| 471 | 452 | void | 
|---|
| 472 | 453 | xfs_do_force_shutdown( | 
|---|
| 473 |  | -	xfs_mount_t	*mp, | 
|---|
|  | 454 | +	struct xfs_mount *mp, | 
|---|
| 474 | 455 | int		flags, | 
|---|
| 475 | 456 | char		*fname, | 
|---|
| 476 | 457 | int		lnnum) | 
|---|
| 477 | 458 | { | 
|---|
| 478 |  | -	int		logerror; | 
|---|
|  | 459 | +	bool		logerror = flags & SHUTDOWN_LOG_IO_ERROR; | 
|---|
| 479 | 460 |  | 
|---|
| 480 |  | -	logerror = flags & SHUTDOWN_LOG_IO_ERROR; | 
|---|
| 481 |  | - | 
|---|
| 482 |  | -	if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { | 
|---|
| 483 |  | -		xfs_notice(mp, | 
|---|
| 484 |  | -	"%s(0x%x) called from line %d of file %s.  Return address = "PTR_FMT, | 
|---|
| 485 |  | -			__func__, flags, lnnum, fname, __return_address); | 
|---|
| 486 |  | -	} | 
|---|
| 487 | 461 | /* | 
|---|
| 488 | 462 | * No need to duplicate efforts. | 
|---|
| 489 | 463 | */ | 
|---|
| .. | .. | 
|---|
| 499 | 473 | if (xfs_log_force_umount(mp, logerror)) | 
|---|
| 500 | 474 | return; | 
|---|
| 501 | 475 |  | 
|---|
|  | 476 | +	if (flags & SHUTDOWN_FORCE_UMOUNT) { | 
|---|
|  | 477 | +		xfs_alert(mp, | 
|---|
|  | 478 | +"User initiated shutdown received. Shutting down filesystem"); | 
|---|
|  | 479 | +		return; | 
|---|
|  | 480 | +	} | 
|---|
|  | 481 | + | 
|---|
|  | 482 | +	xfs_notice(mp, | 
|---|
|  | 483 | +"%s(0x%x) called from line %d of file %s. Return address = "PTR_FMT, | 
|---|
|  | 484 | +		__func__, flags, lnnum, fname, __return_address); | 
|---|
|  | 485 | + | 
|---|
| 502 | 486 | if (flags & SHUTDOWN_CORRUPT_INCORE) { | 
|---|
| 503 | 487 | xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_CORRUPT, | 
|---|
| 504 |  | -    "Corruption of in-memory data detected.  Shutting down filesystem"); | 
|---|
|  | 488 | +"Corruption of in-memory data detected.  Shutting down filesystem"); | 
|---|
| 505 | 489 | if (XFS_ERRLEVEL_HIGH <= xfs_error_level) | 
|---|
| 506 | 490 | xfs_stack_trace(); | 
|---|
| 507 |  | -	} else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { | 
|---|
| 508 |  | -		if (logerror) { | 
|---|
| 509 |  | -			xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_LOGERROR, | 
|---|
| 510 |  | -		"Log I/O Error Detected.  Shutting down filesystem"); | 
|---|
| 511 |  | -		} else if (flags & SHUTDOWN_DEVICE_REQ) { | 
|---|
| 512 |  | -			xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR, | 
|---|
| 513 |  | -		"All device paths lost.  Shutting down filesystem"); | 
|---|
| 514 |  | -		} else if (!(flags & SHUTDOWN_REMOTE_REQ)) { | 
|---|
| 515 |  | -			xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR, | 
|---|
| 516 |  | -		"I/O Error Detected. Shutting down filesystem"); | 
|---|
| 517 |  | -		} | 
|---|
|  | 491 | +	} else if (logerror) { | 
|---|
|  | 492 | +		xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_LOGERROR, | 
|---|
|  | 493 | +			"Log I/O Error Detected. Shutting down filesystem"); | 
|---|
|  | 494 | +	} else { | 
|---|
|  | 495 | +		xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR, | 
|---|
|  | 496 | +			"I/O Error Detected. Shutting down filesystem"); | 
|---|
| 518 | 497 | } | 
|---|
| 519 |  | -	if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { | 
|---|
| 520 |  | -		xfs_alert(mp, | 
|---|
| 521 |  | -	"Please umount the filesystem and rectify the problem(s)"); | 
|---|
| 522 |  | -	} | 
|---|
|  | 498 | + | 
|---|
|  | 499 | +	xfs_alert(mp, | 
|---|
|  | 500 | +		"Please unmount the filesystem and rectify the problem(s)"); | 
|---|
| 523 | 501 | } | 
|---|
| 524 | 502 |  | 
|---|
| 525 | 503 | /* | 
|---|