]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
xfs: split out dqget for inodes from regular dqget
authorDarrick J. Wong <darrick.wong@oracle.com>
Fri, 4 May 2018 22:30:22 +0000 (15:30 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Thu, 10 May 2018 15:56:48 +0000 (08:56 -0700)
There are two uses of dqget here -- one is to return the dquot for a
given type and id, and the other is to return the dquot for a given type
and inode.  Those are two separate things, so split them into two
smaller functions.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_dquot.c
fs/xfs/xfs_dquot.h
fs/xfs/xfs_iomap.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_qm_bhv.c
fs/xfs/xfs_qm_syscalls.c
fs/xfs/xfs_quota.h
fs/xfs/xfs_reflink.c

index 1ee05e5ab1d93ea7497f208c3930c0ea70b7f94e..376923fd21745faac0c77e4255a15a63260ebd19 100644 (file)
@@ -790,24 +790,19 @@ xfs_qm_dqget_checks(
 }
 
 /*
- * Given the file system, inode OR id, and type (UDQUOT/GDQUOT), return a
- * a locked dquot, doing an allocation (if requested) as needed.
- * When both an inode and an id are given, the inode's id takes precedence.
- * That is, if the id changes while we don't hold the ilock inside this
- * function, the new dquot is returned, not necessarily the one requested
- * in the id argument.
+ * Given the file system, id, and type (UDQUOT/GDQUOT), return a a locked
+ * dquot, doing an allocation (if requested) as needed.
  */
 int
 xfs_qm_dqget(
-       xfs_mount_t     *mp,
-       xfs_inode_t     *ip,      /* locked inode (optional) */
-       xfs_dqid_t      id,       /* uid/projid/gid depending on type */
-       uint            type,     /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */
-       uint            flags,    /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */
-       xfs_dquot_t     **O_dqpp) /* OUT : locked incore dquot */
+       struct xfs_mount        *mp,
+       xfs_dqid_t              id,
+       uint                    type,
+       uint                    flags,    /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */
+       struct xfs_dquot        **O_dqpp)
 {
        struct xfs_quotainfo    *qi = mp->m_quotainfo;
-       struct radix_tree_root *tree = xfs_dquot_tree(qi, type);
+       struct radix_tree_root  *tree = xfs_dquot_tree(qi, type);
        struct xfs_dquot        *dqp;
        int                     error;
 
@@ -815,10 +810,82 @@ xfs_qm_dqget(
        if (error)
                return error;
 
-       if (ip) {
-               ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-               ASSERT(xfs_inode_dquot(ip, type) == NULL);
+restart:
+       dqp = xfs_qm_dqget_cache_lookup(mp, qi, tree, id);
+       if (dqp) {
+               *O_dqpp = dqp;
+               return 0;
+       }
+
+       error = xfs_qm_dqread(mp, id, type, flags, &dqp);
+       if (error)
+               return error;
+
+       error = xfs_qm_dqget_cache_insert(mp, qi, tree, id, dqp);
+       if (error) {
+               /*
+                * Duplicate found. Just throw away the new dquot and start
+                * over.
+                */
+               xfs_qm_dqdestroy(dqp);
+               XFS_STATS_INC(mp, xs_qm_dquot_dups);
+               goto restart;
+       }
+
+       trace_xfs_dqget_miss(dqp);
+       *O_dqpp = dqp;
+       return 0;
+}
+
+/* Return the quota id for a given inode and type. */
+xfs_dqid_t
+xfs_qm_id_for_quotatype(
+       struct xfs_inode        *ip,
+       uint                    type)
+{
+       switch (type) {
+       case XFS_DQ_USER:
+               return ip->i_d.di_uid;
+       case XFS_DQ_GROUP:
+               return ip->i_d.di_gid;
+       case XFS_DQ_PROJ:
+               return xfs_get_projid(ip);
        }
+       ASSERT(0);
+       return 0;
+}
+
+/*
+ * Return the dquot for a given inode and type.  If @can_alloc is true, then
+ * allocate blocks if needed.  The inode's ILOCK must be held and it must not
+ * have already had an inode attached.
+ */
+int
+xfs_qm_dqget_inode(
+       struct xfs_inode        *ip,
+       uint                    type,
+       bool                    can_alloc,
+       struct xfs_dquot        **O_dqpp)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_quotainfo    *qi = mp->m_quotainfo;
+       struct radix_tree_root  *tree = xfs_dquot_tree(qi, type);
+       struct xfs_dquot        *dqp;
+       xfs_dqid_t              id;
+       uint                    flags = 0;
+       int                     error;
+
+       error = xfs_qm_dqget_checks(mp, type);
+       if (error)
+               return error;
+
+       if (can_alloc)
+               flags |= XFS_QMOPT_DQALLOC;
+
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+       ASSERT(xfs_inode_dquot(ip, type) == NULL);
+
+       id = xfs_qm_id_for_quotatype(ip, type);
 
 restart:
        dqp = xfs_qm_dqget_cache_lookup(mp, qi, tree, id);
@@ -834,37 +901,30 @@ xfs_qm_dqget(
         * lock here means dealing with a chown that can happen before
         * we re-acquire the lock.
         */
-       if (ip)
-               xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
        error = xfs_qm_dqread(mp, id, type, flags, &dqp);
-
-       if (ip)
-               xfs_ilock(ip, XFS_ILOCK_EXCL);
-
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
        if (error)
                return error;
 
-       if (ip) {
-               /*
-                * A dquot could be attached to this inode by now, since
-                * we had dropped the ilock.
-                */
-               if (xfs_this_quota_on(mp, type)) {
-                       struct xfs_dquot        *dqp1;
-
-                       dqp1 = xfs_inode_dquot(ip, type);
-                       if (dqp1) {
-                               xfs_qm_dqdestroy(dqp);
-                               dqp = dqp1;
-                               xfs_dqlock(dqp);
-                               goto dqret;
-                       }
-               } else {
-                       /* inode stays locked on return */
+       /*
+        * A dquot could be attached to this inode by now, since we had
+        * dropped the ilock.
+        */
+       if (xfs_this_quota_on(mp, type)) {
+               struct xfs_dquot        *dqp1;
+
+               dqp1 = xfs_inode_dquot(ip, type);
+               if (dqp1) {
                        xfs_qm_dqdestroy(dqp);
-                       return -ESRCH;
+                       dqp = dqp1;
+                       xfs_dqlock(dqp);
+                       goto dqret;
                }
+       } else {
+               /* inode stays locked on return */
+               xfs_qm_dqdestroy(dqp);
+               return -ESRCH;
        }
 
        error = xfs_qm_dqget_cache_insert(mp, qi, tree, id, dqp);
@@ -878,8 +938,8 @@ xfs_qm_dqget(
                goto restart;
        }
 
- dqret:
-       ASSERT((ip == NULL) || xfs_isilocked(ip, XFS_ILOCK_EXCL));
+dqret:
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        trace_xfs_dqget_miss(dqp);
        *O_dqpp = dqp;
        return 0;
@@ -901,7 +961,7 @@ xfs_qm_dqget_next(
 
        *dqpp = NULL;
        for (; !error; error = xfs_dq_get_next_id(mp, type, &id)) {
-               error = xfs_qm_dqget(mp, NULL, id, type, 0, &dqp);
+               error = xfs_qm_dqget(mp, id, type, 0, &dqp);
                if (error == -ENOENT)
                        continue;
                else if (error != 0)
index 303e71dfcf707c77b20c7c7b1801ac7aea9d378a..8a5b30e952b0454c28f780a421e82bb24abad3fd 100644 (file)
@@ -169,8 +169,14 @@ extern void                xfs_qm_adjust_dqtimers(xfs_mount_t *,
                                        xfs_disk_dquot_t *);
 extern void            xfs_qm_adjust_dqlimits(struct xfs_mount *,
                                               struct xfs_dquot *);
-extern int             xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
-                                       xfs_dqid_t, uint, uint, xfs_dquot_t **);
+extern xfs_dqid_t      xfs_qm_id_for_quotatype(struct xfs_inode *ip,
+                                       uint type);
+extern int             xfs_qm_dqget(struct xfs_mount *mp, xfs_dqid_t id,
+                                       uint type, uint flags,
+                                       struct xfs_dquot **dqpp);
+extern int             xfs_qm_dqget_inode(struct xfs_inode *ip, uint type,
+                                       bool can_alloc,
+                                       struct xfs_dquot **dqpp);
 extern int             xfs_qm_dqget_next(struct xfs_mount *mp, xfs_dqid_t id,
                                        uint type, struct xfs_dquot **dqpp);
 extern void            xfs_qm_dqput(xfs_dquot_t *);
index 0880685a11434ec8802c510754038058ec9aeaf1..c6ce6f9335b65e66caf1ee303390253d36a5a8f1 100644 (file)
@@ -576,7 +576,7 @@ xfs_file_iomap_begin_delay(
                goto done;
        }
 
-       error = xfs_qm_dqattach_locked(ip, 0);
+       error = xfs_qm_dqattach_locked(ip, false);
        if (error)
                goto out_unlock;
 
index 3893f541f88df72927e4f2445524e7ec8a9ee150..6122097da0b69adba6c2872429f8791bb07d2394 100644 (file)
@@ -262,7 +262,7 @@ xfs_qm_dqattach_one(
        xfs_inode_t     *ip,
        xfs_dqid_t      id,
        uint            type,
-       uint            doalloc,
+       bool            doalloc,
        xfs_dquot_t     **IO_idqpp)
 {
        xfs_dquot_t     *dqp;
@@ -288,7 +288,7 @@ xfs_qm_dqattach_one(
         * exist on disk and we didn't ask it to allocate; ESRCH if quotas got
         * turned off suddenly.
         */
-       error = xfs_qm_dqget(ip->i_mount, ip, id, type, doalloc, &dqp);
+       error = xfs_qm_dqget_inode(ip, type, doalloc, &dqp);
        if (error)
                return error;
 
@@ -330,7 +330,7 @@ xfs_qm_need_dqattach(
 int
 xfs_qm_dqattach_locked(
        xfs_inode_t     *ip,
-       uint            flags)
+       bool            doalloc)
 {
        xfs_mount_t     *mp = ip->i_mount;
        int             error = 0;
@@ -342,8 +342,7 @@ xfs_qm_dqattach_locked(
 
        if (XFS_IS_UQUOTA_ON(mp) && !ip->i_udquot) {
                error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER,
-                                               flags & XFS_QMOPT_DQALLOC,
-                                               &ip->i_udquot);
+                               doalloc, &ip->i_udquot);
                if (error)
                        goto done;
                ASSERT(ip->i_udquot);
@@ -351,8 +350,7 @@ xfs_qm_dqattach_locked(
 
        if (XFS_IS_GQUOTA_ON(mp) && !ip->i_gdquot) {
                error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
-                                               flags & XFS_QMOPT_DQALLOC,
-                                               &ip->i_gdquot);
+                               doalloc, &ip->i_gdquot);
                if (error)
                        goto done;
                ASSERT(ip->i_gdquot);
@@ -360,8 +358,7 @@ xfs_qm_dqattach_locked(
 
        if (XFS_IS_PQUOTA_ON(mp) && !ip->i_pdquot) {
                error = xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
-                                               flags & XFS_QMOPT_DQALLOC,
-                                               &ip->i_pdquot);
+                               doalloc, &ip->i_pdquot);
                if (error)
                        goto done;
                ASSERT(ip->i_pdquot);
@@ -386,7 +383,7 @@ xfs_qm_dqattach(
                return 0;
 
        xfs_ilock(ip, XFS_ILOCK_EXCL);
-       error = xfs_qm_dqattach_locked(ip, 0);
+       error = xfs_qm_dqattach_locked(ip, false);
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 
        return error;
@@ -1068,7 +1065,7 @@ xfs_qm_quotacheck_dqadjust(
        struct xfs_dquot        *dqp;
        int                     error;
 
-       error = xfs_qm_dqget(mp, ip, id, type, XFS_QMOPT_DQALLOC, &dqp);
+       error = xfs_qm_dqget_inode(ip, type, true, &dqp);
        if (error) {
                /*
                 * Shouldn't be able to turn off quotas here.
@@ -1667,7 +1664,7 @@ xfs_qm_vop_dqalloc(
         * if necessary. The dquot(s) will not be locked.
         */
        if (XFS_NOT_DQATTACHED(mp, ip)) {
-               error = xfs_qm_dqattach_locked(ip, XFS_QMOPT_DQALLOC);
+               error = xfs_qm_dqattach_locked(ip, true);
                if (error) {
                        xfs_iunlock(ip, lockflags);
                        return error;
@@ -1686,10 +1683,8 @@ xfs_qm_vop_dqalloc(
                         * holding ilock.
                         */
                        xfs_iunlock(ip, lockflags);
-                       error = xfs_qm_dqget(mp, NULL, uid,
-                                                XFS_DQ_USER,
-                                                XFS_QMOPT_DQALLOC,
-                                                &uq);
+                       error = xfs_qm_dqget(mp, uid, XFS_DQ_USER,
+                                       XFS_QMOPT_DQALLOC, &uq);
                        if (error) {
                                ASSERT(error != -ENOENT);
                                return error;
@@ -1712,10 +1707,8 @@ xfs_qm_vop_dqalloc(
        if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
                if (ip->i_d.di_gid != gid) {
                        xfs_iunlock(ip, lockflags);
-                       error = xfs_qm_dqget(mp, NULL, gid,
-                                                XFS_DQ_GROUP,
-                                                XFS_QMOPT_DQALLOC,
-                                                &gq);
+                       error = xfs_qm_dqget(mp, gid, XFS_DQ_GROUP,
+                                       XFS_QMOPT_DQALLOC, &gq);
                        if (error) {
                                ASSERT(error != -ENOENT);
                                goto error_rele;
@@ -1731,10 +1724,8 @@ xfs_qm_vop_dqalloc(
        if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
                if (xfs_get_projid(ip) != prid) {
                        xfs_iunlock(ip, lockflags);
-                       error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
-                                                XFS_DQ_PROJ,
-                                                XFS_QMOPT_DQALLOC,
-                                                &pq);
+                       error = xfs_qm_dqget(mp, (xfs_dqid_t)prid, XFS_DQ_PROJ,
+                                       XFS_QMOPT_DQALLOC, &pq);
                        if (error) {
                                ASSERT(error != -ENOENT);
                                goto error_rele;
index 2be6d2735ca9f5d51b610e2f0b7563b64d15d263..531e8224dcb6694c994cd1093eca627175a97ee9 100644 (file)
@@ -72,7 +72,7 @@ xfs_qm_statvfs(
        xfs_mount_t             *mp = ip->i_mount;
        xfs_dquot_t             *dqp;
 
-       if (!xfs_qm_dqget(mp, NULL, xfs_get_projid(ip), XFS_DQ_PROJ, 0, &dqp)) {
+       if (!xfs_qm_dqget(mp, xfs_get_projid(ip), XFS_DQ_PROJ, 0, &dqp)) {
                xfs_fill_statvfs_from_dquot(statp, dqp);
                xfs_qm_dqput(dqp);
        }
index 0234cfc4d4455c9e81e52aa53d7c96cf98fdb448..b9243f5546970e38cae76c3ba52e2dba70f3859a 100644 (file)
@@ -425,7 +425,7 @@ xfs_qm_scall_setqlim(
         * a reference to the dquot, so it's safe to do this unlock/lock without
         * it being reclaimed in the mean time.
         */
-       error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp);
+       error = xfs_qm_dqget(mp, id, type, XFS_QMOPT_DQALLOC, &dqp);
        if (error) {
                ASSERT(error != -ENOENT);
                goto out_unlock;
@@ -700,7 +700,7 @@ xfs_qm_scall_getquota(
         * we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't
         * exist, we'll get ENOENT back.
         */
-       error = xfs_qm_dqget(mp, NULL, id, type, 0, &dqp);
+       error = xfs_qm_dqget(mp, id, type, 0, &dqp);
        if (error)
                return error;
 
index a4d392240cf4b60e0a4da7bed89302fb85a06aa1..1c79ebbe52364fe21b41889d4389fa970e54fb9f 100644 (file)
@@ -91,7 +91,7 @@ extern int xfs_qm_vop_chown_reserve(struct xfs_trans *, struct xfs_inode *,
                struct xfs_dquot *, struct xfs_dquot *,
                struct xfs_dquot *, uint);
 extern int xfs_qm_dqattach(struct xfs_inode *);
-extern int xfs_qm_dqattach_locked(struct xfs_inode *, uint);
+extern int xfs_qm_dqattach_locked(struct xfs_inode *ip, bool doalloc);
 extern void xfs_qm_dqdetach(struct xfs_inode *);
 extern void xfs_qm_dqrele(struct xfs_dquot *);
 extern void xfs_qm_statvfs(struct xfs_inode *, struct kstatfs *);
index 7e2b8078ade29b70136d198baa07c9d58bd7b7c9..713e857d9ffa4eac6c6a649164b4c7e307928c1e 100644 (file)
@@ -305,7 +305,7 @@ xfs_reflink_reserve_cow(
         * Fork all the shared blocks from our write offset until the end of
         * the extent.
         */
-       error = xfs_qm_dqattach_locked(ip, 0);
+       error = xfs_qm_dqattach_locked(ip, false);
        if (error)
                return error;
 
@@ -431,7 +431,7 @@ xfs_reflink_allocate_cow(
                if (error)
                        return error;
 
-               error = xfs_qm_dqattach_locked(ip, 0);
+               error = xfs_qm_dqattach_locked(ip, false);
                if (error)
                        goto out;
                goto retry;