Module Name:    src
Committed By:   hannken
Date:           Mon Jun 17 08:07:27 UTC 2019

Modified Files:
        src/sys/kern: vfs_trans.c

Log Message:
Add an owner field to fstrans mount info and use it to hold
the thread currently suspending this mount.

Remove now unneeded state FSTRANS_EXCL.

It is now possible to suspend a file system from a thread
already holding fstrans locks.  Use with care ...


To generate a diff of this commit:
cvs rdiff -u -r1.60 -r1.61 src/sys/kern/vfs_trans.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/vfs_trans.c
diff -u src/sys/kern/vfs_trans.c:1.60 src/sys/kern/vfs_trans.c:1.61
--- src/sys/kern/vfs_trans.c:1.60	Mon May 13 08:16:56 2019
+++ src/sys/kern/vfs_trans.c	Mon Jun 17 08:07:27 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_trans.c,v 1.60 2019/05/13 08:16:56 hannken Exp $	*/
+/*	$NetBSD: vfs_trans.c,v 1.61 2019/06/17 08:07:27 hannken Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_trans.c,v 1.60 2019/05/13 08:16:56 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_trans.c,v 1.61 2019/06/17 08:07:27 hannken Exp $");
 
 /*
  * File system transaction operations.
@@ -55,8 +55,7 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_trans.c,
 
 enum fstrans_lock_type {
 	FSTRANS_LAZY,			/* Granted while not suspended */
-	FSTRANS_SHARED,			/* Granted while not suspending */
-	FSTRANS_EXCL			/* Internal: exclusive lock */
+	FSTRANS_SHARED			/* Granted while not suspending */
 };
 
 struct fscow_handler {
@@ -83,6 +82,7 @@ struct fstrans_mount_info {
 	bool fmi_cow_change;
 	LIST_HEAD(, fscow_handler) fmi_cow_handler;
 	struct mount *fmi_mount;
+	struct lwp *fmi_owner;
 };
 
 static kmutex_t vfs_suspend_lock;	/* Serialize suspensions. */
@@ -101,7 +101,8 @@ static inline struct fstrans_lwp_info *
     fstrans_get_lwp_info(struct mount *, bool);
 static struct fstrans_lwp_info *fstrans_alloc_lwp_info(struct mount *);
 static inline int _fstrans_start(struct mount *, enum fstrans_lock_type, int);
-static bool grant_lock(const enum fstrans_state, const enum fstrans_lock_type);
+static bool grant_lock(const struct fstrans_mount_info *,
+    const enum fstrans_lock_type);
 static bool state_change_done(const struct fstrans_mount_info *);
 static bool cow_state_change_done(const struct fstrans_mount_info *);
 static void cow_change_enter(struct fstrans_mount_info *);
@@ -233,6 +234,7 @@ fstrans_mount_dtor(struct fstrans_mount_
 
 	KASSERT(fmi->fmi_state == FSTRANS_NORMAL);
 	KASSERT(LIST_FIRST(&fmi->fmi_cow_handler) == NULL);
+	KASSERT(fmi->fmi_owner == NULL);
 
 	KASSERT(fstrans_gone_count > 0);
 	fstrans_gone_count -= 1;
@@ -258,6 +260,7 @@ fstrans_mount(struct mount *mp)
 	LIST_INIT(&newfmi->fmi_cow_handler);
 	newfmi->fmi_cow_change = false;
 	newfmi->fmi_mount = mp;
+	newfmi->fmi_owner = NULL;
 
 	mutex_enter(&fstrans_mount_lock);
 	mp->mnt_transinfo = newfmi;
@@ -433,14 +436,15 @@ fstrans_get_lwp_info(struct mount *mp, b
  * Check if this lock type is granted at this state.
  */
 static bool
-grant_lock(const enum fstrans_state state, const enum fstrans_lock_type type)
+grant_lock(const struct fstrans_mount_info *fmi,
+    const enum fstrans_lock_type type)
 {
 
-	if (__predict_true(state == FSTRANS_NORMAL))
+	if (__predict_true(fmi->fmi_state == FSTRANS_NORMAL))
 		return true;
-	if (type == FSTRANS_EXCL)
+	if (fmi->fmi_owner == curlwp)
 		return true;
-	if  (state == FSTRANS_SUSPENDING && type == FSTRANS_LAZY)
+	if  (fmi->fmi_state == FSTRANS_SUSPENDING && type == FSTRANS_LAZY)
 		return true;
 
 	return false;
@@ -468,14 +472,13 @@ _fstrans_start(struct mount *mp, enum fs
 	fmi = fli->fli_mountinfo;
 
 	if (fli->fli_trans_cnt > 0) {
-		KASSERT(lock_type != FSTRANS_EXCL);
 		fli->fli_trans_cnt += 1;
 
 		return 0;
 	}
 
 	s = pserialize_read_enter();
-	if (__predict_true(grant_lock(fmi->fmi_state, lock_type))) {
+	if (__predict_true(grant_lock(fmi, lock_type))) {
 		fli->fli_trans_cnt = 1;
 		fli->fli_lock_type = lock_type;
 		pserialize_read_exit(s);
@@ -488,7 +491,7 @@ _fstrans_start(struct mount *mp, enum fs
 		return EBUSY;
 
 	mutex_enter(&fstrans_lock);
-	while (! grant_lock(fmi->fmi_state, lock_type))
+	while (! grant_lock(fmi, lock_type))
 		cv_wait(&fstrans_state_cv, &fstrans_lock);
 	fli->fli_trans_cnt = 1;
 	fli->fli_lock_type = lock_type;
@@ -572,15 +575,14 @@ int
 fstrans_is_owner(struct mount *mp)
 {
 	struct fstrans_lwp_info *fli;
+	struct fstrans_mount_info *fmi;
 
 	KASSERT(mp != dead_rootmount);
 
 	fli = fstrans_get_lwp_info(mp, true);
+	fmi = fli->fli_mountinfo;
 
-	if (fli->fli_trans_cnt == 0)
-		return 0;
-
-	return (fli->fli_lock_type == FSTRANS_EXCL);
+	return (fmi->fmi_owner == curlwp);
 }
 
 /*
@@ -598,7 +600,9 @@ state_change_done(const struct fstrans_m
 			continue;
 		if (fli->fli_trans_cnt == 0)
 			continue;
-		if (grant_lock(fmi->fmi_state, fli->fli_lock_type))
+		if (fli->fli_self == curlwp)
+			continue;
+		if (grant_lock(fmi, fli->fli_lock_type))
 			continue;
 
 		return false;
@@ -642,15 +646,18 @@ fstrans_setstate(struct mount *mp, enum 
 			break;
 		}
 	}
-	cv_broadcast(&fstrans_state_cv);
-	mutex_exit(&fstrans_lock);
-
 	if (old_state != new_state) {
-		if (old_state == FSTRANS_NORMAL)
-			_fstrans_start(mp, FSTRANS_EXCL, 1);
-		if (new_state == FSTRANS_NORMAL)
-			fstrans_done(mp);
+		if (old_state == FSTRANS_NORMAL) {
+			KASSERT(fmi->fmi_owner == NULL);
+			fmi->fmi_owner = curlwp;
+		}
+		if (new_state == FSTRANS_NORMAL) {
+			KASSERT(fmi->fmi_owner == curlwp);
+			fmi->fmi_owner = NULL;
+		}
 	}
+	cv_broadcast(&fstrans_state_cv);
+	mutex_exit(&fstrans_lock);
 
 	return error;
 }
@@ -976,9 +983,6 @@ fstrans_print_lwp(struct proc *p, struct
 			case FSTRANS_SHARED:
 				printf(" shared");
 				break;
-			case FSTRANS_EXCL:
-				printf(" excl");
-				break;
 			default:
 				printf(" %#x", fli->fli_lock_type);
 				break;
@@ -1004,6 +1008,7 @@ fstrans_print_mount(struct mount *mp, in
 		printf("(null)\n");
 		return;
 	}
+	printf("owner %p ", fmi->fmi_owner);
 	switch (fmi->fmi_state) {
 	case FSTRANS_NORMAL:
 		printf("state normal\n");

Reply via email to