fuse: add dedicated filesystem context ops for submounts
[linux-2.6-microblaze.git] / fs / fuse / inode.c
index b4b956d..a0a8228 100644 (file)
@@ -506,6 +506,45 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
        return err;
 }
 
+static int fuse_sync_fs(struct super_block *sb, int wait)
+{
+       struct fuse_mount *fm = get_fuse_mount_super(sb);
+       struct fuse_conn *fc = fm->fc;
+       struct fuse_syncfs_in inarg;
+       FUSE_ARGS(args);
+       int err;
+
+       /*
+        * Userspace cannot handle the wait == 0 case.  Avoid a
+        * gratuitous roundtrip.
+        */
+       if (!wait)
+               return 0;
+
+       /* The filesystem is being unmounted.  Nothing to do. */
+       if (!sb->s_root)
+               return 0;
+
+       if (!fc->sync_fs)
+               return 0;
+
+       memset(&inarg, 0, sizeof(inarg));
+       args.in_numargs = 1;
+       args.in_args[0].size = sizeof(inarg);
+       args.in_args[0].value = &inarg;
+       args.opcode = FUSE_SYNCFS;
+       args.nodeid = get_node_id(sb->s_root->d_inode);
+       args.out_numargs = 0;
+
+       err = fuse_simple_request(fm, &args);
+       if (err == -ENOSYS) {
+               fc->sync_fs = 0;
+               err = 0;
+       }
+
+       return err;
+}
+
 enum {
        OPT_SOURCE,
        OPT_SUBTYPE,
@@ -712,6 +751,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm,
        fc->pid_ns = get_pid_ns(task_active_pid_ns(current));
        fc->user_ns = get_user_ns(user_ns);
        fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
+       fc->max_pages_limit = FUSE_MAX_MAX_PAGES;
 
        INIT_LIST_HEAD(&fc->mounts);
        list_add(&fm->fc_entry, &fc->mounts);
@@ -872,14 +912,13 @@ static struct dentry *fuse_get_parent(struct dentry *child)
        struct inode *inode;
        struct dentry *parent;
        struct fuse_entry_out outarg;
-       const struct qstr name = QSTR_INIT("..", 2);
        int err;
 
        if (!fc->export_support)
                return ERR_PTR(-ESTALE);
 
        err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode),
-                              &name, &outarg, &inode);
+                              &dotdot_name, &outarg, &inode);
        if (err) {
                if (err == -ENOENT)
                        return ERR_PTR(-ESTALE);
@@ -909,6 +948,7 @@ static const struct super_operations fuse_super_operations = {
        .put_super      = fuse_put_super,
        .umount_begin   = fuse_umount_begin,
        .statfs         = fuse_statfs,
+       .sync_fs        = fuse_sync_fs,
        .show_options   = fuse_show_options,
 };
 
@@ -1040,7 +1080,7 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
                                fc->abort_err = 1;
                        if (arg->flags & FUSE_MAX_PAGES) {
                                fc->max_pages =
-                                       min_t(unsigned int, FUSE_MAX_MAX_PAGES,
+                                       min_t(unsigned int, fc->max_pages_limit,
                                        max_t(unsigned int, arg->max_pages, 1));
                        }
                        if (IS_ENABLED(CONFIG_FUSE_DAX) &&
@@ -1052,6 +1092,8 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
                                fc->handle_killpriv_v2 = 1;
                                fm->sb->s_flags |= SB_NOSEC;
                        }
+                       if (arg->flags & FUSE_SETXATTR_EXT)
+                               fc->setxattr_ext = 1;
                } else {
                        ra_pages = fc->max_read / PAGE_SIZE;
                        fc->no_lock = 1;
@@ -1095,7 +1137,7 @@ void fuse_send_init(struct fuse_mount *fm)
                FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL |
                FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS |
                FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA |
-               FUSE_HANDLE_KILLPRIV_V2;
+               FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT;
 #ifdef CONFIG_FUSE_DAX
        if (fm->fc->dax)
                ia->in.flags |= FUSE_MAP_ALIGNMENT;
@@ -1311,6 +1353,22 @@ int fuse_fill_super_submount(struct super_block *sb,
        return 0;
 }
 
+static int fuse_get_tree_submount(struct fs_context *fsc)
+{
+       return 0;
+}
+
+static const struct fs_context_operations fuse_context_submount_ops = {
+       .get_tree       = fuse_get_tree_submount,
+};
+
+int fuse_init_fs_context_submount(struct fs_context *fsc)
+{
+       fsc->ops = &fuse_context_submount_ops;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(fuse_init_fs_context_submount);
+
 int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
 {
        struct fuse_dev *fud = NULL;