aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2008-12-09 04:47:33 -0500
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-12-10 21:14:41 -0500
commit4d4be482a4d78ca906f45e99fd9fdb91e907f5ad (patch)
tree52974b28fecd3c11fc0596504270ffee976f1b1a
parent6d73cf133c5477f7038577bfeda603ce9946f8cb (diff)
[XFS] 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. (addition of the generic VFS flag has been ACKed by Al as an interims solution) Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c145
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c29
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.h8
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c56
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.h1
-rw-r--r--fs/xfs/xfs_vnodeops.h2
-rw-r--r--include/linux/fs.h8
7 files changed, 71 insertions, 178 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index f999d20a429c..a0c45cc8a6b8 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -45,81 +45,45 @@
45 45
46static struct vm_operations_struct xfs_file_vm_ops; 46static struct vm_operations_struct xfs_file_vm_ops;
47 47
48STATIC_INLINE ssize_t 48STATIC ssize_t
49__xfs_file_read( 49xfs_file_aio_read(
50 struct kiocb *iocb, 50 struct kiocb *iocb,
51 const struct iovec *iov, 51 const struct iovec *iov,
52 unsigned long nr_segs, 52 unsigned long nr_segs,
53 int ioflags,
54 loff_t pos) 53 loff_t pos)
55{ 54{
56 struct file *file = iocb->ki_filp; 55 struct file *file = iocb->ki_filp;
56 int ioflags = IO_ISAIO;
57 57
58 BUG_ON(iocb->ki_pos != pos); 58 BUG_ON(iocb->ki_pos != pos);
59 if (unlikely(file->f_flags & O_DIRECT)) 59 if (unlikely(file->f_flags & O_DIRECT))
60 ioflags |= IO_ISDIRECT; 60 ioflags |= IO_ISDIRECT;
61 if (file->f_mode & FMODE_NOCMTIME)
62 ioflags |= IO_INVIS;
61 return xfs_read(XFS_I(file->f_path.dentry->d_inode), iocb, iov, 63 return xfs_read(XFS_I(file->f_path.dentry->d_inode), iocb, iov,
62 nr_segs, &iocb->ki_pos, ioflags); 64 nr_segs, &iocb->ki_pos, ioflags);
63} 65}
64 66
65STATIC ssize_t 67STATIC ssize_t
66xfs_file_aio_read( 68xfs_file_aio_write(
67 struct kiocb *iocb,
68 const struct iovec *iov,
69 unsigned long nr_segs,
70 loff_t pos)
71{
72 return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO, pos);
73}
74
75STATIC ssize_t
76xfs_file_aio_read_invis(
77 struct kiocb *iocb,
78 const struct iovec *iov,
79 unsigned long nr_segs,
80 loff_t pos)
81{
82 return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
83}
84
85STATIC_INLINE ssize_t
86__xfs_file_write(
87 struct kiocb *iocb, 69 struct kiocb *iocb,
88 const struct iovec *iov, 70 const struct iovec *iov,
89 unsigned long nr_segs, 71 unsigned long nr_segs,
90 int ioflags,
91 loff_t pos) 72 loff_t pos)
92{ 73{
93 struct file *file = iocb->ki_filp; 74 struct file *file = iocb->ki_filp;
75 int ioflags = IO_ISAIO;
94 76
95 BUG_ON(iocb->ki_pos != pos); 77 BUG_ON(iocb->ki_pos != pos);
96 if (unlikely(file->f_flags & O_DIRECT)) 78 if (unlikely(file->f_flags & O_DIRECT))
97 ioflags |= IO_ISDIRECT; 79 ioflags |= IO_ISDIRECT;
80 if (file->f_mode & FMODE_NOCMTIME)
81 ioflags |= IO_INVIS;
98 return xfs_write(XFS_I(file->f_mapping->host), iocb, iov, nr_segs, 82 return xfs_write(XFS_I(file->f_mapping->host), iocb, iov, nr_segs,
99 &iocb->ki_pos, ioflags); 83 &iocb->ki_pos, ioflags);
100} 84}
101 85
102STATIC ssize_t 86STATIC ssize_t
103xfs_file_aio_write(
104 struct kiocb *iocb,
105 const struct iovec *iov,
106 unsigned long nr_segs,
107 loff_t pos)
108{
109 return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO, pos);
110}
111
112STATIC ssize_t
113xfs_file_aio_write_invis(
114 struct kiocb *iocb,
115 const struct iovec *iov,
116 unsigned long nr_segs,
117 loff_t pos)
118{
119 return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
120}
121
122STATIC ssize_t
123xfs_file_splice_read( 87xfs_file_splice_read(
124 struct file *infilp, 88 struct file *infilp,
125 loff_t *ppos, 89 loff_t *ppos,
@@ -127,20 +91,13 @@ xfs_file_splice_read(
127 size_t len, 91 size_t len,
128 unsigned int flags) 92 unsigned int flags)
129{ 93{
130 return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode), 94 int ioflags = 0;
131 infilp, ppos, pipe, len, flags, 0); 95
132} 96 if (infilp->f_mode & FMODE_NOCMTIME)
97 ioflags |= IO_INVIS;
133 98
134STATIC ssize_t
135xfs_file_splice_read_invis(
136 struct file *infilp,
137 loff_t *ppos,
138 struct pipe_inode_info *pipe,
139 size_t len,
140 unsigned int flags)
141{
142 return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode), 99 return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode),
143 infilp, ppos, pipe, len, flags, IO_INVIS); 100 infilp, ppos, pipe, len, flags, ioflags);
144} 101}
145 102
146STATIC ssize_t 103STATIC ssize_t
@@ -151,20 +108,13 @@ xfs_file_splice_write(
151 size_t len, 108 size_t len,
152 unsigned int flags) 109 unsigned int flags)
153{ 110{
154 return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode), 111 int ioflags = 0;
155 pipe, outfilp, ppos, len, flags, 0); 112
156} 113 if (outfilp->f_mode & FMODE_NOCMTIME)
114 ioflags |= IO_INVIS;
157 115
158STATIC ssize_t
159xfs_file_splice_write_invis(
160 struct pipe_inode_info *pipe,
161 struct file *outfilp,
162 loff_t *ppos,
163 size_t len,
164 unsigned int flags)
165{
166 return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode), 116 return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode),
167 pipe, outfilp, ppos, len, flags, IO_INVIS); 117 pipe, outfilp, ppos, len, flags, ioflags);
168} 118}
169 119
170STATIC int 120STATIC int
@@ -275,42 +225,6 @@ xfs_file_mmap(
275 return 0; 225 return 0;
276} 226}
277 227
278STATIC long
279xfs_file_ioctl(
280 struct file *filp,
281 unsigned int cmd,
282 unsigned long p)
283{
284 struct inode *inode = filp->f_path.dentry->d_inode;
285
286
287 /* NOTE: some of the ioctl's return positive #'s as a
288 * byte count indicating success, such as
289 * readlink_by_handle. So we don't "sign flip"
290 * like most other routines. This means true
291 * errors need to be returned as a negative value.
292 */
293 return xfs_ioctl(XFS_I(inode), filp, 0, cmd, (void __user *)p);
294}
295
296STATIC long
297xfs_file_ioctl_invis(
298 struct file *filp,
299 unsigned int cmd,
300 unsigned long p)
301{
302 struct inode *inode = filp->f_path.dentry->d_inode;
303
304
305 /* NOTE: some of the ioctl's return positive #'s as a
306 * byte count indicating success, such as
307 * readlink_by_handle. So we don't "sign flip"
308 * like most other routines. This means true
309 * errors need to be returned as a negative value.
310 */
311 return xfs_ioctl(XFS_I(inode), filp, IO_INVIS, cmd, (void __user *)p);
312}
313
314/* 228/*
315 * mmap()d file has taken write protection fault and is being made 229 * mmap()d file has taken write protection fault and is being made
316 * writable. We can set the page state up correctly for a writable 230 * writable. We can set the page state up correctly for a writable
@@ -346,25 +260,6 @@ const struct file_operations xfs_file_operations = {
346#endif 260#endif
347}; 261};
348 262
349const struct file_operations xfs_invis_file_operations = {
350 .llseek = generic_file_llseek,
351 .read = do_sync_read,
352 .write = do_sync_write,
353 .aio_read = xfs_file_aio_read_invis,
354 .aio_write = xfs_file_aio_write_invis,
355 .splice_read = xfs_file_splice_read_invis,
356 .splice_write = xfs_file_splice_write_invis,
357 .unlocked_ioctl = xfs_file_ioctl_invis,
358#ifdef CONFIG_COMPAT
359 .compat_ioctl = xfs_file_compat_invis_ioctl,
360#endif
361 .mmap = xfs_file_mmap,
362 .open = xfs_file_open,
363 .release = xfs_file_release,
364 .fsync = xfs_file_fsync,
365};
366
367
368const struct file_operations xfs_dir_file_operations = { 263const struct file_operations xfs_dir_file_operations = {
369 .open = xfs_dir_open, 264 .open = xfs_dir_open,
370 .read = generic_read_dir, 265 .read = generic_read_dir,
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index c8f1e632ba94..0264c8719ffd 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -319,10 +319,11 @@ xfs_open_by_handle(
319 put_unused_fd(new_fd); 319 put_unused_fd(new_fd);
320 return -XFS_ERROR(-PTR_ERR(filp)); 320 return -XFS_ERROR(-PTR_ERR(filp));
321 } 321 }
322
322 if (inode->i_mode & S_IFREG) { 323 if (inode->i_mode & S_IFREG) {
323 /* invisible operation should not change atime */ 324 /* invisible operation should not change atime */
324 filp->f_flags |= O_NOATIME; 325 filp->f_flags |= O_NOATIME;
325 filp->f_op = &xfs_invis_file_operations; 326 filp->f_mode |= FMODE_NOCMTIME;
326 } 327 }
327 328
328 fd_install(new_fd, filp); 329 fd_install(new_fd, filp);
@@ -1328,21 +1329,31 @@ xfs_ioc_getbmapx(
1328 return 0; 1329 return 0;
1329} 1330}
1330 1331
1331int 1332/*
1332xfs_ioctl( 1333 * Note: some of the ioctl's return positive numbers as a
1333 xfs_inode_t *ip, 1334 * byte count indicating success, such as readlink_by_handle.
1335 * So we don't "sign flip" like most other routines. This means
1336 * true errors need to be returned as a negative value.
1337 */
1338long
1339xfs_file_ioctl(
1334 struct file *filp, 1340 struct file *filp,
1335 int ioflags,
1336 unsigned int cmd, 1341 unsigned int cmd,
1337 void __user *arg) 1342 unsigned long p)
1338{ 1343{
1339 struct inode *inode = filp->f_path.dentry->d_inode; 1344 struct inode *inode = filp->f_path.dentry->d_inode;
1340 xfs_mount_t *mp = ip->i_mount; 1345 struct xfs_inode *ip = XFS_I(inode);
1346 struct xfs_mount *mp = ip->i_mount;
1347 void __user *arg = (void __user *)p;
1348 int ioflags = 0;
1341 int error; 1349 int error;
1342 1350
1343 xfs_itrace_entry(XFS_I(inode)); 1351 if (filp->f_mode & FMODE_NOCMTIME)
1344 switch (cmd) { 1352 ioflags |= IO_INVIS;
1345 1353
1354 xfs_itrace_entry(ip);
1355
1356 switch (cmd) {
1346 case XFS_IOC_ALLOCSP: 1357 case XFS_IOC_ALLOCSP:
1347 case XFS_IOC_FREESP: 1358 case XFS_IOC_FREESP:
1348 case XFS_IOC_RESVSP: 1359 case XFS_IOC_RESVSP:
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.h b/fs/xfs/linux-2.6/xfs_ioctl.h
index d92131c827bc..8c16bf2d7e03 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.h
+++ b/fs/xfs/linux-2.6/xfs_ioctl.h
@@ -68,13 +68,13 @@ xfs_attrmulti_attr_remove(
68 __uint32_t flags); 68 __uint32_t flags);
69 69
70extern long 70extern long
71xfs_file_compat_ioctl( 71xfs_file_ioctl(
72 struct file *file, 72 struct file *filp,
73 unsigned int cmd, 73 unsigned int cmd,
74 unsigned long arg); 74 unsigned long p);
75 75
76extern long 76extern long
77xfs_file_compat_invis_ioctl( 77xfs_file_compat_ioctl(
78 struct file *file, 78 struct file *file,
79 unsigned int cmd, 79 unsigned int cmd,
80 unsigned long arg); 80 unsigned long arg);
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index b34b3d8892a2..0504cece9f66 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -599,19 +599,24 @@ out:
599 return error; 599 return error;
600} 600}
601 601
602STATIC long 602long
603xfs_compat_ioctl( 603xfs_file_compat_ioctl(
604 xfs_inode_t *ip, 604 struct file *filp,
605 struct file *filp, 605 unsigned cmd,
606 int ioflags, 606 unsigned long p)
607 unsigned cmd,
608 void __user *arg)
609{ 607{
610 struct inode *inode = filp->f_path.dentry->d_inode; 608 struct inode *inode = filp->f_path.dentry->d_inode;
611 xfs_mount_t *mp = ip->i_mount; 609 struct xfs_inode *ip = XFS_I(inode);
612 int error; 610 struct xfs_mount *mp = ip->i_mount;
611 void __user *arg = (void __user *)p;
612 int ioflags = 0;
613 int error;
614
615 if (filp->f_mode & FMODE_NOCMTIME)
616 ioflags |= IO_INVIS;
617
618 xfs_itrace_entry(ip);
613 619
614 xfs_itrace_entry(XFS_I(inode));
615 switch (cmd) { 620 switch (cmd) {
616 /* No size or alignment issues on any arch */ 621 /* No size or alignment issues on any arch */
617 case XFS_IOC_DIOINFO: 622 case XFS_IOC_DIOINFO:
@@ -632,7 +637,7 @@ xfs_compat_ioctl(
632 case XFS_IOC_GOINGDOWN: 637 case XFS_IOC_GOINGDOWN:
633 case XFS_IOC_ERROR_INJECTION: 638 case XFS_IOC_ERROR_INJECTION:
634 case XFS_IOC_ERROR_CLEARALL: 639 case XFS_IOC_ERROR_CLEARALL:
635 return xfs_ioctl(ip, filp, ioflags, cmd, arg); 640 return xfs_file_ioctl(filp, cmd, p);
636#ifndef BROKEN_X86_ALIGNMENT 641#ifndef BROKEN_X86_ALIGNMENT
637 /* These are handled fine if no alignment issues */ 642 /* These are handled fine if no alignment issues */
638 case XFS_IOC_ALLOCSP: 643 case XFS_IOC_ALLOCSP:
@@ -646,7 +651,7 @@ xfs_compat_ioctl(
646 case XFS_IOC_FSGEOMETRY_V1: 651 case XFS_IOC_FSGEOMETRY_V1:
647 case XFS_IOC_FSGROWFSDATA: 652 case XFS_IOC_FSGROWFSDATA:
648 case XFS_IOC_FSGROWFSRT: 653 case XFS_IOC_FSGROWFSRT:
649 return xfs_ioctl(ip, filp, ioflags, cmd, arg); 654 return xfs_file_ioctl(filp, cmd, p);
650#else 655#else
651 case XFS_IOC_ALLOCSP_32: 656 case XFS_IOC_ALLOCSP_32:
652 case XFS_IOC_FREESP_32: 657 case XFS_IOC_FREESP_32:
@@ -687,7 +692,7 @@ xfs_compat_ioctl(
687 case XFS_IOC_SETXFLAGS_32: 692 case XFS_IOC_SETXFLAGS_32:
688 case XFS_IOC_GETVERSION_32: 693 case XFS_IOC_GETVERSION_32:
689 cmd = _NATIVE_IOC(cmd, long); 694 cmd = _NATIVE_IOC(cmd, long);
690 return xfs_ioctl(ip, filp, ioflags, cmd, arg); 695 return xfs_file_ioctl(filp, cmd, p);
691 case XFS_IOC_SWAPEXT: { 696 case XFS_IOC_SWAPEXT: {
692 struct xfs_swapext sxp; 697 struct xfs_swapext sxp;
693 struct compat_xfs_swapext __user *sxu = arg; 698 struct compat_xfs_swapext __user *sxu = arg;
@@ -738,26 +743,3 @@ xfs_compat_ioctl(
738 return -XFS_ERROR(ENOIOCTLCMD); 743 return -XFS_ERROR(ENOIOCTLCMD);
739 } 744 }
740} 745}
741
742long
743xfs_file_compat_ioctl(
744 struct file *filp,
745 unsigned int cmd,
746 unsigned long p)
747{
748 struct inode *inode = filp->f_path.dentry->d_inode;
749
750 return xfs_compat_ioctl(XFS_I(inode), filp, 0, cmd, (void __user *)p);
751}
752
753long
754xfs_file_compat_invis_ioctl(
755 struct file *filp,
756 unsigned int cmd,
757 unsigned long p)
758{
759 struct inode *inode = filp->f_path.dentry->d_inode;
760
761 return xfs_compat_ioctl(XFS_I(inode), filp, IO_INVIS, cmd,
762 (void __user *)p);
763}
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h
index 8b1a1e31dc21..ef41c92ce66e 100644
--- a/fs/xfs/linux-2.6/xfs_iops.h
+++ b/fs/xfs/linux-2.6/xfs_iops.h
@@ -22,7 +22,6 @@ struct xfs_inode;
22 22
23extern const struct file_operations xfs_file_operations; 23extern const struct file_operations xfs_file_operations;
24extern const struct file_operations xfs_dir_file_operations; 24extern const struct file_operations xfs_dir_file_operations;
25extern const struct file_operations xfs_invis_file_operations;
26 25
27extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size); 26extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size);
28 27
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
index 2a45b00ad32e..55d955ec4ece 100644
--- a/fs/xfs/xfs_vnodeops.h
+++ b/fs/xfs/xfs_vnodeops.h
@@ -53,8 +53,6 @@ int xfs_attr_set(struct xfs_inode *dp, const char *name, char *value,
53int xfs_attr_remove(struct xfs_inode *dp, const char *name, int flags); 53int xfs_attr_remove(struct xfs_inode *dp, const char *name, int flags);
54int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize, 54int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
55 int flags, struct attrlist_cursor_kern *cursor); 55 int flags, struct attrlist_cursor_kern *cursor);
56int xfs_ioctl(struct xfs_inode *ip, struct file *filp,
57 int ioflags, unsigned int cmd, void __user *arg);
58ssize_t xfs_read(struct xfs_inode *ip, struct kiocb *iocb, 56ssize_t xfs_read(struct xfs_inode *ip, struct kiocb *iocb,
59 const struct iovec *iovp, unsigned int segs, 57 const struct iovec *iovp, unsigned int segs,
60 loff_t *offset, int ioflags); 58 loff_t *offset, int ioflags);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 51bd9370d437..965b9ba3865d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -81,6 +81,14 @@ extern int dir_notify_enable;
81#define FMODE_WRITE_IOCTL ((__force fmode_t)128) 81#define FMODE_WRITE_IOCTL ((__force fmode_t)128)
82#define FMODE_NDELAY_NOW ((__force fmode_t)256) 82#define FMODE_NDELAY_NOW ((__force fmode_t)256)
83 83
84/*
85 * Don't update ctime and mtime.
86 *
87 * Currently a special hack for the XFS open_by_handle ioctl, but we'll
88 * hopefully graduate it to a proper O_CMTIME flag supported by open(2) soon.
89 */
90#define FMODE_NOCMTIME ((__force fmode_t)2048)
91
84#define RW_MASK 1 92#define RW_MASK 1
85#define RWA_MASK 2 93#define RWA_MASK 2
86#define READ 0 94#define READ 0