]> git.baikalelectronics.ru Git - kernel.git/commitdiff
orangefs: ensure the userspace component is unmounted if mount fails
authorMartin Brandenburg <martin@omnibond.com>
Tue, 25 Apr 2017 19:38:05 +0000 (15:38 -0400)
committerMike Marshall <hubcap@omnibond.com>
Wed, 26 Apr 2017 18:33:00 +0000 (14:33 -0400)
If the mount is aborted after userspace has been asked to mount,
userspace must be told to unmount.

Ordinarily orangefs_kill_sb does the unmount.  However it cannot be
called if the superblock has not been set up.  This is a very narrow
window.

The NULL fs_id is not unmounted.

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
Signed-off-by: Mike Marshall <hubcap@omnibond.com>
fs/orangefs/orangefs-utils.c
fs/orangefs/super.c

index fcbf4e56fd069450f43abf4f3c299e2931b14383..aab6f1842963d3d0e5891900f46fc9eb570e9a4f 100644 (file)
@@ -523,41 +523,6 @@ int orangefs_flush_inode(struct inode *inode)
        return ret;
 }
 
-int orangefs_unmount_sb(struct super_block *sb)
-{
-       int ret = -EINVAL;
-       struct orangefs_kernel_op_s *new_op = NULL;
-
-       gossip_debug(GOSSIP_UTILS_DEBUG,
-                    "orangefs_unmount_sb called on sb %p\n",
-                    sb);
-
-       new_op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
-       if (!new_op)
-               return -ENOMEM;
-       new_op->upcall.req.fs_umount.id = ORANGEFS_SB(sb)->id;
-       new_op->upcall.req.fs_umount.fs_id = ORANGEFS_SB(sb)->fs_id;
-       strncpy(new_op->upcall.req.fs_umount.orangefs_config_server,
-               ORANGEFS_SB(sb)->devname,
-               ORANGEFS_MAX_SERVER_ADDR_LEN);
-
-       gossip_debug(GOSSIP_UTILS_DEBUG,
-                    "Attempting ORANGEFS Unmount via host %s\n",
-                    new_op->upcall.req.fs_umount.orangefs_config_server);
-
-       ret = service_operation(new_op, "orangefs_fs_umount", 0);
-
-       gossip_debug(GOSSIP_UTILS_DEBUG,
-                    "orangefs_unmount: got return value of %d\n", ret);
-       if (ret)
-               sb = ERR_PTR(ret);
-       else
-               ORANGEFS_SB(sb)->mount_pending = 1;
-
-       op_release(new_op);
-       return ret;
-}
-
 void orangefs_make_bad_inode(struct inode *inode)
 {
        if (is_root_handle(inode)) {
index 629d8c917fa679886715360fcfe8f6cee1b5a37f..5c7c273e17ec3b32c3c87d313e2c68eb82bdac84 100644 (file)
@@ -376,6 +376,25 @@ static const struct export_operations orangefs_export_ops = {
        .fh_to_dentry = orangefs_fh_to_dentry,
 };
 
+static int orangefs_unmount(int id, __s32 fs_id, const char *devname)
+{
+       struct orangefs_kernel_op_s *op;
+       int r;
+       op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
+       if (!op)
+               return -ENOMEM;
+       op->upcall.req.fs_umount.id = id;
+       op->upcall.req.fs_umount.fs_id = fs_id;
+       strncpy(op->upcall.req.fs_umount.orangefs_config_server,
+           devname, ORANGEFS_MAX_SERVER_ADDR_LEN);
+       r = service_operation(op, "orangefs_fs_umount", 0);
+       /* Not much to do about an error here. */
+       if (r)
+               gossip_err("orangefs_unmount: service_operation %d\n", r);
+       op_release(op);
+       return r;
+}
+
 static int orangefs_fill_sb(struct super_block *sb,
                struct orangefs_fs_mount_response *fs_mount,
                void *data, int silent)
@@ -484,6 +503,8 @@ struct dentry *orangefs_mount(struct file_system_type *fst,
 
        if (IS_ERR(sb)) {
                d = ERR_CAST(sb);
+               orangefs_unmount(new_op->downcall.resp.fs_mount.id,
+                   new_op->downcall.resp.fs_mount.fs_id, devname);
                goto free_op;
        }
 
@@ -539,6 +560,7 @@ struct dentry *orangefs_mount(struct file_system_type *fst,
 free_sb_and_op:
        /* Will call orangefs_kill_sb with sb not in list. */
        ORANGEFS_SB(sb)->no_list = 1;
+       /* ORANGEFS_VFS_OP_FS_UMOUNT is done by orangefs_kill_sb. */
        deactivate_locked_super(sb);
 free_op:
        gossip_err("orangefs_mount: mount request failed with %d\n", ret);
@@ -554,6 +576,7 @@ free_op:
 
 void orangefs_kill_sb(struct super_block *sb)
 {
+       int r;
        gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_kill_sb: called\n");
 
        /* provided sb cleanup */
@@ -563,7 +586,10 @@ void orangefs_kill_sb(struct super_block *sb)
         * issue the unmount to userspace to tell it to remove the
         * dynamic mount info it has for this superblock
         */
-        orangefs_unmount_sb(sb);
+       r = orangefs_unmount(ORANGEFS_SB(sb)->id, ORANGEFS_SB(sb)->fs_id,
+           ORANGEFS_SB(sb)->devname);
+       if (!r)
+               ORANGEFS_SB(sb)->mount_pending = 1;
 
        if (!ORANGEFS_SB(sb)->no_list) {
                /* remove the sb from our list of orangefs specific sb's */