scoutfs: add a node_id lock

A mount's node_id item operations need to be locked.  For now let's
use a lock that's held for the duration of the mount.  It makes
it trivial for us to use it with node_id items but we'll have work
to do if we want to opportunistically get access to other mount's
node_id items while they're still up.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2017-09-28 15:35:40 -07:00
committed by Mark Fasheh
parent 85dbc21dc6
commit 1193fbc9c5
4 changed files with 63 additions and 2 deletions

View File

@@ -190,6 +190,13 @@ static struct ocfs2_lock_res_ops scoutfs_global_lops = {
.flags = 0,
};
static struct ocfs2_lock_res_ops scoutfs_node_id_lops = {
.get_osb = get_ino_lock_osb,
/* XXX: .check_downconvert that queries the item cache for dirty items */
.downconvert_worker = ino_lock_downconvert,
.flags = 0,
};
static struct scoutfs_lock *alloc_scoutfs_lock(struct super_block *sb,
struct scoutfs_lock_name *lock_name,
struct ocfs2_lock_res_ops *type,
@@ -671,6 +678,48 @@ int scoutfs_lock_inode_index(struct super_block *sb, int mode,
&scoufs_ino_index_lops, &start, &end, ret_lock);
}
/*
* The node_id lock protects a mount's private persistent items in the
* node_id zone. It's held for the duration of the mount. It lets the
* mount modify the node_id items at will and signals to other mounts
* that we're still alive and our node_id items shouldn't be reclaimed.
*
* Being held for the entire mount prevents other nodes from reclaiming
* our items, like free blocks, when it would make sense for them to be
* able to. Maybe we have a bunch free and they're trying to allocate
* and are getting ENOSPC.
*/
int scoutfs_lock_node_id(struct super_block *sb, int mode, int flags,
u64 node_id, struct scoutfs_lock **lock)
{
struct scoutfs_lock_name lock_name;
struct scoutfs_orphan_key start_okey;
struct scoutfs_orphan_key end_okey;
struct scoutfs_key_buf start;
struct scoutfs_key_buf end;
lock_name.scope = SCOUTFS_LOCK_SCOPE_FS_ITEMS;
lock_name.zone = SCOUTFS_NODE_ZONE;
lock_name.type = 0;
lock_name.first = cpu_to_le64(node_id);
lock_name.second = 0;
start_okey.zone = SCOUTFS_NODE_ZONE;
start_okey.node_id = cpu_to_be64(node_id);
start_okey.type = 0;
start_okey.ino = 0;
scoutfs_key_init(&start, &start_okey, sizeof(start_okey));
end_okey.zone = SCOUTFS_NODE_ZONE;
end_okey.node_id = cpu_to_be64(node_id);
end_okey.type = ~0;
end_okey.ino = cpu_to_be64(~0ULL);
scoutfs_key_init(&end, &end_okey, sizeof(end_okey));
return lock_name_keys(sb, mode, flags, &lock_name,
&scoutfs_node_id_lops, &start, &end, lock);
}
void scoutfs_unlock(struct super_block *sb, struct scoutfs_lock *lock,
int level)
{

View File

@@ -46,6 +46,8 @@ int scoutfs_lock_inodes(struct super_block *sb, int mode, int flags,
struct inode *d, struct scoutfs_lock **D_lock);
int scoutfs_lock_global(struct super_block *sb, int mode, int flags, int type,
struct scoutfs_lock **lock);
int scoutfs_lock_node_id(struct super_block *sb, int mode, int flags,
u64 node_id, struct scoutfs_lock **lock);
void scoutfs_unlock(struct super_block *sb, struct scoutfs_lock *lock,
int level);

View File

@@ -290,6 +290,8 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
*/
ret = scoutfs_server_setup(sb) ?:
scoutfs_client_setup(sb);
scoutfs_lock_node_id(sb, DLM_LOCK_EX, 0, sbi->node_id,
&sbi->node_id_lock);
if (ret)
goto out;
@@ -313,8 +315,11 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
// scoutfs_scan_orphans(sb);
ret = 0;
out:
if (ret)
scoutfs_server_destroy(sb);
if (ret) {
scoutfs_server_destroy(sb);
scoutfs_unlock(sb, sbi->node_id_lock, DLM_LOCK_EX);
sbi->node_id_lock = NULL;
}
return ret;
}
@@ -342,6 +347,9 @@ static void scoutfs_kill_sb(struct super_block *sb)
kill_block_super(sb);
if (sbi) {
scoutfs_unlock(sb, sbi->node_id_lock, DLM_LOCK_EX);
sbi->node_id_lock = NULL;
scoutfs_lock_destroy(sb);
scoutfs_client_destroy(sb);
scoutfs_server_destroy(sb);

View File

@@ -23,7 +23,9 @@ struct btree_info;
struct scoutfs_sb_info {
struct super_block *sb;
/* assigned once at the start of each mount, read-only */
u64 node_id;
struct scoutfs_lock *node_id_lock;
struct scoutfs_super_block super;