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");