add a FMODE flag to make XFS invisible I/O less hacky
Subsystems (2)
PATCH 1/1 add a FMODE flag to make XFS invisible I/O less hacky
XFS has a mode called invisble I/O that doesn't update any of the timestamps. It's used for HSM-style applications and exposed through the nasty open by handle ioctl.
Instead of doing directly assignment of file operations that set an internal flag for it add a new FMODE_NOCMTIME flag that we can check in the normal file operations.
Note that I'd like to get this into 2.6.29 via the XFS tree as there are a lot changes in XFS that would cause conflicts otherwise.
For 2.6.30 I'll plan turning it into a proper O_ flag available via open(2), but for now I just want to sort out the XFS issues.
Signed-off-by Christoph Hellwig <[email protected]>
fs/xfs/linux-2.6/xfs_ioctl32.c +19 -37
@@ -599,19 +599,24 @@ out:return error; } -STATIC long -xfs_compat_ioctl ( -xfs_inode_t *ip, -struct file *filp, -int ioflags, -unsigned cmd, -void __user *arg) +long +xfs_file_compat_ioctl ( +struct file *filp, +unsigned cmd, +unsigned long p) { -struct inode *inode = filp->f_path.dentry->d_inode; -xfs_mount_t *mp = ip->i_mount; -int error; +struct inode *inode = filp->f_path.dentry->d_inode; +struct xfs_inode *ip =XFS_I (inode); +struct xfs_mount *mp = ip->i_mount; +void __user *arg = (void __user *)p; +int ioflags =0 ; +int error; + +if (filp->f_mode &FMODE_NOCMTIME ) + ioflags |=IO_INVIS ; + +xfs_itrace_entry (ip); -xfs_itrace_entry (XFS_I (inode));switch (cmd) {/* No size or alignment issues on any arch */ case XFS_IOC_DIOINFO :
@@ -632,7 +637,7 @@ xfs_compat_ioctl(case XFS_IOC_GOINGDOWN :case XFS_IOC_ERROR_INJECTION :case XFS_IOC_ERROR_CLEARALL : -return xfs_ioctl (ip, filp, ioflags, cmd, arg); +return xfs_file_ioctl (filp, cmd, p);#ifndef BROKEN_X86_ALIGNMENT /* These are handled fine if no alignment issues */ case XFS_IOC_ALLOCSP :
@@ -646,7 +651,7 @@ xfs_compat_ioctl(case XFS_IOC_FSGEOMETRY_V1 :case XFS_IOC_FSGROWFSDATA :case XFS_IOC_FSGROWFSRT : -return xfs_ioctl (ip, filp, ioflags, cmd, arg); +return xfs_file_ioctl (filp, cmd, p);#else case XFS_IOC_ALLOCSP_32 :case XFS_IOC_FREESP_32 :
@@ -687,7 +692,7 @@ xfs_compat_ioctl(case XFS_IOC_SETXFLAGS_32 :case XFS_IOC_GETVERSION_32 : cmd =_NATIVE_IOC (cmd, long); -return xfs_ioctl (ip, filp, ioflags, cmd, arg); +return xfs_file_ioctl (filp, cmd, p);case XFS_IOC_SWAPEXT : {struct xfs_swapext sxp;struct compat_xfs_swapext __user *sxu = arg;
@@ -738,26 +743,3 @@ xfs_compat_ioctl(return -XFS_ERROR (ENOIOCTLCMD ); } } - -long -xfs_file_compat_ioctl ( -struct file *filp, -unsigned int cmd, -unsigned long p) -{ -struct inode *inode = filp->f_path.dentry->d_inode; - -return xfs_compat_ioctl (XFS_I (inode), filp,0 , cmd, (void __user *)p); -} - -long -xfs_file_compat_invis_ioctl ( -struct file *filp, -unsigned int cmd, -unsigned long p) -{ -struct inode *inode = filp->f_path.dentry->d_inode; - -return xfs_compat_ioctl (XFS_I (inode), filp,IO_INVIS , cmd, - (void __user *)p); -}
fs/xfs/linux-2.6/xfs_file.c +20 -125
208 lines not on this page · raw message
fs/xfs/linux-2.6/xfs_ioctl.c +20 -9
@@ -319,10 +319,11 @@ xfs_open_by_handle(put_unused_fd (new_fd);return -XFS_ERROR (-PTR_ERR (filp)); } +if (inode->i_mode &S_IFREG ) {/* invisible operation should not change atime */ filp->f_flags |=O_NOATIME ; - filp->f_op = &xfs_invis_file_operations; + filp->f_mode |=FMODE_NOCMTIME ; }fd_install (new_fd, filp);
@@ -1328,21 +1329,31 @@ xfs_ioc_getbmapx(return 0 ; } -int -xfs_ioctl ( -xfs_inode_t *ip, +/* +* Note: some of the ioctl's return positive numbers as a +* byte count indicating success, such as readlink_by_handle. +* So we don't "sign flip" like most other routines. This means +* true errors need to be returned as a negative value. +*/ +long +xfs_file_ioctl (struct file *filp, -int ioflags,unsigned int cmd, -void __user *arg) +unsigned long p) {struct inode *inode = filp->f_path.dentry->d_inode; -xfs_mount_t *mp = ip->i_mount; +struct xfs_inode *ip =XFS_I (inode); +struct xfs_mount *mp = ip->i_mount; +void __user *arg = (void __user *)p; +int ioflags =0 ;int error; -xfs_itrace_entry (XFS_I (inode)); -switch (cmd) { +if (filp->f_mode &FMODE_NOCMTIME ) + ioflags |=IO_INVIS ; +xfs_itrace_entry (ip); + +switch (cmd) {case XFS_IOC_ALLOCSP :case XFS_IOC_FREESP :case XFS_IOC_RESVSP :
fs/xfs/linux-2.6/xfs_iops.h +0 -1
@@ -22,7 +22,6 @@ struct xfs_inode;extern const struct file_operations xfs_file_operations;extern const struct file_operations xfs_dir_file_operations; -extern const struct file_operations xfs_invis_file_operations;extern ssize_t xfs_vn_listxattr (struct dentry *,char *data,size_t size);
include/linux/fs.h +8 -0
@@ -81,6 +81,14 @@ extern int dir_notify_enable;#define FMODE_WRITE_IOCTL ((__force fmode_t)128)#define FMODE_NDELAY_NOW ((__force fmode_t)256) +/* +* Don't update ctime and mtime. +* +* Currently a special hack for the XFS open_by_handle ioctl, but we'll +* hopefully graduate it to a proper O_CMTIME flag supported by open(2) soon. +*/ +#define FMODE_NOCMTIME ((__force fmode_t)2048) +#define RW_MASK 1#define RWA_MASK 2#define READ 0
fs/xfs/linux-2.6/xfs_ioctl.h +4 -4
@@ -68,13 +68,13 @@ xfs_attrmulti_attr_remove( __uint32_t flags);extern long -xfs_file_compat_ioctl ( -struct file *file, +xfs_file_ioctl ( +struct file *filp,unsigned int cmd, -unsigned long arg); +unsigned long p);extern long -xfs_file_compat_ioctl_invis ( +xfs_file_compat_ioctl (struct file *file,unsigned int cmd,unsigned long arg);
fs/xfs/xfs_vnodeops.h +0 -2
@@ -53,8 +53,6 @@ int xfs_attr_set(struct xfs_inode *dp, cint xfs_attr_remove (struct xfs_inode *dp,const char *name,int flags);int xfs_attr_list (struct xfs_inode *dp,char *buffer,int bufsize,int flags,struct attrlist_cursor_kern *cursor); -int xfs_ioctl (struct xfs_inode *ip,struct file *filp, -int ioflags,unsigned int cmd,void __user *arg);ssize_t xfs_read (struct xfs_inode *ip,struct kiocb *iocb,const struct iovec *iovp,unsigned int segs,loff_t *offset,int ioflags);