Loading fs/xfs/xfs_inode.c +117 −6 Original line number Diff line number Diff line Loading @@ -42,7 +42,6 @@ #include "xfs_bmap_util.h" #include "xfs_error.h" #include "xfs_quota.h" #include "xfs_dinode.h" #include "xfs_filestream.h" #include "xfs_cksum.h" #include "xfs_trace.h" Loading @@ -62,6 +61,8 @@ kmem_zone_t *xfs_inode_zone; STATIC int xfs_iflush_int(xfs_inode_t *, xfs_buf_t *); STATIC int xfs_iunlink_remove(xfs_trans_t *, xfs_inode_t *); /* * helper function to extract extent size hint from inode */ Loading Loading @@ -1115,7 +1116,7 @@ xfs_bumplink( { xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); ASSERT(ip->i_d.di_nlink > 0); ASSERT(ip->i_d.di_nlink > 0 || (VFS_I(ip)->i_state & I_LINKABLE)); ip->i_d.di_nlink++; inc_nlink(VFS_I(ip)); if ((ip->i_d.di_version == 1) && Loading Loading @@ -1165,10 +1166,7 @@ xfs_create( if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) prid = xfs_get_projid(dp); else prid = XFS_PROJID_DEFAULT; prid = xfs_get_initial_prid(dp); /* * Make sure that we have allocated dquot(s) on disk. Loading Loading @@ -1332,6 +1330,113 @@ xfs_create( return error; } int xfs_create_tmpfile( struct xfs_inode *dp, struct dentry *dentry, umode_t mode) { struct xfs_mount *mp = dp->i_mount; struct xfs_inode *ip = NULL; struct xfs_trans *tp = NULL; int error; uint cancel_flags = XFS_TRANS_RELEASE_LOG_RES; prid_t prid; struct xfs_dquot *udqp = NULL; struct xfs_dquot *gdqp = NULL; struct xfs_dquot *pdqp = NULL; struct xfs_trans_res *tres; uint resblks; if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); prid = xfs_get_initial_prid(dp); /* * Make sure that we have allocated dquot(s) on disk. */ error = xfs_qm_vop_dqalloc(dp, xfs_kuid_to_uid(current_fsuid()), xfs_kgid_to_gid(current_fsgid()), prid, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp); if (error) return error; resblks = XFS_IALLOC_SPACE_RES(mp); tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE_TMPFILE); tres = &M_RES(mp)->tr_create_tmpfile; error = xfs_trans_reserve(tp, tres, resblks, 0); if (error == ENOSPC) { /* No space at all so try a "no-allocation" reservation */ resblks = 0; error = xfs_trans_reserve(tp, tres, 0, 0); } if (error) { cancel_flags = 0; goto out_trans_cancel; } error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, pdqp, resblks, 1, 0); if (error) goto out_trans_cancel; error = xfs_dir_ialloc(&tp, dp, mode, 1, 0, prid, resblks > 0, &ip, NULL); if (error) { if (error == ENOSPC) goto out_trans_cancel; goto out_trans_abort; } if (mp->m_flags & XFS_MOUNT_WSYNC) xfs_trans_set_sync(tp); /* * Attach the dquot(s) to the inodes and modify them incore. * These ids of the inode couldn't have changed since the new * inode has been locked ever since it was created. */ xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); ip->i_d.di_nlink--; d_tmpfile(dentry, VFS_I(ip)); error = xfs_iunlink(tp, ip); if (error) goto out_trans_abort; error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); if (error) goto out_release_inode; xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); xfs_qm_dqrele(pdqp); return 0; out_trans_abort: cancel_flags |= XFS_TRANS_ABORT; out_trans_cancel: xfs_trans_cancel(tp, cancel_flags); out_release_inode: /* * Wait until after the current transaction is aborted to * release the inode. This prevents recursive transactions * and deadlocks from xfs_inactive. */ if (ip) IRELE(ip); xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); xfs_qm_dqrele(pdqp); return error; } int xfs_link( xfs_inode_t *tdp, Loading Loading @@ -1397,6 +1502,12 @@ xfs_link( xfs_bmap_init(&free_list, &first_block); if (sip->i_d.di_nlink == 0) { error = xfs_iunlink_remove(tp, sip); if (error) goto abort_return; } error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino, &first_block, &free_list, resblks); if (error) Loading fs/xfs/xfs_inode.h +12 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include "xfs_inode_buf.h" #include "xfs_inode_fork.h" #include "xfs_dinode.h" /* * Kernel only inode definitions Loading Loading @@ -192,6 +193,15 @@ xfs_set_projid(struct xfs_inode *ip, ip->i_d.di_projid_lo = (__uint16_t) (projid & 0xffff); } static inline prid_t xfs_get_initial_prid(struct xfs_inode *dp) { if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) return xfs_get_projid(dp); return XFS_PROJID_DEFAULT; } /* * In-core inode flags. */ Loading Loading @@ -323,6 +333,8 @@ int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name, struct xfs_inode **ipp, struct xfs_name *ci_name); int xfs_create(struct xfs_inode *dp, struct xfs_name *name, umode_t mode, xfs_dev_t rdev, struct xfs_inode **ipp); int xfs_create_tmpfile(struct xfs_inode *dp, struct dentry *dentry, umode_t mode); int xfs_remove(struct xfs_inode *dp, struct xfs_name *name, struct xfs_inode *ip); int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip, Loading fs/xfs/xfs_iops.c +16 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ #include "xfs_da_btree.h" #include "xfs_dir2_priv.h" #include "xfs_dinode.h" #include "xfs_trans_space.h" #include <linux/capability.h> #include <linux/xattr.h> Loading Loading @@ -1046,6 +1047,19 @@ xfs_vn_fiemap( return 0; } STATIC int xfs_vn_tmpfile( struct inode *dir, struct dentry *dentry, umode_t mode) { int error; error = xfs_create_tmpfile(XFS_I(dir), dentry, mode); return -error; } static const struct inode_operations xfs_inode_operations = { .get_acl = xfs_get_acl, .set_acl = xfs_set_acl, Loading Loading @@ -1084,6 +1098,7 @@ static const struct inode_operations xfs_dir_inode_operations = { .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, .update_time = xfs_vn_update_time, .tmpfile = xfs_vn_tmpfile, }; static const struct inode_operations xfs_dir_ci_inode_operations = { Loading Loading @@ -1111,6 +1126,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = { .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, .update_time = xfs_vn_update_time, .tmpfile = xfs_vn_tmpfile, }; static const struct inode_operations xfs_symlink_inode_operations = { Loading fs/xfs/xfs_shared.h +3 −1 Original line number Diff line number Diff line Loading @@ -104,7 +104,8 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops; #define XFS_TRANS_SB_COUNT 41 #define XFS_TRANS_CHECKPOINT 42 #define XFS_TRANS_ICREATE 43 #define XFS_TRANS_TYPE_MAX 43 #define XFS_TRANS_CREATE_TMPFILE 44 #define XFS_TRANS_TYPE_MAX 44 /* new transaction types need to be reflected in xfs_logprint(8) */ #define XFS_TRANS_TYPES \ Loading @@ -112,6 +113,7 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops; { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \ { XFS_TRANS_INACTIVE, "INACTIVE" }, \ { XFS_TRANS_CREATE, "CREATE" }, \ { XFS_TRANS_CREATE_TMPFILE, "CREATE_TMPFILE" }, \ { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \ { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \ { XFS_TRANS_REMOVE, "REMOVE" }, \ Loading fs/xfs/xfs_symlink.c +1 −4 Original line number Diff line number Diff line Loading @@ -212,10 +212,7 @@ xfs_symlink( return XFS_ERROR(ENAMETOOLONG); udqp = gdqp = NULL; if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) prid = xfs_get_projid(dp); else prid = XFS_PROJID_DEFAULT; prid = xfs_get_initial_prid(dp); /* * Make sure that we have allocated dquot(s) on disk. Loading Loading
fs/xfs/xfs_inode.c +117 −6 Original line number Diff line number Diff line Loading @@ -42,7 +42,6 @@ #include "xfs_bmap_util.h" #include "xfs_error.h" #include "xfs_quota.h" #include "xfs_dinode.h" #include "xfs_filestream.h" #include "xfs_cksum.h" #include "xfs_trace.h" Loading @@ -62,6 +61,8 @@ kmem_zone_t *xfs_inode_zone; STATIC int xfs_iflush_int(xfs_inode_t *, xfs_buf_t *); STATIC int xfs_iunlink_remove(xfs_trans_t *, xfs_inode_t *); /* * helper function to extract extent size hint from inode */ Loading Loading @@ -1115,7 +1116,7 @@ xfs_bumplink( { xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); ASSERT(ip->i_d.di_nlink > 0); ASSERT(ip->i_d.di_nlink > 0 || (VFS_I(ip)->i_state & I_LINKABLE)); ip->i_d.di_nlink++; inc_nlink(VFS_I(ip)); if ((ip->i_d.di_version == 1) && Loading Loading @@ -1165,10 +1166,7 @@ xfs_create( if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) prid = xfs_get_projid(dp); else prid = XFS_PROJID_DEFAULT; prid = xfs_get_initial_prid(dp); /* * Make sure that we have allocated dquot(s) on disk. Loading Loading @@ -1332,6 +1330,113 @@ xfs_create( return error; } int xfs_create_tmpfile( struct xfs_inode *dp, struct dentry *dentry, umode_t mode) { struct xfs_mount *mp = dp->i_mount; struct xfs_inode *ip = NULL; struct xfs_trans *tp = NULL; int error; uint cancel_flags = XFS_TRANS_RELEASE_LOG_RES; prid_t prid; struct xfs_dquot *udqp = NULL; struct xfs_dquot *gdqp = NULL; struct xfs_dquot *pdqp = NULL; struct xfs_trans_res *tres; uint resblks; if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); prid = xfs_get_initial_prid(dp); /* * Make sure that we have allocated dquot(s) on disk. */ error = xfs_qm_vop_dqalloc(dp, xfs_kuid_to_uid(current_fsuid()), xfs_kgid_to_gid(current_fsgid()), prid, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp); if (error) return error; resblks = XFS_IALLOC_SPACE_RES(mp); tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE_TMPFILE); tres = &M_RES(mp)->tr_create_tmpfile; error = xfs_trans_reserve(tp, tres, resblks, 0); if (error == ENOSPC) { /* No space at all so try a "no-allocation" reservation */ resblks = 0; error = xfs_trans_reserve(tp, tres, 0, 0); } if (error) { cancel_flags = 0; goto out_trans_cancel; } error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, pdqp, resblks, 1, 0); if (error) goto out_trans_cancel; error = xfs_dir_ialloc(&tp, dp, mode, 1, 0, prid, resblks > 0, &ip, NULL); if (error) { if (error == ENOSPC) goto out_trans_cancel; goto out_trans_abort; } if (mp->m_flags & XFS_MOUNT_WSYNC) xfs_trans_set_sync(tp); /* * Attach the dquot(s) to the inodes and modify them incore. * These ids of the inode couldn't have changed since the new * inode has been locked ever since it was created. */ xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); ip->i_d.di_nlink--; d_tmpfile(dentry, VFS_I(ip)); error = xfs_iunlink(tp, ip); if (error) goto out_trans_abort; error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); if (error) goto out_release_inode; xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); xfs_qm_dqrele(pdqp); return 0; out_trans_abort: cancel_flags |= XFS_TRANS_ABORT; out_trans_cancel: xfs_trans_cancel(tp, cancel_flags); out_release_inode: /* * Wait until after the current transaction is aborted to * release the inode. This prevents recursive transactions * and deadlocks from xfs_inactive. */ if (ip) IRELE(ip); xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); xfs_qm_dqrele(pdqp); return error; } int xfs_link( xfs_inode_t *tdp, Loading Loading @@ -1397,6 +1502,12 @@ xfs_link( xfs_bmap_init(&free_list, &first_block); if (sip->i_d.di_nlink == 0) { error = xfs_iunlink_remove(tp, sip); if (error) goto abort_return; } error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino, &first_block, &free_list, resblks); if (error) Loading
fs/xfs/xfs_inode.h +12 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include "xfs_inode_buf.h" #include "xfs_inode_fork.h" #include "xfs_dinode.h" /* * Kernel only inode definitions Loading Loading @@ -192,6 +193,15 @@ xfs_set_projid(struct xfs_inode *ip, ip->i_d.di_projid_lo = (__uint16_t) (projid & 0xffff); } static inline prid_t xfs_get_initial_prid(struct xfs_inode *dp) { if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) return xfs_get_projid(dp); return XFS_PROJID_DEFAULT; } /* * In-core inode flags. */ Loading Loading @@ -323,6 +333,8 @@ int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name, struct xfs_inode **ipp, struct xfs_name *ci_name); int xfs_create(struct xfs_inode *dp, struct xfs_name *name, umode_t mode, xfs_dev_t rdev, struct xfs_inode **ipp); int xfs_create_tmpfile(struct xfs_inode *dp, struct dentry *dentry, umode_t mode); int xfs_remove(struct xfs_inode *dp, struct xfs_name *name, struct xfs_inode *ip); int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip, Loading
fs/xfs/xfs_iops.c +16 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ #include "xfs_da_btree.h" #include "xfs_dir2_priv.h" #include "xfs_dinode.h" #include "xfs_trans_space.h" #include <linux/capability.h> #include <linux/xattr.h> Loading Loading @@ -1046,6 +1047,19 @@ xfs_vn_fiemap( return 0; } STATIC int xfs_vn_tmpfile( struct inode *dir, struct dentry *dentry, umode_t mode) { int error; error = xfs_create_tmpfile(XFS_I(dir), dentry, mode); return -error; } static const struct inode_operations xfs_inode_operations = { .get_acl = xfs_get_acl, .set_acl = xfs_set_acl, Loading Loading @@ -1084,6 +1098,7 @@ static const struct inode_operations xfs_dir_inode_operations = { .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, .update_time = xfs_vn_update_time, .tmpfile = xfs_vn_tmpfile, }; static const struct inode_operations xfs_dir_ci_inode_operations = { Loading Loading @@ -1111,6 +1126,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = { .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, .update_time = xfs_vn_update_time, .tmpfile = xfs_vn_tmpfile, }; static const struct inode_operations xfs_symlink_inode_operations = { Loading
fs/xfs/xfs_shared.h +3 −1 Original line number Diff line number Diff line Loading @@ -104,7 +104,8 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops; #define XFS_TRANS_SB_COUNT 41 #define XFS_TRANS_CHECKPOINT 42 #define XFS_TRANS_ICREATE 43 #define XFS_TRANS_TYPE_MAX 43 #define XFS_TRANS_CREATE_TMPFILE 44 #define XFS_TRANS_TYPE_MAX 44 /* new transaction types need to be reflected in xfs_logprint(8) */ #define XFS_TRANS_TYPES \ Loading @@ -112,6 +113,7 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops; { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \ { XFS_TRANS_INACTIVE, "INACTIVE" }, \ { XFS_TRANS_CREATE, "CREATE" }, \ { XFS_TRANS_CREATE_TMPFILE, "CREATE_TMPFILE" }, \ { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \ { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \ { XFS_TRANS_REMOVE, "REMOVE" }, \ Loading
fs/xfs/xfs_symlink.c +1 −4 Original line number Diff line number Diff line Loading @@ -212,10 +212,7 @@ xfs_symlink( return XFS_ERROR(ENAMETOOLONG); udqp = gdqp = NULL; if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) prid = xfs_get_projid(dp); else prid = XFS_PROJID_DEFAULT; prid = xfs_get_initial_prid(dp); /* * Make sure that we have allocated dquot(s) on disk. Loading