|
@@ -654,10 +654,23 @@ static inline int __get_file_write_access(struct inode *inode,
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
-static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
|
|
|
- struct file *f,
|
|
|
- int (*open)(struct inode *, struct file *),
|
|
|
- const struct cred *cred)
|
|
|
+int open_check_o_direct(struct file *f)
|
|
|
+{
|
|
|
+ /* NB: we're sure to have correct a_ops only after f_op->open */
|
|
|
+ if (f->f_flags & O_DIRECT) {
|
|
|
+ if (!f->f_mapping->a_ops ||
|
|
|
+ ((!f->f_mapping->a_ops->direct_IO) &&
|
|
|
+ (!f->f_mapping->a_ops->get_xip_mem))) {
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt,
|
|
|
+ struct file *f,
|
|
|
+ int (*open)(struct inode *, struct file *),
|
|
|
+ const struct cred *cred)
|
|
|
{
|
|
|
static const struct file_operations empty_fops = {};
|
|
|
struct inode *inode;
|
|
@@ -713,16 +726,6 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
|
|
|
|
|
|
file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
|
|
|
|
|
|
- /* NB: we're sure to have correct a_ops only after f_op->open */
|
|
|
- if (f->f_flags & O_DIRECT) {
|
|
|
- if (!f->f_mapping->a_ops ||
|
|
|
- ((!f->f_mapping->a_ops->direct_IO) &&
|
|
|
- (!f->f_mapping->a_ops->get_xip_mem))) {
|
|
|
- fput(f);
|
|
|
- f = ERR_PTR(-EINVAL);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
return f;
|
|
|
|
|
|
cleanup_all:
|
|
@@ -750,6 +753,22 @@ cleanup_file:
|
|
|
return ERR_PTR(error);
|
|
|
}
|
|
|
|
|
|
+static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
|
|
|
+ struct file *f,
|
|
|
+ int (*open)(struct inode *, struct file *),
|
|
|
+ const struct cred *cred)
|
|
|
+{
|
|
|
+ struct file *res = do_dentry_open(dentry, mnt, f, open, cred);
|
|
|
+ if (!IS_ERR(res)) {
|
|
|
+ int error = open_check_o_direct(f);
|
|
|
+ if (error) {
|
|
|
+ fput(res);
|
|
|
+ res = ERR_PTR(error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* lookup_instantiate_filp - instantiates the open intent filp
|
|
|
* @nd: pointer to nameidata
|