Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9d286b0d authored by Martin Brandenburg's avatar Martin Brandenburg Committed by Mike Marshall
Browse files

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: default avatarMartin Brandenburg <martin@omnibond.com>
Signed-off-by: default avatarMike Marshall <hubcap@omnibond.com>
parent 53950ef5
Loading
Loading
Loading
Loading
+0 −35
Original line number Diff line number Diff line
@@ -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)) {
+27 −1
Original line number Diff line number Diff line
@@ -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 */