diff options
Diffstat (limited to 'fs/xfs')
| -rw-r--r-- | fs/xfs/xfs_aops.c | 18 | ||||
| -rw-r--r-- | fs/xfs/xfs_file.c | 10 | ||||
| -rw-r--r-- | fs/xfs/xfs_ioctl.c | 55 | ||||
| -rw-r--r-- | fs/xfs/xfs_ioctl32.c | 12 | ||||
| -rw-r--r-- | fs/xfs/xfs_iomap.c | 4 | ||||
| -rw-r--r-- | fs/xfs/xfs_mount.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_mount.h | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_sync.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_trans.c | 17 | ||||
| -rw-r--r-- | fs/xfs/xfs_trans.h | 2 | 
10 files changed, 109 insertions, 16 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 8dad722c004..daa42383ebd 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -124,6 +124,12 @@ xfs_setfilesize_trans_alloc(  	ioend->io_append_trans = tp;  	/* +	 * We will pass freeze protection with a transaction.  So tell lockdep +	 * we released it. +	 */ +	rwsem_release(&ioend->io_inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1], +		      1, _THIS_IP_); +	/*  	 * We hand off the transaction to the completion thread now, so  	 * clear the flag here.  	 */ @@ -199,6 +205,15 @@ xfs_end_io(  	struct xfs_inode *ip = XFS_I(ioend->io_inode);  	int		error = 0; +	if (ioend->io_append_trans) { +		/* +		 * We've got freeze protection passed with the transaction. +		 * Tell lockdep about it. +		 */ +		rwsem_acquire_read( +			&ioend->io_inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1], +			0, 1, _THIS_IP_); +	}  	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {  		ioend->io_error = -EIO;  		goto done; @@ -1410,6 +1425,9 @@ out_trans_cancel:  	if (ioend->io_append_trans) {  		current_set_flags_nested(&ioend->io_append_trans->t_pflags,  					 PF_FSTRANS); +		rwsem_acquire_read( +			&inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1], +			0, 1, _THIS_IP_);  		xfs_trans_cancel(ioend->io_append_trans, 0);  	}  out_destroy_ioend: diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 9f7ec15a652..f0081f20e5c 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -781,10 +781,12 @@ xfs_file_aio_write(  	if (ocount == 0)  		return 0; -	xfs_wait_for_freeze(ip->i_mount, SB_FREEZE_WRITE); +	sb_start_write(inode->i_sb); -	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) -		return -EIO; +	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { +		ret = -EIO; +		goto out; +	}  	if (unlikely(file->f_flags & O_DIRECT))  		ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, ocount); @@ -803,6 +805,8 @@ xfs_file_aio_write(  			ret = err;  	} +out: +	sb_end_write(inode->i_sb);  	return ret;  } diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 1f1535d25a9..0e0232c3b6d 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -364,9 +364,15 @@ xfs_fssetdm_by_handle(  	if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t)))  		return -XFS_ERROR(EFAULT); +	error = mnt_want_write_file(parfilp); +	if (error) +		return error; +  	dentry = xfs_handlereq_to_dentry(parfilp, &dmhreq.hreq); -	if (IS_ERR(dentry)) +	if (IS_ERR(dentry)) { +		mnt_drop_write_file(parfilp);  		return PTR_ERR(dentry); +	}  	if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) {  		error = -XFS_ERROR(EPERM); @@ -382,6 +388,7 @@ xfs_fssetdm_by_handle(  				 fsd.fsd_dmstate);   out: +	mnt_drop_write_file(parfilp);  	dput(dentry);  	return error;  } @@ -634,7 +641,11 @@ xfs_ioc_space(  	if (ioflags & IO_INVIS)  		attr_flags |= XFS_ATTR_DMI; +	error = mnt_want_write_file(filp); +	if (error) +		return error;  	error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags); +	mnt_drop_write_file(filp);  	return -error;  } @@ -1163,6 +1174,7 @@ xfs_ioc_fssetxattr(  {  	struct fsxattr		fa;  	unsigned int		mask; +	int error;  	if (copy_from_user(&fa, arg, sizeof(fa)))  		return -EFAULT; @@ -1171,7 +1183,12 @@ xfs_ioc_fssetxattr(  	if (filp->f_flags & (O_NDELAY|O_NONBLOCK))  		mask |= FSX_NONBLOCK; -	return -xfs_ioctl_setattr(ip, &fa, mask); +	error = mnt_want_write_file(filp); +	if (error) +		return error; +	error = xfs_ioctl_setattr(ip, &fa, mask); +	mnt_drop_write_file(filp); +	return -error;  }  STATIC int @@ -1196,6 +1213,7 @@ xfs_ioc_setxflags(  	struct fsxattr		fa;  	unsigned int		flags;  	unsigned int		mask; +	int error;  	if (copy_from_user(&flags, arg, sizeof(flags)))  		return -EFAULT; @@ -1210,7 +1228,12 @@ xfs_ioc_setxflags(  		mask |= FSX_NONBLOCK;  	fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip)); -	return -xfs_ioctl_setattr(ip, &fa, mask); +	error = mnt_want_write_file(filp); +	if (error) +		return error; +	error = xfs_ioctl_setattr(ip, &fa, mask); +	mnt_drop_write_file(filp); +	return -error;  }  STATIC int @@ -1385,8 +1408,13 @@ xfs_file_ioctl(  		if (copy_from_user(&dmi, arg, sizeof(dmi)))  			return -XFS_ERROR(EFAULT); +		error = mnt_want_write_file(filp); +		if (error) +			return error; +  		error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,  				dmi.fsd_dmstate); +		mnt_drop_write_file(filp);  		return -error;  	} @@ -1434,7 +1462,11 @@ xfs_file_ioctl(  		if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))  			return -XFS_ERROR(EFAULT); +		error = mnt_want_write_file(filp); +		if (error) +			return error;  		error = xfs_swapext(&sxp); +		mnt_drop_write_file(filp);  		return -error;  	} @@ -1463,9 +1495,14 @@ xfs_file_ioctl(  		if (copy_from_user(&inout, arg, sizeof(inout)))  			return -XFS_ERROR(EFAULT); +		error = mnt_want_write_file(filp); +		if (error) +			return error; +  		/* input parameter is passed in resblks field of structure */  		in = inout.resblks;  		error = xfs_reserve_blocks(mp, &in, &inout); +		mnt_drop_write_file(filp);  		if (error)  			return -error; @@ -1496,7 +1533,11 @@ xfs_file_ioctl(  		if (copy_from_user(&in, arg, sizeof(in)))  			return -XFS_ERROR(EFAULT); +		error = mnt_want_write_file(filp); +		if (error) +			return error;  		error = xfs_growfs_data(mp, &in); +		mnt_drop_write_file(filp);  		return -error;  	} @@ -1506,7 +1547,11 @@ xfs_file_ioctl(  		if (copy_from_user(&in, arg, sizeof(in)))  			return -XFS_ERROR(EFAULT); +		error = mnt_want_write_file(filp); +		if (error) +			return error;  		error = xfs_growfs_log(mp, &in); +		mnt_drop_write_file(filp);  		return -error;  	} @@ -1516,7 +1561,11 @@ xfs_file_ioctl(  		if (copy_from_user(&in, arg, sizeof(in)))  			return -XFS_ERROR(EFAULT); +		error = mnt_want_write_file(filp); +		if (error) +			return error;  		error = xfs_growfs_rt(mp, &in); +		mnt_drop_write_file(filp);  		return -error;  	} diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c index c4f2da0d2bf..1244274a567 100644 --- a/fs/xfs/xfs_ioctl32.c +++ b/fs/xfs/xfs_ioctl32.c @@ -600,7 +600,11 @@ xfs_file_compat_ioctl(  		if (xfs_compat_growfs_data_copyin(&in, arg))  			return -XFS_ERROR(EFAULT); +		error = mnt_want_write_file(filp); +		if (error) +			return error;  		error = xfs_growfs_data(mp, &in); +		mnt_drop_write_file(filp);  		return -error;  	}  	case XFS_IOC_FSGROWFSRT_32: { @@ -608,7 +612,11 @@ xfs_file_compat_ioctl(  		if (xfs_compat_growfs_rt_copyin(&in, arg))  			return -XFS_ERROR(EFAULT); +		error = mnt_want_write_file(filp); +		if (error) +			return error;  		error = xfs_growfs_rt(mp, &in); +		mnt_drop_write_file(filp);  		return -error;  	}  #endif @@ -627,7 +635,11 @@ xfs_file_compat_ioctl(  				   offsetof(struct xfs_swapext, sx_stat)) ||  		    xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat))  			return -XFS_ERROR(EFAULT); +		error = mnt_want_write_file(filp); +		if (error) +			return error;  		error = xfs_swapext(&sxp); +		mnt_drop_write_file(filp);  		return -error;  	}  	case XFS_IOC_FSBULKSTAT_32: diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index aadfce6681e..b3b9b26091a 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -680,9 +680,9 @@ xfs_iomap_write_unwritten(  		 * the same inode that we complete here and might deadlock  		 * on the iolock.  		 */ -		xfs_wait_for_freeze(mp, SB_FREEZE_TRANS); +		sb_start_intwrite(mp->m_super);  		tp = _xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE, KM_NOFS); -		tp->t_flags |= XFS_TRANS_RESERVE; +		tp->t_flags |= XFS_TRANS_RESERVE | XFS_TRANS_FREEZE_PROT;  		error = xfs_trans_reserve(tp, resblks,  				XFS_WRITE_LOG_RES(mp), 0,  				XFS_TRANS_PERM_LOG_RES, diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 536021fb3d4..b09a4a7eb64 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1544,7 +1544,7 @@ xfs_unmountfs(  int  xfs_fs_writable(xfs_mount_t *mp)  { -	return !(xfs_test_for_freeze(mp) || XFS_FORCED_SHUTDOWN(mp) || +	return !(mp->m_super->s_writers.frozen || XFS_FORCED_SHUTDOWN(mp) ||  		(mp->m_flags & XFS_MOUNT_RDONLY));  } diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 90c1fc9eaea..c6bca0d92cb 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -314,9 +314,6 @@ void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname,  #define SHUTDOWN_REMOTE_REQ	0x0010	/* shutdown came from remote cell */  #define SHUTDOWN_DEVICE_REQ	0x0020	/* failed all paths to the device */ -#define xfs_test_for_freeze(mp)		((mp)->m_super->s_frozen) -#define xfs_wait_for_freeze(mp,l)	vfs_check_frozen((mp)->m_super, (l)) -  /*   * Flags for xfs_mountfs   */ diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c index 1e9ee064dbb..0b9feacdcd1 100644 --- a/fs/xfs/xfs_sync.c +++ b/fs/xfs/xfs_sync.c @@ -394,7 +394,7 @@ xfs_sync_worker(  	if (!(mp->m_super->s_flags & MS_ACTIVE) &&  	    !(mp->m_flags & XFS_MOUNT_RDONLY)) {  		/* dgc: errors ignored here */ -		if (mp->m_super->s_frozen == SB_UNFROZEN && +		if (mp->m_super->s_writers.frozen == SB_UNFROZEN &&  		    xfs_log_need_covered(mp))  			error = xfs_fs_log_dummy(mp);  		else diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index fdf324508c5..06ed520a767 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -576,8 +576,12 @@ xfs_trans_alloc(  	xfs_mount_t	*mp,  	uint		type)  { -	xfs_wait_for_freeze(mp, SB_FREEZE_TRANS); -	return _xfs_trans_alloc(mp, type, KM_SLEEP); +	xfs_trans_t     *tp; + +	sb_start_intwrite(mp->m_super); +	tp = _xfs_trans_alloc(mp, type, KM_SLEEP); +	tp->t_flags |= XFS_TRANS_FREEZE_PROT; +	return tp;  }  xfs_trans_t * @@ -588,6 +592,7 @@ _xfs_trans_alloc(  {  	xfs_trans_t	*tp; +	WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE);  	atomic_inc(&mp->m_active_trans);  	tp = kmem_zone_zalloc(xfs_trans_zone, memflags); @@ -611,6 +616,8 @@ xfs_trans_free(  	xfs_extent_busy_clear(tp->t_mountp, &tp->t_busy, false);  	atomic_dec(&tp->t_mountp->m_active_trans); +	if (tp->t_flags & XFS_TRANS_FREEZE_PROT) +		sb_end_intwrite(tp->t_mountp->m_super);  	xfs_trans_free_dqinfo(tp);  	kmem_zone_free(xfs_trans_zone, tp);  } @@ -643,7 +650,11 @@ xfs_trans_dup(  	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);  	ASSERT(tp->t_ticket != NULL); -	ntp->t_flags = XFS_TRANS_PERM_LOG_RES | (tp->t_flags & XFS_TRANS_RESERVE); +	ntp->t_flags = XFS_TRANS_PERM_LOG_RES | +		       (tp->t_flags & XFS_TRANS_RESERVE) | +		       (tp->t_flags & XFS_TRANS_FREEZE_PROT); +	/* We gave our writer reference to the new transaction */ +	tp->t_flags &= ~XFS_TRANS_FREEZE_PROT;  	ntp->t_ticket = xfs_log_ticket_get(tp->t_ticket);  	ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used;  	tp->t_blk_res = tp->t_blk_res_used; diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 7c37b533aa8..19c17428287 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -179,6 +179,8 @@ struct xfs_log_item_desc {  #define	XFS_TRANS_SYNC		0x08	/* make commit synchronous */  #define XFS_TRANS_DQ_DIRTY	0x10	/* at least one dquot in trx dirty */  #define XFS_TRANS_RESERVE	0x20    /* OK to use reserved data blocks */ +#define XFS_TRANS_FREEZE_PROT	0x40	/* Transaction has elevated writer +					   count in superblock */  /*   * Values for call flags parameter.  |