fuse: add dedicated filesystem context ops for submounts
[linux-2.6-microblaze.git] / fs / fuse / inode.c
index 393e36b..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,
@@ -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,
 };
 
@@ -1313,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;