diff options
Diffstat (limited to 'fs/xfs/xfs_iops.c')
| -rw-r--r-- | fs/xfs/xfs_iops.c | 117 | 
1 files changed, 74 insertions, 43 deletions
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index fb7dc61f4a29..c5d4eba6972e 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -181,6 +181,8 @@ xfs_generic_create(  	}  #endif +	xfs_setup_iops(ip); +  	if (tmpfile)  		d_tmpfile(dentry, inode);  	else @@ -368,6 +370,8 @@ xfs_vn_symlink(  	if (unlikely(error))  		goto out_cleanup_inode; +	xfs_setup_iops(cip); +  	d_instantiate(dentry, inode);  	xfs_finish_inode_setup(cip);  	return 0; @@ -442,6 +446,16 @@ xfs_vn_get_link(  	return ERR_PTR(error);  } +STATIC const char * +xfs_vn_get_link_inline( +	struct dentry		*dentry, +	struct inode		*inode, +	struct delayed_call	*done) +{ +	ASSERT(XFS_I(inode)->i_df.if_flags & XFS_IFINLINE); +	return XFS_I(inode)->i_df.if_u1.if_data; +} +  STATIC int  xfs_vn_getattr(  	struct vfsmount		*mnt, @@ -599,12 +613,12 @@ xfs_setattr_nonsize(  			return error;  	} -	tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE); -	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0); +	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);  	if (error) -		goto out_trans_cancel; +		goto out_dqrele;  	xfs_ilock(ip, XFS_ILOCK_EXCL); +	xfs_trans_ijoin(tp, ip, 0);  	/*  	 * Change file ownership.  Must be the owner or privileged. @@ -633,12 +647,10 @@ xfs_setattr_nonsize(  						NULL, capable(CAP_FOWNER) ?  						XFS_QMOPT_FORCE_RES : 0);  			if (error)	/* out of quota */ -				goto out_unlock; +				goto out_cancel;  		}  	} -	xfs_trans_ijoin(tp, ip, 0); -  	/*  	 * Change file ownership.  Must be the owner or privileged.  	 */ @@ -722,10 +734,9 @@ xfs_setattr_nonsize(  	return 0; -out_unlock: -	xfs_iunlock(ip, XFS_ILOCK_EXCL); -out_trans_cancel: +out_cancel:  	xfs_trans_cancel(tp); +out_dqrele:  	xfs_qm_dqrele(udqp);  	xfs_qm_dqrele(gdqp);  	return error; @@ -834,7 +845,7 @@ xfs_setattr_size(  	 * We have to do all the page cache truncate work outside the  	 * transaction context as the "lock" order is page lock->log space  	 * reservation as defined by extent allocation in the writeback path. -	 * Hence a truncate can fail with ENOMEM from xfs_trans_reserve(), but +	 * Hence a truncate can fail with ENOMEM from xfs_trans_alloc(), but  	 * having already truncated the in-memory version of the file (i.e. made  	 * user visible changes). There's not much we can do about this, except  	 * to hope that the caller sees ENOMEM and retries the truncate @@ -849,10 +860,9 @@ xfs_setattr_size(  		return error;  	truncate_setsize(inode, newsize); -	tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE); -	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); +	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);  	if (error) -		goto out_trans_cancel; +		return error;  	lock_flags |= XFS_ILOCK_EXCL;  	xfs_ilock(ip, XFS_ILOCK_EXCL); @@ -971,12 +981,9 @@ xfs_vn_update_time(  	trace_xfs_update_time(ip); -	tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); -	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0); -	if (error) { -		xfs_trans_cancel(tp); +	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp); +	if (error)  		return error; -	}  	xfs_ilock(ip, XFS_ILOCK_EXCL);  	if (flags & S_CTIME) @@ -1167,6 +1174,18 @@ static const struct inode_operations xfs_symlink_inode_operations = {  	.update_time		= xfs_vn_update_time,  }; +static const struct inode_operations xfs_inline_symlink_inode_operations = { +	.readlink		= generic_readlink, +	.get_link		= xfs_vn_get_link_inline, +	.getattr		= xfs_vn_getattr, +	.setattr		= xfs_vn_setattr, +	.setxattr		= generic_setxattr, +	.getxattr		= generic_getxattr, +	.removexattr		= generic_removexattr, +	.listxattr		= xfs_vn_listxattr, +	.update_time		= xfs_vn_update_time, +}; +  STATIC void  xfs_diflags_to_iflags(  	struct inode		*inode, @@ -1193,7 +1212,7 @@ xfs_diflags_to_iflags(  }  /* - * Initialize the Linux inode and set up the operation vectors. + * Initialize the Linux inode.   *   * When reading existing inodes from disk this is called directly from xfs_iget,   * when creating a new inode it is called from xfs_ialloc after setting up the @@ -1232,32 +1251,12 @@ xfs_setup_inode(  	i_size_write(inode, ip->i_d.di_size);  	xfs_diflags_to_iflags(inode, ip); -	ip->d_ops = ip->i_mount->m_nondir_inode_ops; -	lockdep_set_class(&ip->i_lock.mr_lock, &xfs_nondir_ilock_class); -	switch (inode->i_mode & S_IFMT) { -	case S_IFREG: -		inode->i_op = &xfs_inode_operations; -		inode->i_fop = &xfs_file_operations; -		inode->i_mapping->a_ops = &xfs_address_space_operations; -		break; -	case S_IFDIR: +	if (S_ISDIR(inode->i_mode)) {  		lockdep_set_class(&ip->i_lock.mr_lock, &xfs_dir_ilock_class); -		if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb)) -			inode->i_op = &xfs_dir_ci_inode_operations; -		else -			inode->i_op = &xfs_dir_inode_operations; -		inode->i_fop = &xfs_dir_file_operations;  		ip->d_ops = ip->i_mount->m_dir_inode_ops; -		break; -	case S_IFLNK: -		inode->i_op = &xfs_symlink_inode_operations; -		if (!(ip->i_df.if_flags & XFS_IFINLINE)) -			inode->i_mapping->a_ops = &xfs_address_space_operations; -		break; -	default: -		inode->i_op = &xfs_inode_operations; -		init_special_inode(inode, inode->i_mode, inode->i_rdev); -		break; +	} else { +		ip->d_ops = ip->i_mount->m_nondir_inode_ops; +		lockdep_set_class(&ip->i_lock.mr_lock, &xfs_nondir_ilock_class);  	}  	/* @@ -1277,3 +1276,35 @@ xfs_setup_inode(  		cache_no_acl(inode);  	}  } + +void +xfs_setup_iops( +	struct xfs_inode	*ip) +{ +	struct inode		*inode = &ip->i_vnode; + +	switch (inode->i_mode & S_IFMT) { +	case S_IFREG: +		inode->i_op = &xfs_inode_operations; +		inode->i_fop = &xfs_file_operations; +		inode->i_mapping->a_ops = &xfs_address_space_operations; +		break; +	case S_IFDIR: +		if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb)) +			inode->i_op = &xfs_dir_ci_inode_operations; +		else +			inode->i_op = &xfs_dir_inode_operations; +		inode->i_fop = &xfs_dir_file_operations; +		break; +	case S_IFLNK: +		if (ip->i_df.if_flags & XFS_IFINLINE) +			inode->i_op = &xfs_inline_symlink_inode_operations; +		else +			inode->i_op = &xfs_symlink_inode_operations; +		break; +	default: +		inode->i_op = &xfs_inode_operations; +		init_special_inode(inode, inode->i_mode, inode->i_rdev); +		break; +	} +}  |