Skip to contentSkip to conversation

fs: Add new pre-allocation ioctls to vfs for compatibility with legacy xfs ioctls

PATCH In review Ankit Jain 3 participants 3 messages Dec 18, 2008 – Dec 19, 2008

Subsystems (3)
lore
Share & tools
lore

Ankit Jain

author
#0 lore raw

PATCH v2 1/1 fs: Add new pre-allocation ioctls to vfs for compatibility with legacy xfs ioctls

This patch adds ioctls to vfs for compatibility with legacy XFS pre-allocation ioctls (XFS_IOC_*RESVP*). The implementation effectively invokes sys_fallocate for the new ioctls.
Note: These legacy ioctls are also implemented by OCFS2.

Changes in v2:
- Dropped the incorrect handling of *UNRESVSP* ioctl.
- Made the ioctl and argument structure kernel only (__KERNEL__)

---
 fs/ioctl.c             |   35 ++++++++++++++++++++++++++
 fs/open.c              |   51 ++++++++++++++++++-------------------
 include/linux/falloc.h |   21 +++++++++++++++
 include/linux/fs.h     |    2 +
 4 files changed, 83 insertions(+), 26 deletions(-)
fs/ioctl.c +35 -0
index 43e8b2c..2b3fae7 100644
@@ -15,6 +15,7 @@
 #include <linux/uaccess.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>
+#include <linux/falloc.h>
 
 #include <asm/ioctls.h>
 
@@ -346,6 +347,37 @@ EXPORT_SYMBOL(generic_block_fiemap);
 
 #endif  /*  CONFIG_BLOCK  */
 
+/*
+ * This provides compatibility with legacy XFS pre-allocation ioctls
+ * which predate the fallocate syscall.
+ *
+ * Only the l_start, l_len and l_whence fields of the 'struct space_resv'
+ * are used here, rest are ignored.
+ */
+static int ioctl_preallocate(struct file *filp, unsigned long arg)
+{
+	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct space_resv sr;
+
+	if (copy_from_user(&sr, (struct space_resv __user *) arg, sizeof(sr)))
+		return -EFAULT;
+
+	switch (sr.l_whence) {
+	case SEEK_SET:
+		break;
+	case SEEK_CUR:
+		sr.l_start += filp->f_pos;
+		break;
+	case SEEK_END:
+		sr.l_start += i_size_read(inode);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return do_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
+}
+
 static int file_ioctl(struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
@@ -361,6 +393,9 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
 		return put_user(inode->i_sb->s_blocksize, p);
 	case FIONREAD:
 		return put_user(i_size_read(inode) - filp->f_pos, p);
+	case F_IOC_RESVSP:
+	case F_IOC_RESVSP64:
+		return ioctl_preallocate(filp, arg);
 	}
 
 	return vfs_ioctl(filp, cmd, arg);
fs/open.c +25 -26

87 lines not on this page · raw message

include/linux/falloc.h +21 -0
index 8e912ab..c4bf904 100644
@@ -3,4 +3,25 @@
 
 #define FALLOC_FL_KEEP_SIZE	0x01 /* default is extend size */
 
+#ifdef __KERNEL__
+
+/*
+ * Space reservation ioctls and argument structure
+ * are designed to be compatible with the legacy XFS ioctls.
+ */
+struct space_resv {
+	__s16		l_type;
+	__s16		l_whence;
+	__s64		l_start;
+	__s64		l_len;		/* len == 0 means until end of file */
+	__s32		l_sysid;
+	__u32		l_pid;
+	__s32		l_pad[4];	/* reserve area			    */
+};
+
+#define F_IOC_RESVSP		_IOW('X', 40, struct space_resv)
+#define F_IOC_RESVSP64		_IOW('X', 42, struct space_resv)
+
+#endif
+
 #endif /* _FALLOC_H_ */
include/linux/fs.h +2 -0
index 4a853ef..b1d8f12 100644
@@ -1671,6 +1671,8 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
 
 extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
 		       struct file *filp);
+extern long do_fallocate(struct file *file, int mode, loff_t offset,
+			loff_t len);
 extern long do_sys_open(int dfd, const char __user *filename, int flags,
 			int mode);
 extern struct file *filp_open(const char *, int, int);
#1 lore raw
Quoted 10 lines · Ankit Jain

This patch adds ioctls to vfs for compatibility with legacy XFS pre-allocation ioctls (XFS_IOC_*RESVP*). The implementation effectively invokes sys_fallocate for the new ioctls.
Note: These legacy ioctls are also implemented by OCFS2.

Changes in v2:
- Dropped the incorrect handling of *UNRESVSP* ioctl.
- Made the ioctl and argument structure kernel only (__KERNEL__)

.....

fs/ioctl.c static int file_ioctl(struct file *filp, unsigned int cmd, · line 401

Quoted 10 lines
fs/ioctl.c +3 -0
@@ -361,6 +393,9 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
 		return put_user(inode->i_sb->s_blocksize, p);
 	case FIONREAD:
 		return put_user(i_size_read(inode) - filp->f_pos, p);
+	case F_IOC_RESVSP:
+	case F_IOC_RESVSP64:
+		return ioctl_preallocate(filp, arg);
 	}
 
 	return vfs_ioctl(filp, cmd, arg);

Adding this here breaks XFS_IOC_RESVSP in subtle and interesting ways.

XFS_IOC_RESVSP supports invisible I/O, and that means XFS_IOC_RESVSP needs to be passed through to vfs_ioctl() to vector to XFS to handle.

This happenѕ because:

include/linux/falloc.h line 23

Quoted 12 lines
include/linux/falloc.h +12 -0
+struct space_resv {
+	__s16		l_type;
+	__s16		l_whence;
+	__s64		l_start;
+	__s64		l_len;		/* len == 0 means until end of file */
+	__s32		l_sysid;
+	__u32		l_pid;
+	__s32		l_pad[4];	/* reserve area			    */
+};
+
+#define F_IOC_RESVSP		_IOW('X', 40, struct space_resv)
+#define F_IOC_RESVSP64		_IOW('X', 42, struct space_resv)

Is the same as:

#define XFS_IOC_RESVSP _IOW ('X', 40, struct xfs_flock64)
#define XFS_IOC_RESVSP64 _IOW ('X', 42, struct xfs_flock64)

because:

typedef struct xfs_flock64 {
        __s16           l_type;
        __s16           l_whence;
        __s64           l_start;
        __s64           l_len;          /* len == 0 means until end of file */
        __s32           l_sysid;
        __u32           l_pid;
        __s32           l_pad[4];       /* reserve area                     */
} xfs_flock64_t;

is the same size as struct space_resv. Hence existing calls to XFS_IOC_RESVSP will now vector incorrectly down the fallocate path resulting in invisible operations will now be visible....

Cheers,

Dave.

Signature · 6 lines
Dave Chinner
[email protected]
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#2 lore raw
Quoted 3 lines · Dave Chinner

XFS_IOC_RESVSP supports invisible I/O, and that means XFS_IOC_RESVSP needs to be passed through to vfs_ioctl() to vector to XFS to handle.

When the current XFS git tree gets merged to mainline before this patch. invisible I/O handling is now FMODE_NOCMTIME in file->f_flags which this patch will pass through to the filesystem. We just need to chage xfs_vn_fallocate ot honour it.