mirror of
https://github.com/versity/scoutfs.git
synced 2026-08-20 22:26:42 +00:00
scoutfs: have per-fs inode nr allocators
We had previously seen lock contention between mounts that were either resolving paths by looking up entries in directories or writing xattrs in file inodes as they did archiving work. The previous attempt to avoid this contention was to give each directory its own inode number allocator which ensured that inodes created for entries in the directory wouldn't share lock groups with inodes in other directories. But this creates the problem of operating on few files per lock for reasonably small directories. It also creates more server commits as each new directory gets its inode allocation reservation. The fix is to have mount-wide seperate allocators for directories and for everything else. This puts directories and files in seperate groups and locks, regardless of directory population. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
+15
-8
@@ -47,9 +47,17 @@
|
||||
* - describe data locking size problems
|
||||
*/
|
||||
|
||||
struct inode_allocator {
|
||||
spinlock_t lock;
|
||||
u64 ino;
|
||||
u64 nr;
|
||||
};
|
||||
|
||||
struct inode_sb_info {
|
||||
spinlock_t writeback_lock;
|
||||
struct rb_root writeback_inodes;
|
||||
struct inode_allocator dir_ino_alloc;
|
||||
struct inode_allocator ino_alloc;
|
||||
};
|
||||
|
||||
#define DECLARE_INODE_SB_INFO(sb, name) \
|
||||
@@ -74,7 +82,6 @@ static void scoutfs_inode_ctor(void *obj)
|
||||
init_waitqueue_head(&ci->data_waitq.waitq);
|
||||
init_rwsem(&ci->xattr_rwsem);
|
||||
RB_CLEAR_NODE(&ci->writeback_node);
|
||||
spin_lock_init(&ci->ino_alloc.lock);
|
||||
|
||||
inode_init_once(&ci->inode);
|
||||
}
|
||||
@@ -682,8 +689,6 @@ struct inode *scoutfs_iget(struct super_block *sb, u64 ino)
|
||||
/* XXX ensure refresh, instead clear in drop_inode? */
|
||||
si = SCOUTFS_I(inode);
|
||||
atomic64_set(&si->last_refreshed, 0);
|
||||
si->ino_alloc.ino = 0;
|
||||
si->ino_alloc.nr = 0;
|
||||
|
||||
ret = scoutfs_inode_refresh(inode, lock, 0);
|
||||
if (ret) {
|
||||
@@ -1322,14 +1327,16 @@ u64 scoutfs_last_ino(struct super_block *sb)
|
||||
* minimize that loss while still being large enough for typical
|
||||
* directory file counts.
|
||||
*/
|
||||
int scoutfs_alloc_ino(struct inode *parent, u64 *ino_ret)
|
||||
int scoutfs_alloc_ino(struct super_block *sb, bool is_dir, u64 *ino_ret)
|
||||
{
|
||||
struct scoutfs_inode_allocator *ia = &SCOUTFS_I(parent)->ino_alloc;
|
||||
struct super_block *sb = parent->i_sb;
|
||||
DECLARE_INODE_SB_INFO(sb, inf);
|
||||
struct inode_allocator *ia;
|
||||
u64 ino;
|
||||
u64 nr;
|
||||
int ret;
|
||||
|
||||
ia = is_dir ? &inf->dir_ino_alloc : &inf->ino_alloc;
|
||||
|
||||
spin_lock(&ia->lock);
|
||||
|
||||
if (ia->nr == 0) {
|
||||
@@ -1385,8 +1392,6 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
|
||||
ci->have_item = false;
|
||||
atomic64_set(&ci->last_refreshed, lock->refresh_gen);
|
||||
ci->flags = 0;
|
||||
ci->ino_alloc.ino = 0;
|
||||
ci->ino_alloc.nr = 0;
|
||||
|
||||
scoutfs_inode_set_meta_seq(inode);
|
||||
scoutfs_inode_set_data_seq(inode);
|
||||
@@ -1725,6 +1730,8 @@ int scoutfs_inode_setup(struct super_block *sb)
|
||||
|
||||
spin_lock_init(&inf->writeback_lock);
|
||||
inf->writeback_inodes = RB_ROOT;
|
||||
spin_lock_init(&inf->dir_ino_alloc.lock);
|
||||
spin_lock_init(&inf->ino_alloc.lock);
|
||||
|
||||
sbi->inode_sb_info = inf;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user