]> git.hungrycats.org Git - linux/commitdiff
[PATCH] check for O_DIRECT capability in open(), not write()
authorAndrew Morton <akpm@zip.com.au>
Thu, 4 Jul 2002 15:31:05 +0000 (08:31 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Thu, 4 Jul 2002 15:31:05 +0000 (08:31 -0700)
For O_DIRECT opens we're currently checking that the fs supports
O_DIRECT at write(2)-time.

This is a forward-port of Andrea's patch which moves the check to
open() time.  Seems more sensible.

fs/fcntl.c
fs/open.c
mm/filemap.c

index 96c057d35bd1e09b7aaad851d78538289f24c7b2..8bc8995dd172a472f1c87395a319b1a44575fecc 100644 (file)
@@ -245,6 +245,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
        }
 
        if (arg & O_DIRECT) {
+               if (inode->i_mapping && inode->i_mapping->a_ops) {
+                       if (!inode->i_mapping->a_ops->direct_IO)
+                               return -EINVAL;
+               }
+
                /*
                 * alloc_kiovec() can sleep and we are only serialized by
                 * the big kernel lock here, so abuse the i_sem to serialize
index 1586159468a5640496b1ba92dcbaf78e376c59ff..eec397a0efc258744b99357e008d71a9f9340ff6 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -665,6 +665,14 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
        }
        f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 
+       /* NB: we're sure to have correct a_ops only after f_op->open */
+       if (f->f_flags & O_DIRECT) {
+               error = -EINVAL;
+               if (inode->i_mapping && inode->i_mapping->a_ops)
+                       if (!inode->i_mapping->a_ops->direct_IO)
+                               goto cleanup_all;
+       }
+
        return f;
 
 cleanup_all:
index 86ea3c15e6e8173dc3804a627d7745c0f630c282..17b9167e6a15aefa7afffc5f0b9eeab43473655b 100644 (file)
@@ -1121,8 +1121,6 @@ static ssize_t generic_file_direct_IO(int rw, struct file * filp, char * buf, si
        retval = -EINVAL;
        if ((offset & blocksize_mask) || (count & blocksize_mask))
                goto out_free;
-       if (!mapping->a_ops->direct_IO)
-               goto out_free;
 
        /*
         * Flush to disk exclusively the _data_, metadata must remain