scoutfs: add lock arg to _item_create()

scoutfs_item_create() hasn't been working with lock coverage.  It
wouldn't return -ENOENT if it didn't have the lock cached.  It would
create items outside lock coverate so they wouldn't be invalidated and
re-read if another node modified the item.

Add a lock arg and teach it to populate the cache so that it's correctly
consistent.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2017-10-05 11:57:14 -07:00
committed by Mark Fasheh
parent 47f5946c90
commit 0aa16f5ef6
5 changed files with 35 additions and 20 deletions

View File

@@ -373,7 +373,7 @@ static int set_segno_free(struct super_block *sb, u64 segno)
if (ret == -ENOENT) {
memset(&frb, 0, sizeof(frb));
set_bit_le(bit, &frb);
ret = scoutfs_item_create(sb, &key, val);
ret = scoutfs_item_create(sb, &key, val, lock);
goto out;
}
@@ -399,6 +399,7 @@ static int create_blkno_free(struct super_block *sb, u64 blkno,
struct scoutfs_free_bits_key *fbk)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits frb;
SCOUTFS_DECLARE_KVEC(val);
int bit;
@@ -411,7 +412,7 @@ static int create_blkno_free(struct super_block *sb, u64 blkno,
memset(&frb, 0xff, sizeof(frb));
clear_bit_le(bit, frb.bits);
return scoutfs_item_create(sb, key, val);
return scoutfs_item_create(sb, key, val, lock);
}
/*
@@ -507,7 +508,7 @@ static int set_blkno_free(struct super_block *sb, u64 blkno)
if (ret == -ENOENT) {
memset(&frb, 0, sizeof(frb));
set_bit_le(bit, &frb);
ret = scoutfs_item_create(sb, &key, val);
ret = scoutfs_item_create(sb, &key, val, lock);
goto out;
}
@@ -961,7 +962,7 @@ static int find_alloc_block(struct super_block *sb, struct block_mapping *map,
if (map_exists)
ret = scoutfs_item_update(sb, map_key, val, data_lock->end);
else
ret = scoutfs_item_create(sb, map_key, val);
ret = scoutfs_item_create(sb, map_key, val, data_lock);
if (ret)
goto out;

View File

@@ -439,7 +439,7 @@ static int add_entry_items(struct super_block *sb, u64 dir_ino, u64 pos,
scoutfs_kvec_init(val, &dent, sizeof(dent));
ret = scoutfs_item_create(sb, ent_key, val);
ret = scoutfs_item_create(sb, ent_key, val, dir_lock);
if (ret)
goto out;
del_ent = true;
@@ -448,7 +448,7 @@ static int add_entry_items(struct super_block *sb, u64 dir_ino, u64 pos,
init_readdir_key(&rdir_key, &rkey, dir_ino, pos);
scoutfs_kvec_init(val, &dent, sizeof(dent), (char *)name, name_len);
ret = scoutfs_item_create(sb, &rdir_key, val);
ret = scoutfs_item_create(sb, &rdir_key, val, dir_lock);
if (ret)
goto out;
del_rdir = true;
@@ -460,7 +460,7 @@ static int add_entry_items(struct super_block *sb, u64 dir_ino, u64 pos,
goto out;
}
ret = scoutfs_item_create(sb, lb_key, NULL);
ret = scoutfs_item_create(sb, lb_key, NULL, inode_lock);
out:
if (ret < 0) {
if (del_ent)
@@ -899,7 +899,7 @@ static int symlink_item_ops(struct super_block *sb, int op, u64 ino,
scoutfs_kvec_init(val, (void *)target, bytes);
if (op == SYM_CREATE)
ret = scoutfs_item_create(sb, &key, val);
ret = scoutfs_item_create(sb, &key, val, lock);
else if (op == SYM_LOOKUP)
ret = scoutfs_item_lookup_exact(sb, &key, val, bytes,
lock);

View File

@@ -639,7 +639,7 @@ static int update_index_items(struct super_block *sb,
scoutfs_key_init(&ins, &ins_ikey, sizeof(ins_ikey));
ins_lock = find_index_lock(lock_list, type, major, minor, ino);
ret = scoutfs_item_create(sb, &ins, NULL);
ret = scoutfs_item_create(sb, &ins, NULL, ins_lock);
if (ret || !will_del_index(si, type, major, minor))
return ret;
@@ -1188,7 +1188,7 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
scoutfs_inode_init_key(&key, &ikey, scoutfs_ino(inode));
scoutfs_kvec_init(val, &sinode, sizeof(sinode));
ret = scoutfs_item_create(sb, &key, val);
ret = scoutfs_item_create(sb, &key, val, lock);
if (ret) {
iput(inode);
return ERR_PTR(ret);
@@ -1394,6 +1394,7 @@ int scoutfs_orphan_inode(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_orphan_key okey;
struct scoutfs_key_buf key;
int ret;
@@ -1402,7 +1403,7 @@ int scoutfs_orphan_inode(struct inode *inode)
init_orphan_key(&key, &okey, sbi->node_id, scoutfs_ino(inode));
ret = scoutfs_item_create(sb, &key, NULL);
ret = scoutfs_item_create(sb, &key, NULL, lock);
return ret;
}

View File

@@ -1062,7 +1062,7 @@ int scoutfs_item_next_same(struct super_block *sb, struct scoutfs_key_buf *key,
* XXX but it doesn't read.. is that weird? Seems weird.
*/
int scoutfs_item_create(struct super_block *sb, struct scoutfs_key_buf *key,
struct kvec *val)
struct kvec *val, struct scoutfs_lock *lock)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct item_cache *cac = sbi->item_cache;
@@ -1077,13 +1077,26 @@ int scoutfs_item_create(struct super_block *sb, struct scoutfs_key_buf *key,
if (!item)
return -ENOMEM;
spin_lock_irqsave(&cac->lock, flags);
ret = insert_item(sb, cac, item, false, false);
if (!ret) {
scoutfs_inc_counter(sb, item_create);
mark_item_dirty(sb, cac, item);
}
spin_unlock_irqrestore(&cac->lock, flags);
if (WARN_ON_ONCE(!lock_coverage(lock, key, WRITE)))
return -EINVAL;
do {
spin_lock_irqsave(&cac->lock, flags);
if (!check_range(sb, &cac->ranges, key, NULL)) {
ret = -ENODATA;
} else {
ret = insert_item(sb, cac, item, false, false);
if (!ret) {
scoutfs_inc_counter(sb, item_create);
mark_item_dirty(sb, cac, item);
}
}
spin_unlock_irqrestore(&cac->lock, flags);
} while (ret == -ENODATA &&
(ret = scoutfs_manifest_read_items(sb, key, lock->end)) == 0);
if (ret)
free_item(sb, item);

View File

@@ -29,7 +29,7 @@ int scoutfs_item_next_same(struct super_block *sb, struct scoutfs_key_buf *key,
struct scoutfs_key_buf *last, struct kvec *val,
struct scoutfs_lock *lock);
int scoutfs_item_create(struct super_block *sb, struct scoutfs_key_buf *key,
struct kvec *val);
struct kvec *val, struct scoutfs_lock *lock);
int scoutfs_item_dirty(struct super_block *sb, struct scoutfs_key_buf *key,
struct scoutfs_lock *lock);
int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key,