aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMartin Brandenburg <martin@omnibond.com>2017-04-14 14:22:41 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-21 03:31:19 -0400
commit975a7ea950c6d9bcb3666505c6ca9df9b404105c (patch)
treec5be296c2ae3ddb80604836ed4ed69e355cfdfe1 /fs
parentd19f745ea3a989f9d037dfbc26abcccfe7710723 (diff)
orangefs: free superblock when mount fails
commit 1ec1688c5360e14dde4094d6acbf7516bf6db37e upstream. Otherwise lockdep says: [ 1337.483798] ================================================ [ 1337.483999] [ BUG: lock held when returning to user space! ] [ 1337.484252] 4.11.0-rc6 #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 <martin@omnibond.com> Acked-by: Mike Marshall <hubcap@omnibond.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/orangefs/devorangefs-req.c9
-rw-r--r--fs/orangefs/orangefs-kernel.h1
-rw-r--r--fs/orangefs/super.c23
3 files changed, 24 insertions, 9 deletions
diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c
index f419dd999581..fe2cbeb90772 100644
--- a/fs/orangefs/devorangefs-req.c
+++ b/fs/orangefs/devorangefs-req.c
@@ -208,14 +208,19 @@ restart:
208 continue; 208 continue;
209 /* 209 /*
210 * Skip ops whose filesystem we don't know about unless 210 * 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.
212 */ 215 */
213 /* XXX: is there a better way to detect this? */ 216 /* XXX: is there a better way to detect this? */
214 } else if (ret == -1 && 217 } else if (ret == -1 &&
215 !(op->upcall.type == 218 !(op->upcall.type ==
216 ORANGEFS_VFS_OP_FS_MOUNT || 219 ORANGEFS_VFS_OP_FS_MOUNT ||
217 op->upcall.type == 220 op->upcall.type ==
218 ORANGEFS_VFS_OP_GETATTR)) { 221 ORANGEFS_VFS_OP_GETATTR ||
222 op->upcall.type ==
223 ORANGEFS_VFS_OP_FS_UMOUNT)) {
219 gossip_debug(GOSSIP_DEV_DEBUG, 224 gossip_debug(GOSSIP_DEV_DEBUG,
220 "orangefs: skipping op tag %llu %s\n", 225 "orangefs: skipping op tag %llu %s\n",
221 llu(op->tag), get_opname_string(op)); 226 llu(op->tag), get_opname_string(op));
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 3bf803d732c5..45dd8f27b2ac 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -249,6 +249,7 @@ struct orangefs_sb_info_s {
249 char devname[ORANGEFS_MAX_SERVER_ADDR_LEN]; 249 char devname[ORANGEFS_MAX_SERVER_ADDR_LEN];
250 struct super_block *sb; 250 struct super_block *sb;
251 int mount_pending; 251 int mount_pending;
252 int no_list;
252 struct list_head list; 253 struct list_head list;
253}; 254};
254 255
diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c
index cd261c8de53a..629d8c917fa6 100644
--- a/fs/orangefs/super.c
+++ b/fs/orangefs/super.c
@@ -493,7 +493,7 @@ struct dentry *orangefs_mount(struct file_system_type *fst,
493 493
494 if (ret) { 494 if (ret) {
495 d = ERR_PTR(ret); 495 d = ERR_PTR(ret);
496 goto free_op; 496 goto free_sb_and_op;
497 } 497 }
498 498
499 /* 499 /*
@@ -519,6 +519,9 @@ struct dentry *orangefs_mount(struct file_system_type *fst,
519 spin_unlock(&orangefs_superblocks_lock); 519 spin_unlock(&orangefs_superblocks_lock);
520 op_release(new_op); 520 op_release(new_op);
521 521
522 /* Must be removed from the list now. */
523 ORANGEFS_SB(sb)->no_list = 0;
524
522 if (orangefs_userspace_version >= 20906) { 525 if (orangefs_userspace_version >= 20906) {
523 new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES); 526 new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES);
524 if (!new_op) 527 if (!new_op)
@@ -533,6 +536,10 @@ struct dentry *orangefs_mount(struct file_system_type *fst,
533 536
534 return dget(sb->s_root); 537 return dget(sb->s_root);
535 538
539free_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);
536free_op: 543free_op:
537 gossip_err("orangefs_mount: mount request failed with %d\n", ret); 544 gossip_err("orangefs_mount: mount request failed with %d\n", ret);
538 if (ret == -EINVAL) { 545 if (ret == -EINVAL) {
@@ -558,12 +565,14 @@ void orangefs_kill_sb(struct super_block *sb)
558 */ 565 */
559 orangefs_unmount_sb(sb); 566 orangefs_unmount_sb(sb);
560 567
561 /* remove the sb from our list of orangefs specific sb's */ 568 if (!ORANGEFS_SB(sb)->no_list) {
562 569 /* remove the sb from our list of orangefs specific sb's */
563 spin_lock(&orangefs_superblocks_lock); 570 spin_lock(&orangefs_superblocks_lock);
564 __list_del_entry(&ORANGEFS_SB(sb)->list); /* not list_del_init */ 571 /* not list_del_init */
565 ORANGEFS_SB(sb)->list.prev = NULL; 572 __list_del_entry(&ORANGEFS_SB(sb)->list);
566 spin_unlock(&orangefs_superblocks_lock); 573 ORANGEFS_SB(sb)->list.prev = NULL;
574 spin_unlock(&orangefs_superblocks_lock);
575 }
567 576
568 /* 577 /*
569 * make sure that ORANGEFS_DEV_REMOUNT_ALL loop that might've seen us 578 * make sure that ORANGEFS_DEV_REMOUNT_ALL loop that might've seen us