From 76cf28b44215d5555a042807eb42317b6cf12590 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Tue, 29 Aug 2017 15:02:04 -0700 Subject: [PATCH] scoutfs: warn if lock with trans held We can't block on a lock while holding the transaction open because that'd stop lock downconversion from syncing to write out items while it is converting from EX. Add a warning if we try to acquire a blocking lock while holding a transaction. Signed-off-by: Zach Brown --- kmod/src/lock.c | 5 +++++ kmod/src/trans.c | 12 ++++++++++++ kmod/src/trans.h | 1 + 3 files changed, 18 insertions(+) diff --git a/kmod/src/lock.c b/kmod/src/lock.c index dd569cbb..c9fc20b4 100644 --- a/kmod/src/lock.c +++ b/kmod/src/lock.c @@ -26,6 +26,7 @@ #include "cmp.h" #include "dlmglue.h" #include "inode.h" +#include "trans.h" #define LN_FMT "%u.%u.%u.%llu.%llu" #define LN_ARG(name) \ @@ -383,6 +384,10 @@ static int lock_name_keys(struct super_block *sb, int mode, int flags, int lkm_flags; int ret; + if (WARN_ON_ONCE(!(flags & SCOUTFS_LKF_TRYLOCK) && + scoutfs_trans_held())) + return -EINVAL; + lock = find_alloc_scoutfs_lock(sb, lock_name, type, start, end); if (!lock) return -ENOMEM; diff --git a/kmod/src/trans.c b/kmod/src/trans.c index e630d0fc..ca05240f 100644 --- a/kmod/src/trans.c +++ b/kmod/src/trans.c @@ -370,6 +370,18 @@ int scoutfs_hold_trans(struct super_block *sb, struct scoutfs_item_count *cnt) return ret; } +/* + * Return true if the current task has a transaction held. That is, + * true if the current transaction can't finish and be written out if + * the current task blocks. + */ +bool scoutfs_trans_held(void) +{ + struct scoutfs_reservation *rsv = current->journal_info; + + return rsv && rsv->magic == SCOUTFS_RESERVATION_MAGIC; +} + void scoutfs_trans_track_item(struct super_block *sb, signed items, signed keys, signed vals) { diff --git a/kmod/src/trans.h b/kmod/src/trans.h index fcf0d376..49db305d 100644 --- a/kmod/src/trans.h +++ b/kmod/src/trans.h @@ -10,6 +10,7 @@ int scoutfs_file_fsync(struct file *file, loff_t start, loff_t end, void scoutfs_trans_restart_sync_deadline(struct super_block *sb); int scoutfs_hold_trans(struct super_block *sb, struct scoutfs_item_count *cnt); +bool scoutfs_trans_held(void); void scoutfs_release_trans(struct super_block *sb); void scoutfs_trans_wake_holders(struct super_block *sb); void scoutfs_trans_track_item(struct super_block *sb, signed items,