Skip to content

Commit

Permalink
orangefs: ensure the userspace component is unmounted if mount fails
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Martin Brandenburg authored and Mike Marshall committed Apr 26, 2017
1 parent 53950ef commit 9d286b0
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 36 deletions.
35 changes: 0 additions & 35 deletions fs/orangefs/orangefs-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
28 changes: 27 additions & 1 deletion fs/orangefs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand All @@ -554,6 +576,7 @@ struct dentry *orangefs_mount(struct file_system_type *fst,

void orangefs_kill_sb(struct super_block *sb)
{
int r;
gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_kill_sb: called\n");

/* provided sb cleanup */
Expand All @@ -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 */
Expand Down

0 comments on commit 9d286b0

Please sign in to comment.