mirror of
https://github.com/versity/scoutfs.git
synced 2026-01-09 13:23:14 +00:00
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:
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user