From fbffad1d5196fe2d3bec7a40a1ec209218fb6bda Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 25 Oct 2019 11:34:49 -0700 Subject: [PATCH] scoutfs: add initial lock write_version We need a way to compare two items in different log btrees and learn which is the most recent. Each time we grant a new write lock we give it a larger write version. Items store the version of the lock they're written under. Readers can now easily see which item is newer. This is a trivial initial implementation which is not consistent across unmount or server failover. We'll need to recover the greatest write_version from locks during recovery and from log trees as the server starts up. Signed-off-by: Zach Brown --- kmod/src/format.h | 1 + kmod/src/lock.c | 1 + kmod/src/lock.h | 5 +++-- kmod/src/lock_server.c | 8 ++++++++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/kmod/src/format.h b/kmod/src/format.h index a167c5cc..cb804c4e 100644 --- a/kmod/src/format.h +++ b/kmod/src/format.h @@ -726,6 +726,7 @@ struct scoutfs_net_extent_list { struct scoutfs_net_lock { struct scoutfs_key key; + __le64 write_version; __u8 old_mode; __u8 new_mode; } __packed; diff --git a/kmod/src/lock.c b/kmod/src/lock.c index 6397d573..c491ed22 100644 --- a/kmod/src/lock.c +++ b/kmod/src/lock.c @@ -587,6 +587,7 @@ int scoutfs_lock_grant_response(struct super_block *sb, lock->request_pending = 0; lock->mode = nl->new_mode; + lock->write_version = le64_to_cpu(nl->write_version); if (lock_count_match_exists(nl->new_mode, lock->waiters)) extend_grace(sb, lock); diff --git a/kmod/src/lock.h b/kmod/src/lock.h index f61bbe70..a6f8a688 100644 --- a/kmod/src/lock.h +++ b/kmod/src/lock.h @@ -11,8 +11,8 @@ #define SCOUTFS_LOCK_NR_MODES SCOUTFS_LOCK_INVALID /* - * A few fields (start, end, refresh_gen, granted_mode) are referenced - * by code outside lock.c. + * A few fields (start, end, refresh_gen, write_version, granted_mode) + * are referenced by code outside lock.c. */ struct scoutfs_lock { struct super_block *sb; @@ -21,6 +21,7 @@ struct scoutfs_lock { struct rb_node node; struct rb_node range_node; u64 refresh_gen; + u64 write_version; struct list_head lru_head; wait_queue_head_t waitq; struct work_struct shrink_work; diff --git a/kmod/src/lock_server.c b/kmod/src/lock_server.c index 5c393038..2199bb23 100644 --- a/kmod/src/lock_server.c +++ b/kmod/src/lock_server.c @@ -494,6 +494,8 @@ static int process_waiting_requests(struct super_block *sb, struct client_lock_entry *req_tmp; struct client_lock_entry *gr; struct client_lock_entry *gr_tmp; + static atomic64_t write_version = ATOMIC64_INIT(0); + u64 wv; int ret; BUG_ON(!mutex_is_locked(&snode->mutex)); @@ -544,6 +546,12 @@ static int process_waiting_requests(struct super_block *sb, nl.old_mode = SCOUTFS_LOCK_NULL; } + if (nl.new_mode == SCOUTFS_LOCK_WRITE || + nl.new_mode == SCOUTFS_LOCK_WRITE_ONLY) { + wv = atomic64_inc_return(&write_version); + nl.write_version = cpu_to_le64(wv); + } + ret = scoutfs_server_lock_response(sb, req->rid, req->net_id, &nl); if (ret)