diff -urNp x-ref/fs/fcntl.c x/fs/fcntl.c --- x-ref/fs/fcntl.c 2003-01-14 03:04:09.000000000 +0100 +++ x/fs/fcntl.c 2003-01-14 03:04:12.000000000 +0100 @@ -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 x-ref/fs/open.c x/fs/open.c --- x-ref/fs/open.c 2002-11-29 02:23:16.000000000 +0100 +++ x/fs/open.c 2003-01-14 03:04:12.000000000 +0100 @@ -699,6 +699,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 x-ref/mm/filemap.c x/mm/filemap.c --- x-ref/mm/filemap.c 2003-01-14 03:04:11.000000000 +0100 +++ x/mm/filemap.c 2003-01-14 03:04:52.000000000 +0100 @@ -1538,8 +1538,6 @@ static ssize_t generic_file_direct_IO(in retval = -EINVAL; if ((offset & blocksize_mask) || (count & blocksize_mask) || ((unsigned long) buf & blocksize_mask)) goto out_free; - if (!mapping->a_ops->direct_IO) - goto out_free; if ((rw == READ) && (offset + count > size)) count = size - offset;