]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: move xfs_ioc_getfsmap out of xfs_ioctl.c
authorDarrick J. Wong <djwong@kernel.org>
Fri, 30 Aug 2024 22:37:16 +0000 (15:37 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Sun, 1 Sep 2024 15:58:19 +0000 (08:58 -0700)
Move this function out of xfs_ioctl.c to reduce the clutter in there,
and make the entire getfsmap implementation self-contained in a single
file.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_fsmap.c
fs/xfs/xfs_fsmap.h
fs/xfs/xfs_ioctl.c

index 615253406fde1a7839d1f5c64d8bcca7e3197658..ae18ab86e608b5d9c23414d0b90cb369bf6e863f 100644 (file)
@@ -44,7 +44,7 @@ xfs_fsmap_from_internal(
 }
 
 /* Convert an fsmap to an xfs_fsmap. */
-void
+static void
 xfs_fsmap_to_internal(
        struct xfs_fsmap        *dest,
        struct fsmap            *src)
@@ -889,7 +889,7 @@ xfs_getfsmap_check_keys(
  * xfs_getfsmap_info.low/high  -- per-AG low/high keys computed from
  *                                dkeys; used to query the metadata.
  */
-int
+STATIC int
 xfs_getfsmap(
        struct xfs_mount                *mp,
        struct xfs_fsmap_head           *head,
@@ -1019,3 +1019,133 @@ xfs_getfsmap(
        head->fmh_oflags = FMH_OF_DEV_T;
        return error;
 }
+
+int
+xfs_ioc_getfsmap(
+       struct xfs_inode        *ip,
+       struct fsmap_head       __user *arg)
+{
+       struct xfs_fsmap_head   xhead = {0};
+       struct fsmap_head       head;
+       struct fsmap            *recs;
+       unsigned int            count;
+       __u32                   last_flags = 0;
+       bool                    done = false;
+       int                     error;
+
+       if (copy_from_user(&head, arg, sizeof(struct fsmap_head)))
+               return -EFAULT;
+       if (memchr_inv(head.fmh_reserved, 0, sizeof(head.fmh_reserved)) ||
+           memchr_inv(head.fmh_keys[0].fmr_reserved, 0,
+                      sizeof(head.fmh_keys[0].fmr_reserved)) ||
+           memchr_inv(head.fmh_keys[1].fmr_reserved, 0,
+                      sizeof(head.fmh_keys[1].fmr_reserved)))
+               return -EINVAL;
+
+       /*
+        * Use an internal memory buffer so that we don't have to copy fsmap
+        * data to userspace while holding locks.  Start by trying to allocate
+        * up to 128k for the buffer, but fall back to a single page if needed.
+        */
+       count = min_t(unsigned int, head.fmh_count,
+                       131072 / sizeof(struct fsmap));
+       recs = kvcalloc(count, sizeof(struct fsmap), GFP_KERNEL);
+       if (!recs) {
+               count = min_t(unsigned int, head.fmh_count,
+                               PAGE_SIZE / sizeof(struct fsmap));
+               recs = kvcalloc(count, sizeof(struct fsmap), GFP_KERNEL);
+               if (!recs)
+                       return -ENOMEM;
+       }
+
+       xhead.fmh_iflags = head.fmh_iflags;
+       xfs_fsmap_to_internal(&xhead.fmh_keys[0], &head.fmh_keys[0]);
+       xfs_fsmap_to_internal(&xhead.fmh_keys[1], &head.fmh_keys[1]);
+
+       trace_xfs_getfsmap_low_key(ip->i_mount, &xhead.fmh_keys[0]);
+       trace_xfs_getfsmap_high_key(ip->i_mount, &xhead.fmh_keys[1]);
+
+       head.fmh_entries = 0;
+       do {
+               struct fsmap __user     *user_recs;
+               struct fsmap            *last_rec;
+
+               user_recs = &arg->fmh_recs[head.fmh_entries];
+               xhead.fmh_entries = 0;
+               xhead.fmh_count = min_t(unsigned int, count,
+                                       head.fmh_count - head.fmh_entries);
+
+               /* Run query, record how many entries we got. */
+               error = xfs_getfsmap(ip->i_mount, &xhead, recs);
+               switch (error) {
+               case 0:
+                       /*
+                        * There are no more records in the result set.  Copy
+                        * whatever we got to userspace and break out.
+                        */
+                       done = true;
+                       break;
+               case -ECANCELED:
+                       /*
+                        * The internal memory buffer is full.  Copy whatever
+                        * records we got to userspace and go again if we have
+                        * not yet filled the userspace buffer.
+                        */
+                       error = 0;
+                       break;
+               default:
+                       goto out_free;
+               }
+               head.fmh_entries += xhead.fmh_entries;
+               head.fmh_oflags = xhead.fmh_oflags;
+
+               /*
+                * If the caller wanted a record count or there aren't any
+                * new records to return, we're done.
+                */
+               if (head.fmh_count == 0 || xhead.fmh_entries == 0)
+                       break;
+
+               /* Copy all the records we got out to userspace. */
+               if (copy_to_user(user_recs, recs,
+                                xhead.fmh_entries * sizeof(struct fsmap))) {
+                       error = -EFAULT;
+                       goto out_free;
+               }
+
+               /* Remember the last record flags we copied to userspace. */
+               last_rec = &recs[xhead.fmh_entries - 1];
+               last_flags = last_rec->fmr_flags;
+
+               /* Set up the low key for the next iteration. */
+               xfs_fsmap_to_internal(&xhead.fmh_keys[0], last_rec);
+               trace_xfs_getfsmap_low_key(ip->i_mount, &xhead.fmh_keys[0]);
+       } while (!done && head.fmh_entries < head.fmh_count);
+
+       /*
+        * If there are no more records in the query result set and we're not
+        * in counting mode, mark the last record returned with the LAST flag.
+        */
+       if (done && head.fmh_count > 0 && head.fmh_entries > 0) {
+               struct fsmap __user     *user_rec;
+
+               last_flags |= FMR_OF_LAST;
+               user_rec = &arg->fmh_recs[head.fmh_entries - 1];
+
+               if (copy_to_user(&user_rec->fmr_flags, &last_flags,
+                                       sizeof(last_flags))) {
+                       error = -EFAULT;
+                       goto out_free;
+               }
+       }
+
+       /* copy back header */
+       if (copy_to_user(arg, &head, sizeof(struct fsmap_head))) {
+               error = -EFAULT;
+               goto out_free;
+       }
+
+out_free:
+       kvfree(recs);
+       return error;
+}
index a0775788e7b13d82414c87be82f31a2e4046a20f..a0bcc38486a569bef539b92daf6758d73163a579 100644 (file)
@@ -7,6 +7,7 @@
 #define __XFS_FSMAP_H__
 
 struct fsmap;
+struct fsmap_head;
 
 /* internal fsmap representation */
 struct xfs_fsmap {
@@ -27,9 +28,6 @@ struct xfs_fsmap_head {
        struct xfs_fsmap fmh_keys[2];   /* low and high keys */
 };
 
-void xfs_fsmap_to_internal(struct xfs_fsmap *dest, struct fsmap *src);
-
-int xfs_getfsmap(struct xfs_mount *mp, struct xfs_fsmap_head *head,
-               struct fsmap *out_recs);
+int xfs_ioc_getfsmap(struct xfs_inode *ip, struct fsmap_head __user *arg);
 
 #endif /* __XFS_FSMAP_H__ */
index 90b3ee21e7fe6a448792ccfef6a76ab4a265f571..7226d27e8afc3f29e090c6b308c07782802e9b39 100644 (file)
@@ -876,136 +876,6 @@ out_free_buf:
        return error;
 }
 
-STATIC int
-xfs_ioc_getfsmap(
-       struct xfs_inode        *ip,
-       struct fsmap_head       __user *arg)
-{
-       struct xfs_fsmap_head   xhead = {0};
-       struct fsmap_head       head;
-       struct fsmap            *recs;
-       unsigned int            count;
-       __u32                   last_flags = 0;
-       bool                    done = false;
-       int                     error;
-
-       if (copy_from_user(&head, arg, sizeof(struct fsmap_head)))
-               return -EFAULT;
-       if (memchr_inv(head.fmh_reserved, 0, sizeof(head.fmh_reserved)) ||
-           memchr_inv(head.fmh_keys[0].fmr_reserved, 0,
-                      sizeof(head.fmh_keys[0].fmr_reserved)) ||
-           memchr_inv(head.fmh_keys[1].fmr_reserved, 0,
-                      sizeof(head.fmh_keys[1].fmr_reserved)))
-               return -EINVAL;
-
-       /*
-        * Use an internal memory buffer so that we don't have to copy fsmap
-        * data to userspace while holding locks.  Start by trying to allocate
-        * up to 128k for the buffer, but fall back to a single page if needed.
-        */
-       count = min_t(unsigned int, head.fmh_count,
-                       131072 / sizeof(struct fsmap));
-       recs = kvcalloc(count, sizeof(struct fsmap), GFP_KERNEL);
-       if (!recs) {
-               count = min_t(unsigned int, head.fmh_count,
-                               PAGE_SIZE / sizeof(struct fsmap));
-               recs = kvcalloc(count, sizeof(struct fsmap), GFP_KERNEL);
-               if (!recs)
-                       return -ENOMEM;
-       }
-
-       xhead.fmh_iflags = head.fmh_iflags;
-       xfs_fsmap_to_internal(&xhead.fmh_keys[0], &head.fmh_keys[0]);
-       xfs_fsmap_to_internal(&xhead.fmh_keys[1], &head.fmh_keys[1]);
-
-       trace_xfs_getfsmap_low_key(ip->i_mount, &xhead.fmh_keys[0]);
-       trace_xfs_getfsmap_high_key(ip->i_mount, &xhead.fmh_keys[1]);
-
-       head.fmh_entries = 0;
-       do {
-               struct fsmap __user     *user_recs;
-               struct fsmap            *last_rec;
-
-               user_recs = &arg->fmh_recs[head.fmh_entries];
-               xhead.fmh_entries = 0;
-               xhead.fmh_count = min_t(unsigned int, count,
-                                       head.fmh_count - head.fmh_entries);
-
-               /* Run query, record how many entries we got. */
-               error = xfs_getfsmap(ip->i_mount, &xhead, recs);
-               switch (error) {
-               case 0:
-                       /*
-                        * There are no more records in the result set.  Copy
-                        * whatever we got to userspace and break out.
-                        */
-                       done = true;
-                       break;
-               case -ECANCELED:
-                       /*
-                        * The internal memory buffer is full.  Copy whatever
-                        * records we got to userspace and go again if we have
-                        * not yet filled the userspace buffer.
-                        */
-                       error = 0;
-                       break;
-               default:
-                       goto out_free;
-               }
-               head.fmh_entries += xhead.fmh_entries;
-               head.fmh_oflags = xhead.fmh_oflags;
-
-               /*
-                * If the caller wanted a record count or there aren't any
-                * new records to return, we're done.
-                */
-               if (head.fmh_count == 0 || xhead.fmh_entries == 0)
-                       break;
-
-               /* Copy all the records we got out to userspace. */
-               if (copy_to_user(user_recs, recs,
-                                xhead.fmh_entries * sizeof(struct fsmap))) {
-                       error = -EFAULT;
-                       goto out_free;
-               }
-
-               /* Remember the last record flags we copied to userspace. */
-               last_rec = &recs[xhead.fmh_entries - 1];
-               last_flags = last_rec->fmr_flags;
-
-               /* Set up the low key for the next iteration. */
-               xfs_fsmap_to_internal(&xhead.fmh_keys[0], last_rec);
-               trace_xfs_getfsmap_low_key(ip->i_mount, &xhead.fmh_keys[0]);
-       } while (!done && head.fmh_entries < head.fmh_count);
-
-       /*
-        * If there are no more records in the query result set and we're not
-        * in counting mode, mark the last record returned with the LAST flag.
-        */
-       if (done && head.fmh_count > 0 && head.fmh_entries > 0) {
-               struct fsmap __user     *user_rec;
-
-               last_flags |= FMR_OF_LAST;
-               user_rec = &arg->fmh_recs[head.fmh_entries - 1];
-
-               if (copy_to_user(&user_rec->fmr_flags, &last_flags,
-                                       sizeof(last_flags))) {
-                       error = -EFAULT;
-                       goto out_free;
-               }
-       }
-
-       /* copy back header */
-       if (copy_to_user(arg, &head, sizeof(struct fsmap_head))) {
-               error = -EFAULT;
-               goto out_free;
-       }
-
-out_free:
-       kvfree(recs);
-       return error;
-}
-
 int
 xfs_ioc_swapext(
        xfs_swapext_t   *sxp)