forked from luck/tmp_suning_uos_patched
orangefs: ensure the userspace component is unmounted if mount fails
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>
This commit is contained in:
parent
53950ef541
commit
9d286b0d82
|
@ -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)) {
|
||||
|
|
|
@ -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 @@ 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 */
|
||||
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue
Block a user