diff --git a/kmod/src/format.h b/kmod/src/format.h index 6f80059e..e7bbcb59 100644 --- a/kmod/src/format.h +++ b/kmod/src/format.h @@ -149,6 +149,7 @@ struct scoutfs_super_block { struct scoutfs_block_header hdr; __le64 id; __u8 uuid[SCOUTFS_UUID_BYTES]; + __le64 next_ino; __le64 total_blocks; __le32 buddy_blocks; __le32 buddy_sweep_bit; diff --git a/kmod/src/inode.c b/kmod/src/inode.c index 8ce039b3..1b37381f 100644 --- a/kmod/src/inode.c +++ b/kmod/src/inode.c @@ -249,6 +249,27 @@ void scoutfs_update_inode_item(struct inode *inode) trace_scoutfs_update_inode(inode); } +static int alloc_ino(struct super_block *sb, u64 *ino) +{ + struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); + struct scoutfs_super_block *super = &sbi->super; + int ret; + + spin_lock(&sbi->next_ino_lock); + + if (super->next_ino == 0) { + ret = -ENOSPC; + } else { + *ino = le64_to_cpu(super->next_ino); + le64_add_cpu(&super->next_ino, 1); + ret = 0; + } + + spin_unlock(&sbi->next_ino_lock); + + return ret; +} + /* * Allocate and initialize a new inode. The caller is responsible for * creating links to it and updating it. @dir can be null. @@ -256,22 +277,26 @@ void scoutfs_update_inode_item(struct inode *inode) struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir, umode_t mode, dev_t rdev) { - struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); DECLARE_SCOUTFS_BTREE_CURSOR(curs); struct scoutfs_inode_info *ci; struct scoutfs_key key; struct inode *inode; + u64 ino; int ret; + ret = alloc_ino(sb, &ino); + if (ret) + return ERR_PTR(ret); + inode = new_inode(sb); if (!inode) return ERR_PTR(-ENOMEM); ci = SCOUTFS_I(inode); - ci->ino = atomic64_inc_return(&sbi->next_ino); + ci->ino = ino; get_random_bytes(&ci->salt, sizeof(ci->salt)); - inode->i_ino = ci->ino; + inode->i_ino = ino; /* XXX overflow */ inode_init_owner(inode, dir, mode); inode_set_bytes(inode, 0); inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; diff --git a/kmod/src/super.c b/kmod/src/super.c index e8354d5e..1867d1f8 100644 --- a/kmod/src/super.c +++ b/kmod/src/super.c @@ -122,11 +122,6 @@ static int read_supers(struct super_block *sb) scoutfs_info(sb, "using super %u with seq %llu", found, le64_to_cpu(sbi->super.hdr.seq)); - /* - * XXX These don't exist in the super yet. They should soon. - */ - atomic64_set(&sbi->next_ino, SCOUTFS_ROOT_INO + 1); - return 0; } @@ -146,6 +141,7 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent) if (!sbi) return -ENOMEM; + spin_lock_init(&sbi->next_ino_lock); spin_lock_init(&sbi->block_lock); INIT_RADIX_TREE(&sbi->block_radix, GFP_NOFS); init_waitqueue_head(&sbi->block_wq); diff --git a/kmod/src/super.h b/kmod/src/super.h index 18c9be86..03226baf 100644 --- a/kmod/src/super.h +++ b/kmod/src/super.h @@ -15,14 +15,14 @@ struct scoutfs_sb_info { struct scoutfs_super_block super; + spinlock_t next_ino_lock; + spinlock_t block_lock; struct radix_tree_root block_radix; wait_queue_head_t block_wq; atomic_t block_writes; int block_write_err; - atomic64_t next_ino; - struct mutex buddy_mutex; struct buddy_alloc *bud;