The original kernel patch that Dave wrote for xfs_spaceman implemented FS_IOC_FIEMAPFS ioctl, here is the original fiemap extension patch: http://oss.sgi.com/archives/xfs/2012-10/msg00363.html These patches were not posted and were just forward ported to a current 3.18-rc7+ for-next XFS tree and were pushed to the fiemapfs branch in Dave's kernel tree at: git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs.git The original xfs_spaceman tool that Dave wrote to call the fiemap interface and make use of it is here: http://oss.sgi.com/archives/xfs/2012-10/msg00366.html Dave just updated it to the 3.2.2 code base and pushed it to the spaceman branch in this tree: git://git.kernel.org/pub/scm/fs/xfs/xfsprogs-dev.git This patch is concerned with turning FS_IOC_FIEMAPFS, present in the earlier version of xfs_spaceman into an XFS specific ioctl called XFS_IOC_FIEMAPFS that uses the fiemap plumbing. Please do comment. Signed-off-by: Dhruvesh Rathore <dhruvesh_r@xxxxxxxxxxx> Amey Ruikar <ameyruikar@xxxxxxxxx> Somdeep Dey <somdeepdey10@xxxxxxxxx> --- linux-xfs/fs/xfs/xfs_fs.h | 1 + linux-xfs/fs/xfs/xfs_ioctl.c | 71 ++++- xfsprogs-3.2.2/include/xfs_fs.h | 1 + xfsprogs-3.2.2/spaceman/freesp.c | 10 ++++++--- 4 files changed, 79 insertions(+), 4 deletions(-) --------------------------------------------------------------------------------------- --- a/linux-xfs/fs/xfs/xfs_fs.h 2015-01-04 15:26:46.954401773 +0530 +++ b/linux-xfs/fs/xfs/xfs_fs.h 2015-01-04 11:29:54.531652554 +0530 @@ -505,6 +505,7 @@ #define XFS_IOC_DIOINFO _IOR ('X', 30, struct dioattr) #define XFS_IOC_FSGETXATTR _IOR ('X', 31, struct fsxattr) #define XFS_IOC_FSSETXATTR _IOW ('X', 32, struct fsxattr) +#define XFS_IOC_FIEMAPFS _IOWR('X', 33, struct fiemap) #define XFS_IOC_ALLOCSP64 _IOW ('X', 36, struct xfs_flock64) #define XFS_IOC_FREESP64 _IOW ('X', 37, struct xfs_flock64) #define XFS_IOC_GETBMAP _IOWR('X', 38, struct getbmap) ---------------------------------------------------------------------------------------- --- a/linux-xfs/fs/xfs/xfs_ioctl.c 2015-01-04 15:45:26.518359725 +0530 +++ b/linux-xfs/fs/xfs/xfs_ioctl.c 2015-01-04 15:24:06.030407817 +0530 @@ -49,6 +49,8 @@ #include <linux/exportfs.h> +/* So that the fiemap access checks can't overflow on 32 bit machines. */ +#define FIEMAP_MAX_EXTENTS (UINT_MAX / sizeof(struct fiemap_extent)) /* * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to @@ -1511,8 +1513,73 @@ return error; } +static int fiemap_check_ranges(struct super_block *sb, + u64 start, u64 len, u64 *new_len) +{ + u64 maxbytes = (u64) sb->s_maxbytes; + + *new_len = len; + + if (len == 0) + return -EINVAL; + + if (start > maxbytes) + return -EFBIG; + + /* + * Shrink request scope to what the fs can actually handle. + */ + if (len > maxbytes || (maxbytes - len) < start) + *new_len = maxbytes - start; + return 0; +} + +static int xfsctl_fiemapfs(struct super_block *sb, unsigned long arg) +{ + struct fiemap fiemap; + struct fiemap __user *ufiemap = (struct fiemap __user *) arg; + struct fiemap_extent_info fieinfo = { 0, }; + u64 len; + int error; + + if (!sb->s_op->fiemapfs) + return -EOPNOTSUPP; + if (copy_from_user(&fiemap, ufiemap, sizeof(fiemap))) + return -EFAULT; + + if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS) + return -EINVAL; + + error = fiemap_check_ranges(sb, fiemap.fm_start, fiemap.fm_length, + &len); + if (error) + return error; + + fieinfo.fi_flags = fiemap.fm_flags; + fieinfo.fi_extents_max = fiemap.fm_extent_count; + fieinfo.fi_extents_start = ufiemap->fm_extents; + + if (fiemap.fm_extent_count != 0 && + !access_ok(VERIFY_WRITE, fieinfo.fi_extents_start, + fieinfo.fi_extents_max * sizeof(struct fiemap_extent))) + return -EFAULT; + + if (fiemap.fm_extent_count != 0 && + (fiemap.fm_flags & FIEMAPFS_FLAG_FREESP_SIZE_HINT) && + !access_ok(VERIFY_READ, fieinfo.fi_extents_start, + sizeof(struct fiemap_extent))) + return -EFAULT; + + error = sb->s_op->fiemapfs(sb, &fieinfo, fiemap.fm_start, len); + fiemap.fm_flags = fieinfo.fi_flags; + fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped; + if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap))) + error = -EFAULT; + + return error; +} /* * Note: some of the ioctl's return positive numbers as a @@ -1570,7 +1637,9 @@ return 0; } - + case XFS_IOC_FIEMAPFS: + return xfsctl_fiemapfs(inode->i_sb, p); + case XFS_IOC_FSBULKSTAT_SINGLE: case XFS_IOC_FSBULKSTAT: case XFS_IOC_FSINUMBERS: -------------------------------------------------------------------------------------------- --- a/xfsprogs-3.2.2/include/xfs_fs.h 2015-01-04 15:26:50.954401773 +0530 +++ b/xfsprogs-3.2.2/include/xfs_fs.h 2015-01-04 11:29:59.531652554 +0530 @@ -505,6 +505,7 @@ #define XFS_IOC_DIOINFO _IOR ('X', 30, struct dioattr) #define XFS_IOC_FSGETXATTR _IOR ('X', 31, struct fsxattr) #define XFS_IOC_FSSETXATTR _IOW ('X', 32, struct fsxattr) +#define XFS_IOC_FIEMAPFS _IOWR('X', 33, struct fiemap) #define XFS_IOC_ALLOCSP64 _IOW ('X', 36, struct xfs_flock64) #define XFS_IOC_FREESP64 _IOW ('X', 37, struct xfs_flock64) #define XFS_IOC_GETBMAP _IOWR('X', 38, struct getbmap) -------------------------------------------------------------------------------------------- --- a/xfsprogs-3.2.2/spaceman/freesp.c 2015-01-04 15:39:58.446372047 +0530 +++ b/xfsprogs-3.2.2/spaceman/freesp.c 2015-01-04 15:38:30.294375357 +0530 @@ -31,7 +31,7 @@ #define FIEMAPFS_FLAG_FREESP_SIZE_HINT 0x20000000 #define FIEMAPFS_FLAG_FREESP_CONTINUE 0x10000000 -#define FS_IOC_FIEMAPFS _IOWR('f', 12, struct fiemap) +#define XFS_IOC_FIEMAPFS _IOWR('X', 33, struct fiemap) #endif typedef struct histent @@ -201,9 +201,9 @@ fiemap->fm_length = length; fiemap->fm_extent_count = NR_EXTENTS; - ret = ioctl(file->fd, XFS_IOC_FIEMAPFS, (unsigned long)fiemap); + ret = xfsctl(file->name,file->fd, XFS_IOC_FIEMAPFS, (unsigned long)fiemap); if (ret < 0) { - fprintf(stderr, "%s: ioctl(FS_IOC_FIEMAPFS) [\"%s\"]: " + fprintf(stderr, "%s: xfsctl(XFS_IOC_FIEMAPFS) [\"%s\"]: " "%s\n", progname, file->name, strerror(errno)); free(fiemap); exitcode = 1; @@ -338,6 +338,10 @@ if (!init(argc, argv)) return 0; + + if (dumpflag) + printf("%8s %8s %8s\n", "agno", "agbno", "len"); + for (agno = 0; agno < file->geom.agcount; agno++) { if (inaglist(agno)) scan_ag(agno); ---------------------------------------------------------------------------------------------- _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs