scoutfs: store next allocated inode in super

The next inode number to be allocated has been stored only in the
in-memory super block and hasn't survived across mounts.  This sometimes
accidentally worked if the tests removed the initial inodes but often
would cause failures when inode allocation returned existing inodes.

This tracks the next inode to allocate in the super block and maintains
it across mounts.  Tests now consistently pass as inode allocations
consistently return free inode numbers.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2016-05-01 09:16:40 -07:00
parent 979a36e175
commit e0f38231b3
4 changed files with 32 additions and 10 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;