Skip to content

Commit 1ec1688

Browse files
Martin Brandenburgtorvalds
Martin Brandenburg
authored andcommitted
orangefs: free superblock when mount fails
Otherwise lockdep says: [ 1337.483798] ================================================ [ 1337.483999] [ BUG: lock held when returning to user space! ] [ 1337.484252] 4.11.0-rc6 rib#19 Not tainted [ 1337.484423] ------------------------------------------------ [ 1337.484626] mount/14766 is leaving the kernel with locks still held! [ 1337.484841] 1 lock held by mount/14766: [ 1337.485017] #0: (&type->s_umount_key#33/1){+.+.+.}, at: [<ffffffff8124171f>] sget_userns+0x2af/0x520 Caught by xfstests generic/413 which tried to mount with the unsupported mount option dax. Then xfstests generic/422 ran sync which deadlocks. Signed-off-by: Martin Brandenburg <[email protected]> Acked-by: Mike Marshall <[email protected]> Cc: [email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent c0eb027 commit 1ec1688

File tree

3 files changed

+24
-9
lines changed

3 files changed

+24
-9
lines changed

fs/orangefs/devorangefs-req.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,19 @@ static ssize_t orangefs_devreq_read(struct file *file,
208208
continue;
209209
/*
210210
* Skip ops whose filesystem we don't know about unless
211-
* it is being mounted.
211+
* it is being mounted or unmounted. It is possible for
212+
* a filesystem we don't know about to be unmounted if
213+
* it fails to mount in the kernel after userspace has
214+
* been sent the mount request.
212215
*/
213216
/* XXX: is there a better way to detect this? */
214217
} else if (ret == -1 &&
215218
!(op->upcall.type ==
216219
ORANGEFS_VFS_OP_FS_MOUNT ||
217220
op->upcall.type ==
218-
ORANGEFS_VFS_OP_GETATTR)) {
221+
ORANGEFS_VFS_OP_GETATTR ||
222+
op->upcall.type ==
223+
ORANGEFS_VFS_OP_FS_UMOUNT)) {
219224
gossip_debug(GOSSIP_DEV_DEBUG,
220225
"orangefs: skipping op tag %llu %s\n",
221226
llu(op->tag), get_opname_string(op));

fs/orangefs/orangefs-kernel.h

+1
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ struct orangefs_sb_info_s {
249249
char devname[ORANGEFS_MAX_SERVER_ADDR_LEN];
250250
struct super_block *sb;
251251
int mount_pending;
252+
int no_list;
252253
struct list_head list;
253254
};
254255

fs/orangefs/super.c

+16-7
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ struct dentry *orangefs_mount(struct file_system_type *fst,
493493

494494
if (ret) {
495495
d = ERR_PTR(ret);
496-
goto free_op;
496+
goto free_sb_and_op;
497497
}
498498

499499
/*
@@ -519,6 +519,9 @@ struct dentry *orangefs_mount(struct file_system_type *fst,
519519
spin_unlock(&orangefs_superblocks_lock);
520520
op_release(new_op);
521521

522+
/* Must be removed from the list now. */
523+
ORANGEFS_SB(sb)->no_list = 0;
524+
522525
if (orangefs_userspace_version >= 20906) {
523526
new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES);
524527
if (!new_op)
@@ -533,6 +536,10 @@ struct dentry *orangefs_mount(struct file_system_type *fst,
533536

534537
return dget(sb->s_root);
535538

539+
free_sb_and_op:
540+
/* Will call orangefs_kill_sb with sb not in list. */
541+
ORANGEFS_SB(sb)->no_list = 1;
542+
deactivate_locked_super(sb);
536543
free_op:
537544
gossip_err("orangefs_mount: mount request failed with %d\n", ret);
538545
if (ret == -EINVAL) {
@@ -558,12 +565,14 @@ void orangefs_kill_sb(struct super_block *sb)
558565
*/
559566
orangefs_unmount_sb(sb);
560567

561-
/* remove the sb from our list of orangefs specific sb's */
562-
563-
spin_lock(&orangefs_superblocks_lock);
564-
__list_del_entry(&ORANGEFS_SB(sb)->list); /* not list_del_init */
565-
ORANGEFS_SB(sb)->list.prev = NULL;
566-
spin_unlock(&orangefs_superblocks_lock);
568+
if (!ORANGEFS_SB(sb)->no_list) {
569+
/* remove the sb from our list of orangefs specific sb's */
570+
spin_lock(&orangefs_superblocks_lock);
571+
/* not list_del_init */
572+
__list_del_entry(&ORANGEFS_SB(sb)->list);
573+
ORANGEFS_SB(sb)->list.prev = NULL;
574+
spin_unlock(&orangefs_superblocks_lock);
575+
}
567576

568577
/*
569578
* make sure that ORANGEFS_DEV_REMOUNT_ALL loop that might've seen us

0 commit comments

Comments
 (0)