diff --git a/kmod/src/inode.c b/kmod/src/inode.c index 42761a3f..e0e11e59 100644 --- a/kmod/src/inode.c +++ b/kmod/src/inode.c @@ -82,6 +82,7 @@ static void scoutfs_inode_ctor(void *obj) init_waitqueue_head(&si->data_waitq.waitq); init_rwsem(&si->xattr_rwsem); RB_CLEAR_NODE(&si->writeback_node); + scoutfs_lock_init_coverage(&si->ino_lock_cov); inode_init_once(&si->inode); } @@ -141,12 +142,15 @@ static void remove_writeback_inode(struct inode_sb_info *inf, void scoutfs_destroy_inode(struct inode *inode) { + struct scoutfs_inode_info *si = SCOUTFS_I(inode); DECLARE_INODE_SB_INFO(inode->i_sb, inf); spin_lock(&inf->writeback_lock); remove_writeback_inode(inf, SCOUTFS_I(inode)); spin_unlock(&inf->writeback_lock); + scoutfs_lock_del_coverage(inode->i_sb, &si->ino_lock_cov); + call_rcu(&inode->i_rcu, scoutfs_i_callback); } @@ -307,6 +311,7 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock, if (ret == 0) { load_inode(inode, &sinode); atomic64_set(&si->last_refreshed, refresh_gen); + scoutfs_lock_add_coverage(sb, lock, &si->ino_lock_cov); } } else { ret = 0; @@ -1384,6 +1389,7 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir, si->next_xattr_id = 0; si->have_item = false; atomic64_set(&si->last_refreshed, lock->refresh_gen); + scoutfs_lock_add_coverage(sb, lock, &si->ino_lock_cov); si->flags = 0; scoutfs_inode_set_meta_seq(inode); diff --git a/kmod/src/inode.h b/kmod/src/inode.h index ad517752..60213d73 100644 --- a/kmod/src/inode.h +++ b/kmod/src/inode.h @@ -51,6 +51,8 @@ struct scoutfs_inode_info { struct rw_semaphore xattr_rwsem; struct rb_node writeback_node; + struct scoutfs_lock_coverage ino_lock_cov; + struct inode inode; }; diff --git a/kmod/src/lock.c b/kmod/src/lock.c index 10d95507..7bddb762 100644 --- a/kmod/src/lock.c +++ b/kmod/src/lock.c @@ -127,15 +127,19 @@ static bool lock_modes_match(int granted, int requested) */ static void invalidate_inode(struct super_block *sb, u64 ino) { + struct scoutfs_inode_info *si; struct inode *inode; inode = scoutfs_ilookup(sb, ino); if (inode) { + si = SCOUTFS_I(inode); + scoutfs_inc_counter(sb, lock_invalidate_inode); if (S_ISREG(inode->i_mode)) { truncate_inode_pages(inode->i_mapping, 0); scoutfs_data_wait_changed(inode); } + iput(inode); } } @@ -172,6 +176,16 @@ static int lock_invalidate(struct super_block *sb, struct scoutfs_lock *lock, /* have to invalidate if we're not in the only usable case */ if (!(prev == SCOUTFS_LOCK_WRITE && mode == SCOUTFS_LOCK_READ)) { retry: + /* invalidate inodes before removing coverage */ + if (lock->start.sk_zone == SCOUTFS_FS_ZONE) { + ino = le64_to_cpu(lock->start.ski_ino); + last = le64_to_cpu(lock->end.ski_ino); + while (ino <= last) { + invalidate_inode(sb, ino); + ino++; + } + } + /* remove cov items to tell users that their cache is stale */ spin_lock(&lock->cov_list_lock); list_for_each_entry_safe(cov, tmp, &lock->cov_list, head) { @@ -187,15 +201,6 @@ retry: } spin_unlock(&lock->cov_list_lock); - if (lock->start.sk_zone == SCOUTFS_FS_ZONE) { - ino = le64_to_cpu(lock->start.ski_ino); - last = le64_to_cpu(lock->end.ski_ino); - while (ino <= last) { - invalidate_inode(sb, ino); - ino++; - } - } - scoutfs_item_invalidate(sb, &lock->start, &lock->end); }