X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=fs%2Fxfs%2Fxfs_iops.c;h=d046dc8c1925619bf899de8d6acf54fc9a2d6fb1;hb=d420e5c810bce5debce0238021b410d0ef99cf08;hp=96dda62d497b7e04a68a1a6ddfc579aececf8374;hpb=36f571e9ed0419e73d127e18aa8992ced867268c;p=deliverable%2Flinux.git diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 96dda62d497b..d046dc8c1925 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -17,6 +17,8 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_acl.h" #include "xfs_log.h" #include "xfs_trans.h" @@ -25,20 +27,23 @@ #include "xfs_alloc.h" #include "xfs_quota.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_bmap.h" +#include "xfs_bmap_util.h" #include "xfs_rtalloc.h" #include "xfs_error.h" #include "xfs_itable.h" #include "xfs_attr.h" #include "xfs_buf_item.h" -#include "xfs_utils.h" -#include "xfs_vnodeops.h" #include "xfs_inode_item.h" #include "xfs_trace.h" #include "xfs_icache.h" +#include "xfs_symlink.h" +#include "xfs_da_btree.h" +#include "xfs_dir2_priv.h" #include #include @@ -87,10 +92,12 @@ xfs_init_security( static void xfs_dentry_to_name( struct xfs_name *namep, - struct dentry *dentry) + struct dentry *dentry, + int mode) { namep->name = dentry->d_name.name; namep->len = dentry->d_name.len; + namep->type = xfs_mode_to_ftype[(mode & S_IFMT) >> S_SHIFT]; } STATIC void @@ -106,7 +113,7 @@ xfs_cleanup_inode( * xfs_init_security we must back out. * ENOSPC can hit here, among other things. */ - xfs_dentry_to_name(&teardown, dentry); + xfs_dentry_to_name(&teardown, dentry, 0); xfs_remove(XFS_I(dir), &teardown, XFS_I(inode)); iput(inode); @@ -146,7 +153,7 @@ xfs_vn_mknod( mode &= ~current_umask(); } - xfs_dentry_to_name(&name, dentry); + xfs_dentry_to_name(&name, dentry, mode); error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip); if (unlikely(error)) goto out_free_acl; @@ -207,7 +214,7 @@ xfs_vn_lookup( if (dentry->d_name.len >= MAXNAMELEN) return ERR_PTR(-ENAMETOOLONG); - xfs_dentry_to_name(&name, dentry); + xfs_dentry_to_name(&name, dentry, 0); error = xfs_lookup(XFS_I(dir), &name, &cip, NULL); if (unlikely(error)) { if (unlikely(error != ENOENT)) @@ -234,7 +241,7 @@ xfs_vn_ci_lookup( if (dentry->d_name.len >= MAXNAMELEN) return ERR_PTR(-ENAMETOOLONG); - xfs_dentry_to_name(&xname, dentry); + xfs_dentry_to_name(&xname, dentry, 0); error = xfs_lookup(XFS_I(dir), &xname, &ip, &ci_name); if (unlikely(error)) { if (unlikely(error != ENOENT)) @@ -269,7 +276,7 @@ xfs_vn_link( struct xfs_name name; int error; - xfs_dentry_to_name(&name, dentry); + xfs_dentry_to_name(&name, dentry, inode->i_mode); error = xfs_link(XFS_I(dir), XFS_I(inode), &name); if (unlikely(error)) @@ -288,7 +295,7 @@ xfs_vn_unlink( struct xfs_name name; int error; - xfs_dentry_to_name(&name, dentry); + xfs_dentry_to_name(&name, dentry, 0); error = -xfs_remove(XFS_I(dir), &name, XFS_I(dentry->d_inode)); if (error) @@ -318,7 +325,7 @@ xfs_vn_symlink( mode = S_IFLNK | (irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO); - xfs_dentry_to_name(&name, dentry); + xfs_dentry_to_name(&name, dentry, mode); error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip); if (unlikely(error)) @@ -350,12 +357,12 @@ xfs_vn_rename( struct xfs_name oname; struct xfs_name nname; - xfs_dentry_to_name(&oname, odentry); - xfs_dentry_to_name(&nname, ndentry); + xfs_dentry_to_name(&oname, odentry, 0); + xfs_dentry_to_name(&nname, ndentry, odentry->d_inode->i_mode); return -xfs_rename(XFS_I(odir), &oname, XFS_I(odentry->d_inode), XFS_I(ndir), &nname, new_inode ? - XFS_I(new_inode) : NULL); + XFS_I(new_inode) : NULL); } /* @@ -420,8 +427,8 @@ xfs_vn_getattr( stat->dev = inode->i_sb->s_dev; stat->mode = ip->i_d.di_mode; stat->nlink = ip->i_d.di_nlink; - stat->uid = ip->i_d.di_uid; - stat->gid = ip->i_d.di_gid; + stat->uid = inode->i_uid; + stat->gid = inode->i_gid; stat->ino = ip->i_ino; stat->atime = inode->i_atime; stat->mtime = inode->i_mtime; @@ -485,8 +492,8 @@ xfs_setattr_nonsize( int mask = iattr->ia_valid; xfs_trans_t *tp; int error; - uid_t uid = 0, iuid = 0; - gid_t gid = 0, igid = 0; + kuid_t uid = GLOBAL_ROOT_UID, iuid = GLOBAL_ROOT_UID; + kgid_t gid = GLOBAL_ROOT_GID, igid = GLOBAL_ROOT_GID; struct xfs_dquot *udqp = NULL, *gdqp = NULL; struct xfs_dquot *olddquot1 = NULL, *olddquot2 = NULL; @@ -522,13 +529,13 @@ xfs_setattr_nonsize( uid = iattr->ia_uid; qflags |= XFS_QMOPT_UQUOTA; } else { - uid = ip->i_d.di_uid; + uid = inode->i_uid; } if ((mask & ATTR_GID) && XFS_IS_GQUOTA_ON(mp)) { gid = iattr->ia_gid; qflags |= XFS_QMOPT_GQUOTA; } else { - gid = ip->i_d.di_gid; + gid = inode->i_gid; } /* @@ -538,14 +545,16 @@ xfs_setattr_nonsize( */ ASSERT(udqp == NULL); ASSERT(gdqp == NULL); - error = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip), - qflags, &udqp, &gdqp, NULL); + error = xfs_qm_vop_dqalloc(ip, xfs_kuid_to_uid(uid), + xfs_kgid_to_gid(gid), + xfs_get_projid(ip), + qflags, &udqp, &gdqp, NULL); if (error) return error; } tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE); - error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0); + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0); if (error) goto out_dqrele; @@ -561,8 +570,8 @@ xfs_setattr_nonsize( * while we didn't have the inode locked, inode's dquot(s) * would have changed also. */ - iuid = ip->i_d.di_uid; - igid = ip->i_d.di_gid; + iuid = inode->i_uid; + igid = inode->i_gid; gid = (mask & ATTR_GID) ? iattr->ia_gid : igid; uid = (mask & ATTR_UID) ? iattr->ia_uid : iuid; @@ -571,8 +580,8 @@ xfs_setattr_nonsize( * going to change. */ if (XFS_IS_QUOTA_RUNNING(mp) && - ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) || - (XFS_IS_GQUOTA_ON(mp) && igid != gid))) { + ((XFS_IS_UQUOTA_ON(mp) && !uid_eq(iuid, uid)) || + (XFS_IS_GQUOTA_ON(mp) && !gid_eq(igid, gid)))) { ASSERT(tp); error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, NULL, capable(CAP_FOWNER) ? @@ -602,17 +611,17 @@ xfs_setattr_nonsize( * Change the ownerships and register quota modifications * in the transaction. */ - if (iuid != uid) { + if (!uid_eq(iuid, uid)) { if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_UQUOTA_ON(mp)) { ASSERT(mask & ATTR_UID); ASSERT(udqp); olddquot1 = xfs_qm_vop_chown(tp, ip, &ip->i_udquot, udqp); } - ip->i_d.di_uid = uid; + ip->i_d.di_uid = xfs_kuid_to_uid(uid); inode->i_uid = uid; } - if (igid != gid) { + if (!gid_eq(igid, gid)) { if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_GQUOTA_ON(mp)) { ASSERT(!XFS_IS_PQUOTA_ON(mp)); ASSERT(mask & ATTR_GID); @@ -620,7 +629,7 @@ xfs_setattr_nonsize( olddquot2 = xfs_qm_vop_chown(tp, ip, &ip->i_gdquot, gdqp); } - ip->i_d.di_gid = gid; + ip->i_d.di_gid = xfs_kgid_to_gid(gid); inode->i_gid = gid; } } @@ -701,8 +710,7 @@ out_dqrele: int xfs_setattr_size( struct xfs_inode *ip, - struct iattr *iattr, - int flags) + struct iattr *iattr) { struct xfs_mount *mp = ip->i_mount; struct inode *inode = VFS_I(ip); @@ -725,15 +733,11 @@ xfs_setattr_size( if (error) return XFS_ERROR(error); + ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); ASSERT(S_ISREG(ip->i_d.di_mode)); ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); - if (!(flags & XFS_ATTR_NOLOCK)) { - lock_flags |= XFS_IOLOCK_EXCL; - xfs_ilock(ip, lock_flags); - } - oldsize = inode->i_size; newsize = iattr->ia_size; @@ -742,12 +746,11 @@ xfs_setattr_size( */ if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) { if (!(mask & (ATTR_CTIME|ATTR_MTIME))) - goto out_unlock; + return 0; /* * Use the regular setattr path to update the timestamps. */ - xfs_iunlock(ip, lock_flags); iattr->ia_valid &= ~ATTR_SIZE; return xfs_setattr_nonsize(ip, iattr, 0); } @@ -757,7 +760,7 @@ xfs_setattr_size( */ error = xfs_qm_dqattach(ip, 0); if (error) - goto out_unlock; + return error; /* * Now we can make the changes. Before we join the inode to the @@ -775,7 +778,7 @@ xfs_setattr_size( */ error = xfs_zero_eof(ip, newsize, oldsize); if (error) - goto out_unlock; + return error; } /* @@ -794,7 +797,7 @@ xfs_setattr_size( error = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping, ip->i_d.di_size, newsize); if (error) - goto out_unlock; + return error; } /* @@ -804,12 +807,10 @@ xfs_setattr_size( error = -block_truncate_page(inode->i_mapping, newsize, xfs_get_blocks); if (error) - goto out_unlock; + return error; tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE); - error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, - XFS_TRANS_PERM_LOG_RES, - XFS_ITRUNCATE_LOG_COUNT); + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); if (error) goto out_trans_cancel; @@ -910,12 +911,21 @@ out_trans_cancel: STATIC int xfs_vn_setattr( - struct dentry *dentry, - struct iattr *iattr) + struct dentry *dentry, + struct iattr *iattr) { - if (iattr->ia_valid & ATTR_SIZE) - return -xfs_setattr_size(XFS_I(dentry->d_inode), iattr, 0); - return -xfs_setattr_nonsize(XFS_I(dentry->d_inode), iattr, 0); + struct xfs_inode *ip = XFS_I(dentry->d_inode); + int error; + + if (iattr->ia_valid & ATTR_SIZE) { + xfs_ilock(ip, XFS_IOLOCK_EXCL); + error = xfs_setattr_size(ip, iattr); + xfs_iunlock(ip, XFS_IOLOCK_EXCL); + } else { + error = xfs_setattr_nonsize(ip, iattr, 0); + } + + return -error; } STATIC int @@ -932,7 +942,7 @@ xfs_vn_update_time( trace_xfs_update_time(ip); tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); - error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0); if (error) { xfs_trans_cancel(tp, 0); return -error; @@ -1173,8 +1183,8 @@ xfs_setup_inode( inode->i_mode = ip->i_d.di_mode; set_nlink(inode, ip->i_d.di_nlink); - inode->i_uid = ip->i_d.di_uid; - inode->i_gid = ip->i_d.di_gid; + inode->i_uid = xfs_uid_to_kuid(ip->i_d.di_uid); + inode->i_gid = xfs_gid_to_kgid(ip->i_d.di_gid); switch (inode->i_mode & S_IFMT) { case S_IFBLK: