diff -urNp open-check-ref/fs/fcntl.c open-check/fs/fcntl.c --- open-check-ref/fs/fcntl.c Sat Jul 6 19:07:22 2002 +++ open-check/fs/fcntl.c Sat Jul 6 19:07:48 2002 @@ -231,6 +231,11 @@ static int setfl(int fd, struct file * f } if (arg & O_DIRECT) { + error = -EINVAL; + if (!inode->i_mapping || !inode->i_mapping->a_ops || + !inode->i_mapping->a_ops->direct_IO) + goto out; + if (!filp->f_iobuf) { error = alloc_kiovec(1, &filp->f_iobuf); if (error < 0) diff -urNp open-check-ref/fs/open.c open-check/fs/open.c --- open-check-ref/fs/open.c Fri Jul 5 12:20:51 2002 +++ open-check/fs/open.c Sat Jul 6 19:07:48 2002 @@ -715,6 +715,12 @@ struct file *dentry_open(struct dentry * } 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 */ + error = -EINVAL; + if (f->f_flags & O_DIRECT && (!inode->i_mapping || !inode->i_mapping->a_ops || + !inode->i_mapping->a_ops->direct_IO)) + goto cleanup_all; + return f; cleanup_all: diff -urNp open-check-ref/mm/filemap.c open-check/mm/filemap.c --- open-check-ref/mm/filemap.c Sat Jul 6 19:07:22 2002 +++ open-check/mm/filemap.c Sat Jul 6 19:08:05 2002 @@ -1519,8 +1519,6 @@ static ssize_t generic_file_direct_IO(in retval = -EINVAL; if ((offset & blocksize_mask) || (count & blocksize_mask)) goto out_free; - if (!mapping->a_ops->direct_IO) - goto out_free; if ((rw == READ) && (offset + count > size)) count = size - offset;