mirror of
https://github.com/versity/scoutfs.git
synced 2026-07-23 08:23:15 +00:00
scoutfs: use our locking service
Convert client locking to call the server's lock service instead of using a fs/dlm lockspace. The client code gets some shims to send and receive lock messages to and from the server. Callers use our lock mode constants instead of the DLM's. Locks are now identified by their starting key instead of an additional scoped lock name so that we don't have more mapping structures to track. The global rename lock uses keys that are defined by the format as only used for locking. The biggest change is in the client lock state machine. Instead of calling the dlm and getting callbacks we send messages to our server and get called from incoming message processing. We don't have everything come through a per-lock work queue. Instead we send requests either from the blocking lock caller or from a shrink work queue. Incoming messages are called in the net layer's blocking work contexts so we don't need to do any more work to defer to other contexts. The different processing contexts leads to a slightly different lock life cycle. We refactor and seperate allocation and freeing from tracking and removing locks in data structures. We add a _get and _put to track active use of locks and then async references to locks by holders and requests are tracked seperately. Our lock service's rules are a bit simpler in that we'll only ever send one request at a time and the server will only ever send one request at a time. We do have to do a bit of work to make sure we process back to back grant reponses and invalidation requests from the server. As of this change the lock setup and destruction paths are a little wobbly. They'll be shored up as we add lock recovery between the client and server. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -231,6 +231,55 @@ int scoutfs_client_statfs(struct super_block *sb,
|
||||
sizeof(struct scoutfs_net_statfs));
|
||||
}
|
||||
|
||||
/* process an incoming grant response from the server */
|
||||
static int client_lock_response(struct super_block *sb,
|
||||
struct scoutfs_net_connection *conn,
|
||||
void *resp, unsigned int resp_len,
|
||||
int error, void *data)
|
||||
{
|
||||
if (resp_len != sizeof(struct scoutfs_net_lock))
|
||||
return -EINVAL;
|
||||
|
||||
/* XXX error? */
|
||||
|
||||
return scoutfs_lock_grant_response(sb, resp);
|
||||
}
|
||||
|
||||
/* Send a lock request to the server. */
|
||||
int scoutfs_client_lock_request(struct super_block *sb,
|
||||
struct scoutfs_net_lock *nl)
|
||||
{
|
||||
struct client_info *client = SCOUTFS_SB(sb)->client_info;
|
||||
|
||||
return scoutfs_net_submit_request(sb, client->conn,
|
||||
SCOUTFS_NET_CMD_LOCK,
|
||||
nl, sizeof(*nl),
|
||||
client_lock_response, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Send a lock response to the server. */
|
||||
int scoutfs_client_lock_response(struct super_block *sb, u64 net_id,
|
||||
struct scoutfs_net_lock *nl)
|
||||
{
|
||||
struct client_info *client = SCOUTFS_SB(sb)->client_info;
|
||||
|
||||
return scoutfs_net_response(sb, client->conn, SCOUTFS_NET_CMD_LOCK,
|
||||
net_id, 0, nl, sizeof(*nl));
|
||||
}
|
||||
|
||||
/* The client is receiving a invalidation request from the server */
|
||||
static int client_lock(struct super_block *sb,
|
||||
struct scoutfs_net_connection *conn, u8 cmd, u64 id,
|
||||
void *arg, u16 arg_len)
|
||||
{
|
||||
if (arg_len != sizeof(struct scoutfs_net_lock))
|
||||
return -EINVAL;
|
||||
|
||||
/* XXX error? */
|
||||
|
||||
return scoutfs_lock_invalidate_request(sb, id, arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a greeting response in the client from the server. This is
|
||||
* called for every connected socket on the connection. The first
|
||||
@@ -412,6 +461,7 @@ out:
|
||||
|
||||
static scoutfs_net_request_t client_req_funcs[] = {
|
||||
[SCOUTFS_NET_CMD_COMPACT] = client_compact,
|
||||
[SCOUTFS_NET_CMD_LOCK] = client_lock,
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -17,6 +17,10 @@ int scoutfs_client_get_manifest_root(struct super_block *sb,
|
||||
struct scoutfs_btree_root *root);
|
||||
int scoutfs_client_statfs(struct super_block *sb,
|
||||
struct scoutfs_net_statfs *nstatfs);
|
||||
int scoutfs_client_lock_request(struct super_block *sb,
|
||||
struct scoutfs_net_lock *nl);
|
||||
int scoutfs_client_lock_response(struct super_block *sb, u64 net_id,
|
||||
struct scoutfs_net_lock *nl);
|
||||
|
||||
int scoutfs_client_wait_node_id(struct super_block *sb);
|
||||
int scoutfs_client_setup(struct super_block *sb);
|
||||
|
||||
+13
-10
@@ -82,23 +82,26 @@
|
||||
EXPAND_COUNTER(item_shrink_small_split) \
|
||||
EXPAND_COUNTER(item_shrink_split_range) \
|
||||
EXPAND_COUNTER(lock_alloc) \
|
||||
EXPAND_COUNTER(lock_ast) \
|
||||
EXPAND_COUNTER(lock_ast_edeadlk) \
|
||||
EXPAND_COUNTER(lock_ast_error) \
|
||||
EXPAND_COUNTER(lock_bast) \
|
||||
EXPAND_COUNTER(lock_dlm_call) \
|
||||
EXPAND_COUNTER(lock_dlm_call_error) \
|
||||
EXPAND_COUNTER(lock_free) \
|
||||
EXPAND_COUNTER(lock_grace_enforced) \
|
||||
EXPAND_COUNTER(lock_grace_expired) \
|
||||
EXPAND_COUNTER(lock_grace_elapsed) \
|
||||
EXPAND_COUNTER(lock_grace_extended) \
|
||||
EXPAND_COUNTER(lock_grace_set) \
|
||||
EXPAND_COUNTER(lock_grace_wait) \
|
||||
EXPAND_COUNTER(lock_grant_request) \
|
||||
EXPAND_COUNTER(lock_grant_response) \
|
||||
EXPAND_COUNTER(lock_invalidate_clean_item) \
|
||||
EXPAND_COUNTER(lock_invalidate_coverage) \
|
||||
EXPAND_COUNTER(lock_invalidate_inode) \
|
||||
EXPAND_COUNTER(lock_invalidate_request) \
|
||||
EXPAND_COUNTER(lock_invalidate_response) \
|
||||
EXPAND_COUNTER(lock_lock) \
|
||||
EXPAND_COUNTER(lock_lock_error) \
|
||||
EXPAND_COUNTER(lock_nonblock_eagain) \
|
||||
EXPAND_COUNTER(lock_shrink) \
|
||||
EXPAND_COUNTER(lock_write_dirty_item) \
|
||||
EXPAND_COUNTER(lock_shrink_queued) \
|
||||
EXPAND_COUNTER(lock_shrink_request_aborted) \
|
||||
EXPAND_COUNTER(lock_unlock) \
|
||||
EXPAND_COUNTER(lock_wait) \
|
||||
EXPAND_COUNTER(lock_write_dirty_item) \
|
||||
EXPAND_COUNTER(manifest_compact_migrate) \
|
||||
EXPAND_COUNTER(manifest_hard_stale_error) \
|
||||
EXPAND_COUNTER(manifest_read_excluded_key) \
|
||||
|
||||
+15
-13
@@ -792,15 +792,17 @@ static int scoutfs_readpage(struct file *file, struct page *page)
|
||||
int ret;
|
||||
|
||||
flags = SCOUTFS_LKF_REFRESH_INODE | SCOUTFS_LKF_NONBLOCK;
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, flags, inode, &inode_lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ, flags, inode,
|
||||
&inode_lock);
|
||||
if (ret < 0) {
|
||||
unlock_page(page);
|
||||
if (ret == -EAGAIN) {
|
||||
flags &= ~SCOUTFS_LKF_NONBLOCK;
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, flags, inode,
|
||||
&inode_lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ, flags,
|
||||
inode, &inode_lock);
|
||||
if (ret == 0) {
|
||||
scoutfs_unlock(sb, inode_lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, inode_lock,
|
||||
SCOUTFS_LOCK_READ);
|
||||
ret = AOP_TRUNCATED_PAGE;
|
||||
}
|
||||
}
|
||||
@@ -808,7 +810,7 @@ static int scoutfs_readpage(struct file *file, struct page *page)
|
||||
}
|
||||
|
||||
ret = mpage_readpage(page, scoutfs_get_block);
|
||||
scoutfs_unlock(sb, inode_lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -820,14 +822,14 @@ static int scoutfs_readpages(struct file *file, struct address_space *mapping,
|
||||
struct scoutfs_lock *inode_lock = NULL;
|
||||
int ret;
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, SCOUTFS_LKF_REFRESH_INODE,
|
||||
inode, &inode_lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &inode_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mpage_readpages(mapping, pages, nr_pages, scoutfs_get_block);
|
||||
|
||||
scoutfs_unlock(sb, inode_lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1076,8 +1078,8 @@ long scoutfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_EX, SCOUTFS_LKF_REFRESH_INODE,
|
||||
inode, &lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_WRITE,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -1166,7 +1168,7 @@ long scoutfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
|
||||
}
|
||||
|
||||
out:
|
||||
scoutfs_unlock(sb, lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_WRITE);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
trace_scoutfs_data_fallocate(sb, ino, mode, offset, len, ret);
|
||||
@@ -1199,7 +1201,7 @@ int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||
/* XXX overkill? */
|
||||
mutex_lock(&inode->i_mutex);
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, 0, inode, &inode_lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ, 0, inode, &inode_lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -1240,7 +1242,7 @@ int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||
blk_off = ext.start + ext.len;
|
||||
}
|
||||
|
||||
scoutfs_unlock(sb, inode_lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
|
||||
out:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
|
||||
+40
-34
@@ -335,7 +335,7 @@ static int scoutfs_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
}
|
||||
dir = parent->d_inode;
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, 0, dir, &lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ, 0, dir, &lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -368,7 +368,7 @@ out:
|
||||
trace_scoutfs_d_revalidate(sb, dentry, flags, parent, is_covered, ret);
|
||||
|
||||
dput(parent);
|
||||
scoutfs_unlock(sb, lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_READ);
|
||||
|
||||
if (ret < 0 && ret != -ECHILD)
|
||||
scoutfs_inc_counter(sb, dentry_revalidate_error);
|
||||
@@ -409,7 +409,7 @@ static struct dentry *scoutfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, 0, dir, &dir_lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ, 0, dir, &dir_lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -423,7 +423,7 @@ static struct dentry *scoutfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
update_dentry_info(sb, dentry, le64_to_cpu(dent.hash),
|
||||
le64_to_cpu(dent.pos), dir_lock);
|
||||
}
|
||||
scoutfs_unlock(sb, dir_lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, dir_lock, SCOUTFS_LOCK_READ);
|
||||
|
||||
out:
|
||||
if (ret < 0)
|
||||
@@ -491,7 +491,7 @@ static int scoutfs_readdir(struct file *file, void *dirent, filldir_t filldir)
|
||||
SCOUTFS_DIRENT_LAST_POS, 0);
|
||||
kvec_init(&val, dent, dirent_bytes(SCOUTFS_NAME_LEN));
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, 0, inode, &dir_lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ, 0, inode, &dir_lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -529,7 +529,7 @@ static int scoutfs_readdir(struct file *file, void *dirent, filldir_t filldir)
|
||||
}
|
||||
|
||||
out:
|
||||
scoutfs_unlock(sb, dir_lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, dir_lock, SCOUTFS_LOCK_READ);
|
||||
|
||||
kfree(dent);
|
||||
return ret;
|
||||
@@ -665,15 +665,17 @@ static struct inode *lock_hold_create(struct inode *dir, struct dentry *dentry,
|
||||
return ERR_PTR(ret);
|
||||
|
||||
if (ino < scoutfs_ino(dir)) {
|
||||
ret = scoutfs_lock_ino(sb, DLM_LOCK_EX, 0, ino, inode_lock) ?:
|
||||
scoutfs_lock_inode(sb, DLM_LOCK_EX,
|
||||
ret = scoutfs_lock_ino(sb, SCOUTFS_LOCK_WRITE, 0, ino,
|
||||
inode_lock) ?:
|
||||
scoutfs_lock_inode(sb, SCOUTFS_LOCK_WRITE,
|
||||
SCOUTFS_LKF_REFRESH_INODE, dir,
|
||||
dir_lock);
|
||||
} else {
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_EX,
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_WRITE,
|
||||
SCOUTFS_LKF_REFRESH_INODE, dir,
|
||||
dir_lock) ?:
|
||||
scoutfs_lock_ino(sb, DLM_LOCK_EX, 0, ino, inode_lock);
|
||||
scoutfs_lock_ino(sb, SCOUTFS_LOCK_WRITE, 0, ino,
|
||||
inode_lock);
|
||||
}
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
@@ -701,8 +703,8 @@ out:
|
||||
out_unlock:
|
||||
if (ret) {
|
||||
scoutfs_inode_index_unlock(sb, ind_locks);
|
||||
scoutfs_unlock(sb, *dir_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, *inode_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, *dir_lock, SCOUTFS_LOCK_WRITE);
|
||||
scoutfs_unlock(sb, *inode_lock, SCOUTFS_LOCK_WRITE);
|
||||
*dir_lock = NULL;
|
||||
*inode_lock = NULL;
|
||||
|
||||
@@ -763,8 +765,8 @@ static int scoutfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||
out:
|
||||
scoutfs_release_trans(sb);
|
||||
scoutfs_inode_index_unlock(sb, &ind_locks);
|
||||
scoutfs_unlock(sb, dir_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, inode_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, dir_lock, SCOUTFS_LOCK_WRITE);
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_WRITE);
|
||||
|
||||
/* XXX delete the inode item here */
|
||||
if (ret && !IS_ERR_OR_NULL(inode))
|
||||
@@ -803,7 +805,8 @@ static int scoutfs_link(struct dentry *old_dentry,
|
||||
if (dentry->d_name.len > SCOUTFS_NAME_LEN)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
ret = scoutfs_lock_inodes(sb, DLM_LOCK_EX, SCOUTFS_LKF_REFRESH_INODE,
|
||||
ret = scoutfs_lock_inodes(sb, SCOUTFS_LOCK_WRITE,
|
||||
SCOUTFS_LKF_REFRESH_INODE,
|
||||
dir, &dir_lock, inode, &inode_lock,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (ret)
|
||||
@@ -858,8 +861,8 @@ out:
|
||||
scoutfs_release_trans(sb);
|
||||
out_unlock:
|
||||
scoutfs_inode_index_unlock(sb, &ind_locks);
|
||||
scoutfs_unlock(sb, dir_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, inode_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, dir_lock, SCOUTFS_LOCK_WRITE);
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_WRITE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -889,7 +892,8 @@ static int scoutfs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
u64 ind_seq;
|
||||
int ret = 0;
|
||||
|
||||
ret = scoutfs_lock_inodes(sb, DLM_LOCK_EX, SCOUTFS_LKF_REFRESH_INODE,
|
||||
ret = scoutfs_lock_inodes(sb, SCOUTFS_LOCK_WRITE,
|
||||
SCOUTFS_LKF_REFRESH_INODE,
|
||||
dir, &dir_lock, inode, &inode_lock,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (ret)
|
||||
@@ -946,8 +950,8 @@ out:
|
||||
scoutfs_release_trans(sb);
|
||||
unlock:
|
||||
scoutfs_inode_index_unlock(sb, &ind_locks);
|
||||
scoutfs_unlock(sb, dir_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, inode_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, dir_lock, SCOUTFS_LOCK_WRITE);
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_WRITE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1034,8 +1038,8 @@ static void *scoutfs_follow_link(struct dentry *dentry, struct nameidata *nd)
|
||||
loff_t size;
|
||||
int ret;
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, SCOUTFS_LKF_REFRESH_INODE,
|
||||
inode, &inode_lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &inode_lock);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
@@ -1087,7 +1091,7 @@ out:
|
||||
} else {
|
||||
nd_set_link(nd, path);
|
||||
}
|
||||
scoutfs_unlock(sb, inode_lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -1184,8 +1188,8 @@ out:
|
||||
|
||||
scoutfs_release_trans(sb);
|
||||
scoutfs_inode_index_unlock(sb, &ind_locks);
|
||||
scoutfs_unlock(sb, dir_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, inode_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, dir_lock, SCOUTFS_LOCK_WRITE);
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_WRITE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1239,12 +1243,12 @@ int scoutfs_dir_add_next_linkref(struct super_block *sb, u64 ino,
|
||||
U64_MAX);
|
||||
kvec_init(&val, &ent->dent, dirent_bytes(SCOUTFS_NAME_LEN));
|
||||
|
||||
ret = scoutfs_lock_ino(sb, DLM_LOCK_PR, 0, ino, &lock);
|
||||
ret = scoutfs_lock_ino(sb, SCOUTFS_LOCK_READ, 0, ino, &lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = scoutfs_item_next(sb, &key, &last_key, &val, lock);
|
||||
scoutfs_unlock(sb, lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_READ);
|
||||
lock = NULL;
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@@ -1524,7 +1528,8 @@ static int scoutfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
|
||||
/* if dirs are different make sure ancestor relationships are valid */
|
||||
if (old_dir != new_dir) {
|
||||
ret = scoutfs_lock_rename(sb, DLM_LOCK_EX, 0, &rename_lock);
|
||||
ret = scoutfs_lock_rename(sb, SCOUTFS_LOCK_WRITE, 0,
|
||||
&rename_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1537,7 +1542,8 @@ static int scoutfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
}
|
||||
|
||||
/* lock all the inodes */
|
||||
ret = scoutfs_lock_inodes(sb, DLM_LOCK_EX, SCOUTFS_LKF_REFRESH_INODE,
|
||||
ret = scoutfs_lock_inodes(sb, SCOUTFS_LOCK_WRITE,
|
||||
SCOUTFS_LKF_REFRESH_INODE,
|
||||
old_dir, &old_dir_lock,
|
||||
new_dir, &new_dir_lock,
|
||||
old_inode, &old_inode_lock,
|
||||
@@ -1722,11 +1728,11 @@ out:
|
||||
|
||||
out_unlock:
|
||||
scoutfs_inode_index_unlock(sb, &ind_locks);
|
||||
scoutfs_unlock(sb, old_inode_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, new_inode_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, old_dir_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, new_dir_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, rename_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, old_inode_lock, SCOUTFS_LOCK_WRITE);
|
||||
scoutfs_unlock(sb, new_inode_lock, SCOUTFS_LOCK_WRITE);
|
||||
scoutfs_unlock(sb, old_dir_lock, SCOUTFS_LOCK_WRITE);
|
||||
scoutfs_unlock(sb, new_dir_lock, SCOUTFS_LOCK_WRITE);
|
||||
scoutfs_unlock(sb, rename_lock, SCOUTFS_LOCK_WRITE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+11
-11
@@ -41,13 +41,13 @@ ssize_t scoutfs_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_ent);
|
||||
int ret;
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, SCOUTFS_LKF_REFRESH_INODE,
|
||||
inode, &inode_lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &inode_lock);
|
||||
if (ret == 0) {
|
||||
scoutfs_per_task_add(&si->pt_data_lock, &pt_ent, inode_lock);
|
||||
ret = generic_file_aio_read(iocb, iov, nr_segs, pos);
|
||||
scoutfs_per_task_del(&si->pt_data_lock, &pt_ent);
|
||||
scoutfs_unlock(sb, inode_lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -68,8 +68,8 @@ ssize_t scoutfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
return 0;
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_EX, SCOUTFS_LKF_REFRESH_INODE,
|
||||
inode, &inode_lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_WRITE,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &inode_lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -84,7 +84,7 @@ ssize_t scoutfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
|
||||
out:
|
||||
scoutfs_per_task_del(&si->pt_data_lock, &pt_ent);
|
||||
scoutfs_unlock(sb, inode_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_WRITE);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
if (ret > 0 || ret == -EIOCBQUEUED) {
|
||||
@@ -107,14 +107,14 @@ int scoutfs_permission(struct inode *inode, int mask)
|
||||
if (mask & MAY_NOT_BLOCK)
|
||||
return -ECHILD;
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, SCOUTFS_LKF_REFRESH_INODE,
|
||||
inode, &inode_lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &inode_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = generic_permission(inode, mask);
|
||||
|
||||
scoutfs_unlock(sb, inode_lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -138,7 +138,7 @@ loff_t scoutfs_file_llseek(struct file *file, loff_t offset, int whence)
|
||||
* items instead of relying on generic_file_llseek()
|
||||
* trickery.
|
||||
*/
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR,
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode,
|
||||
&lock);
|
||||
case SEEK_SET:
|
||||
@@ -152,7 +152,7 @@ loff_t scoutfs_file_llseek(struct file *file, loff_t offset, int whence)
|
||||
if (ret == 0)
|
||||
offset = generic_file_llseek(file, offset, whence);
|
||||
|
||||
scoutfs_unlock(sb, lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_READ);
|
||||
|
||||
return ret ? ret : offset;
|
||||
}
|
||||
|
||||
+5
-19
@@ -320,7 +320,8 @@ struct scoutfs_segment_block {
|
||||
#define SCOUTFS_INODE_INDEX_ZONE 1
|
||||
#define SCOUTFS_NODE_ZONE 2
|
||||
#define SCOUTFS_FS_ZONE 3
|
||||
#define SCOUTFS_MAX_ZONE 4 /* power of 2 is efficient */
|
||||
#define SCOUTFS_LOCK_ZONE 4
|
||||
#define SCOUTFS_MAX_ZONE 8 /* power of 2 is efficient */
|
||||
|
||||
/* inode index zone */
|
||||
#define SCOUTFS_INODE_INDEX_META_SEQ_TYPE 1
|
||||
@@ -341,6 +342,9 @@ struct scoutfs_segment_block {
|
||||
#define SCOUTFS_FILE_EXTENT_TYPE 7
|
||||
#define SCOUTFS_ORPHAN_TYPE 8
|
||||
|
||||
/* lock zone, only ever found in lock ranges, never in persistent items */
|
||||
#define SCOUTFS_RENAME_TYPE 1
|
||||
|
||||
#define SCOUTFS_MAX_TYPE 16 /* power of 2 is efficient */
|
||||
|
||||
/*
|
||||
@@ -557,26 +561,8 @@ enum {
|
||||
|
||||
#define SCOUTFS_MAX_VAL_SIZE SCOUTFS_XATTR_MAX_PART_SIZE
|
||||
|
||||
/*
|
||||
* structures used by dlm
|
||||
*/
|
||||
#define SCOUTFS_LOCK_SCOPE_GLOBAL 1
|
||||
#define SCOUTFS_LOCK_SCOPE_FS_ITEMS 2
|
||||
|
||||
#define SCOUTFS_LOCK_TYPE_GLOBAL_RENAME 1
|
||||
#define SCOUTFS_LOCK_TYPE_GLOBAL_SERVER 2
|
||||
|
||||
struct scoutfs_lock_name {
|
||||
__u8 scope;
|
||||
__u8 zone;
|
||||
__u8 type;
|
||||
__le64 first;
|
||||
__le64 second;
|
||||
} __packed;
|
||||
|
||||
#define SCOUTFS_LOCK_INODE_GROUP_NR 1024
|
||||
#define SCOUTFS_LOCK_INODE_GROUP_MASK (SCOUTFS_LOCK_INODE_GROUP_NR - 1)
|
||||
|
||||
#define SCOUTFS_LOCK_SEQ_GROUP_MASK ((1ULL << 10) - 1)
|
||||
|
||||
/*
|
||||
|
||||
+14
-14
@@ -315,11 +315,11 @@ int scoutfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
struct scoutfs_lock *lock = NULL;
|
||||
int ret;
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, SCOUTFS_LKF_REFRESH_INODE,
|
||||
inode, &lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &lock);
|
||||
if (ret == 0) {
|
||||
generic_fillattr(inode, stat);
|
||||
scoutfs_unlock(sb, lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_READ);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -406,8 +406,8 @@ int scoutfs_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
|
||||
trace_scoutfs_setattr(dentry, attr);
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_EX, SCOUTFS_LKF_REFRESH_INODE,
|
||||
inode, &lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_WRITE,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -452,7 +452,7 @@ int scoutfs_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
scoutfs_release_trans(sb);
|
||||
scoutfs_inode_index_unlock(sb, &ind_locks);
|
||||
out:
|
||||
scoutfs_unlock(sb, lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_WRITE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -612,7 +612,7 @@ struct inode *scoutfs_iget(struct super_block *sb, u64 ino)
|
||||
struct inode *inode;
|
||||
int ret;
|
||||
|
||||
ret = scoutfs_lock_ino(sb, DLM_LOCK_PR, 0, ino, &lock);
|
||||
ret = scoutfs_lock_ino(sb, SCOUTFS_LOCK_READ, 0, ino, &lock);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
@@ -641,7 +641,7 @@ struct inode *scoutfs_iget(struct super_block *sb, u64 ino)
|
||||
}
|
||||
|
||||
out:
|
||||
scoutfs_unlock(sb, lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_READ);
|
||||
return inode;
|
||||
}
|
||||
|
||||
@@ -1141,9 +1141,9 @@ int scoutfs_inode_index_try_lock_hold(struct super_block *sb,
|
||||
list_sort(NULL, list, cmp_index_lock);
|
||||
|
||||
list_for_each_entry(ind_lock, list, head) {
|
||||
ret = scoutfs_lock_inode_index(sb, DLM_LOCK_CW, ind_lock->type,
|
||||
ind_lock->major, ind_lock->ino,
|
||||
&ind_lock->lock);
|
||||
ret = scoutfs_lock_inode_index(sb, SCOUTFS_LOCK_WRITE_ONLY,
|
||||
ind_lock->type, ind_lock->major,
|
||||
ind_lock->ino, &ind_lock->lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
@@ -1188,7 +1188,7 @@ void scoutfs_inode_index_unlock(struct super_block *sb, struct list_head *list)
|
||||
struct index_lock *tmp;
|
||||
|
||||
list_for_each_entry_safe(ind_lock, tmp, list, head) {
|
||||
scoutfs_unlock(sb, ind_lock->lock, DLM_LOCK_CW);
|
||||
scoutfs_unlock(sb, ind_lock->lock, SCOUTFS_LOCK_WRITE_ONLY);
|
||||
list_del_init(&ind_lock->head);
|
||||
kfree(ind_lock);
|
||||
}
|
||||
@@ -1403,7 +1403,7 @@ static int delete_inode_items(struct super_block *sb, u64 ino)
|
||||
u64 size;
|
||||
int ret;
|
||||
|
||||
ret = scoutfs_lock_ino(sb, DLM_LOCK_EX, 0, ino, &lock);
|
||||
ret = scoutfs_lock_ino(sb, SCOUTFS_LOCK_WRITE, 0, ino, &lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1472,7 +1472,7 @@ out:
|
||||
if (release)
|
||||
scoutfs_release_trans(sb);
|
||||
scoutfs_inode_index_unlock(sb, &ind_locks);
|
||||
scoutfs_unlock(sb, lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_WRITE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+17
-16
@@ -43,11 +43,11 @@
|
||||
* relatively cheap because reading is going to check the segments
|
||||
* anyway.
|
||||
*
|
||||
* This is copying to userspace while holding a DLM lock. This is safe
|
||||
* because faulting can convert the lock to a higher level while we hold
|
||||
* the lower level. DLM locks don't block tasks in a node, they match
|
||||
* and the tasks fall back to local locking. In this case the spin
|
||||
* locks around the item cache.
|
||||
* This is copying to userspace while holding a read lock. This is safe
|
||||
* because faulting can send a request for a write lock while the read
|
||||
* lock is being used. The cluster locks don't block tasks in a node,
|
||||
* they match and the tasks fall back to local locking. In this case
|
||||
* the spin locks around the item cache.
|
||||
*/
|
||||
static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg)
|
||||
{
|
||||
@@ -99,8 +99,9 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg)
|
||||
/* cap nr to the max the ioctl can return to a compat task */
|
||||
walk.nr_entries = min_t(u64, walk.nr_entries, INT_MAX);
|
||||
|
||||
ret = scoutfs_lock_inode_index(sb, DLM_LOCK_PR, type, walk.first.major,
|
||||
walk.first.ino, &lock);
|
||||
ret = scoutfs_lock_inode_index(sb, SCOUTFS_LOCK_READ, type,
|
||||
walk.first.major, walk.first.ino,
|
||||
&lock);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
@@ -122,7 +123,7 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg)
|
||||
key = lock->end;
|
||||
scoutfs_key_inc(&key);
|
||||
|
||||
scoutfs_unlock(sb, lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_READ);
|
||||
|
||||
/*
|
||||
* XXX This will miss dirty items. We'd need to
|
||||
@@ -143,7 +144,7 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg)
|
||||
|
||||
key = next_key;
|
||||
|
||||
ret = scoutfs_lock_inode_index(sb, DLM_LOCK_PR,
|
||||
ret = scoutfs_lock_inode_index(sb, SCOUTFS_LOCK_READ,
|
||||
key.sk_type,
|
||||
le64_to_cpu(key.skii_major),
|
||||
le64_to_cpu(key.skii_ino),
|
||||
@@ -170,7 +171,7 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg)
|
||||
scoutfs_key_inc(&key);
|
||||
}
|
||||
|
||||
scoutfs_unlock(sb, lock, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_READ);
|
||||
|
||||
out:
|
||||
if (nr > 0)
|
||||
@@ -299,8 +300,8 @@ static long scoutfs_ioc_release(struct file *file, unsigned long arg)
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_EX, SCOUTFS_LKF_REFRESH_INODE,
|
||||
inode, &lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_WRITE,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -344,7 +345,7 @@ static long scoutfs_ioc_release(struct file *file, unsigned long arg)
|
||||
}
|
||||
|
||||
out:
|
||||
scoutfs_unlock(sb, lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_WRITE);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
mnt_drop_write_file(file);
|
||||
|
||||
@@ -423,8 +424,8 @@ static long scoutfs_ioc_stage(struct file *file, unsigned long arg)
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_EX, SCOUTFS_LKF_REFRESH_INODE,
|
||||
inode, &lock);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_WRITE,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -464,7 +465,7 @@ static long scoutfs_ioc_stage(struct file *file, unsigned long arg)
|
||||
current->backing_dev_info = NULL;
|
||||
out:
|
||||
scoutfs_per_task_del(&si->pt_data_lock, &pt_ent);
|
||||
scoutfs_unlock(sb, lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_WRITE);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
mnt_drop_write_file(file);
|
||||
|
||||
|
||||
+15
-13
@@ -791,10 +791,11 @@ restart:
|
||||
static bool lock_coverage(struct scoutfs_lock *lock,
|
||||
struct scoutfs_key *key, int op_mode)
|
||||
{
|
||||
signed char mode = ACCESS_ONCE(lock->granted_mode);
|
||||
signed char mode = ACCESS_ONCE(lock->mode);
|
||||
|
||||
return ((op_mode == mode) ||
|
||||
(op_mode == DLM_LOCK_PR && mode == DLM_LOCK_EX)) &&
|
||||
(op_mode == SCOUTFS_LOCK_READ &&
|
||||
mode == SCOUTFS_LOCK_WRITE)) &&
|
||||
scoutfs_key_compare_ranges(key, key,
|
||||
&lock->start, &lock->end) == 0;
|
||||
}
|
||||
@@ -816,7 +817,7 @@ int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key *key,
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, DLM_LOCK_PR)))
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, SCOUTFS_LOCK_READ)))
|
||||
return -EINVAL;
|
||||
|
||||
trace_scoutfs_item_lookup(sb, key);
|
||||
@@ -976,7 +977,7 @@ int scoutfs_item_next(struct super_block *sb, struct scoutfs_key *key,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, DLM_LOCK_PR))) {
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, SCOUTFS_LOCK_READ))) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -1142,7 +1143,7 @@ int scoutfs_item_prev(struct super_block *sb, struct scoutfs_key *key,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, DLM_LOCK_PR))) {
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, SCOUTFS_LOCK_READ))) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -1222,7 +1223,7 @@ int scoutfs_item_create(struct super_block *sb, struct scoutfs_key *key,
|
||||
int ret;
|
||||
|
||||
if (invalid_key_val(key, val) ||
|
||||
WARN_ON_ONCE(!lock_coverage(lock, key, DLM_LOCK_EX))) {
|
||||
WARN_ON_ONCE(!lock_coverage(lock, key, SCOUTFS_LOCK_WRITE))) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -1282,7 +1283,7 @@ int scoutfs_item_create_force(struct super_block *sb,
|
||||
if (invalid_key_val(key, val))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, DLM_LOCK_CW)))
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, SCOUTFS_LOCK_WRITE_ONLY)))
|
||||
return -EINVAL;
|
||||
|
||||
item = alloc_item(sb, key, val);
|
||||
@@ -1428,7 +1429,7 @@ int scoutfs_item_dirty(struct super_block *sb, struct scoutfs_key *key,
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, DLM_LOCK_EX)))
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, SCOUTFS_LOCK_WRITE)))
|
||||
return -EINVAL;
|
||||
|
||||
do {
|
||||
@@ -1473,7 +1474,7 @@ int scoutfs_item_update(struct super_block *sb, struct scoutfs_key *key,
|
||||
if (invalid_key_val(key, val))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, DLM_LOCK_EX)))
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, SCOUTFS_LOCK_WRITE)))
|
||||
return -EINVAL;
|
||||
|
||||
if (val) {
|
||||
@@ -1534,7 +1535,7 @@ int scoutfs_item_delete(struct super_block *sb, struct scoutfs_key *key,
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, DLM_LOCK_EX))) {
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, SCOUTFS_LOCK_WRITE))) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -1581,7 +1582,7 @@ int scoutfs_item_delete_force(struct super_block *sb,
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, DLM_LOCK_CW)))
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, SCOUTFS_LOCK_WRITE_ONLY)))
|
||||
return -EINVAL;
|
||||
|
||||
item = alloc_item(sb, key, NULL);
|
||||
@@ -1630,7 +1631,7 @@ int scoutfs_item_delete_save(struct super_block *sb,
|
||||
bool was_dirty;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, DLM_LOCK_EX))) {
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, SCOUTFS_LOCK_WRITE))) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -1704,7 +1705,8 @@ int scoutfs_item_restore(struct super_block *sb, struct list_head *list,
|
||||
|
||||
/* make sure all the items are locked and cached */
|
||||
list_for_each_entry(item, list, entry) {
|
||||
mode = item_is_dirty(item) ? DLM_LOCK_EX : DLM_LOCK_PR;
|
||||
mode = item_is_dirty(item) ? SCOUTFS_LOCK_WRITE :
|
||||
SCOUTFS_LOCK_READ;
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, &item->key, mode)) ||
|
||||
WARN_ON_ONCE(!check_range(sb, &cac->ranges, &item->key,
|
||||
NULL, NULL))) {
|
||||
|
||||
+640
-637
File diff suppressed because it is too large
Load Diff
+11
-13
@@ -1,14 +1,14 @@
|
||||
#ifndef _SCOUTFS_LOCK_H_
|
||||
#define _SCOUTFS_LOCK_H_
|
||||
|
||||
#include <linux/dlm.h>
|
||||
#include "key.h"
|
||||
#include "tseq.h"
|
||||
|
||||
#define SCOUTFS_LKF_REFRESH_INODE 0x01 /* update stale inode from item */
|
||||
#define SCOUTFS_LKF_NONBLOCK 0x02 /* only use already held locks */
|
||||
#define SCOUTFS_LKF_INVALID (~((SCOUTFS_LKF_NONBLOCK << 1) - 1))
|
||||
|
||||
#define SCOUTFS_LOCK_NR_MODES (DLM_LOCK_EX + 1)
|
||||
#define SCOUTFS_LOCK_NR_MODES SCOUTFS_LOCK_INVALID
|
||||
|
||||
/*
|
||||
* A few fields (start, end, refresh_gen, granted_mode) are referenced
|
||||
@@ -16,29 +16,22 @@
|
||||
*/
|
||||
struct scoutfs_lock {
|
||||
struct super_block *sb;
|
||||
struct scoutfs_lock_name name;
|
||||
struct scoutfs_key start;
|
||||
struct scoutfs_key end;
|
||||
struct rb_node node;
|
||||
struct rb_node range_node;
|
||||
unsigned int debug_locks_id;
|
||||
u64 refresh_gen;
|
||||
struct list_head lru_head;
|
||||
wait_queue_head_t waitq;
|
||||
struct work_struct work;
|
||||
struct dlm_lksb lksb;
|
||||
struct work_struct shrink_work;
|
||||
ktime_t grace_deadline;
|
||||
struct delayed_work grace_work;
|
||||
bool grace_pending;
|
||||
unsigned long request_pending:1,
|
||||
invalidate_pending:1;
|
||||
|
||||
spinlock_t cov_list_lock;
|
||||
struct list_head cov_list;
|
||||
|
||||
int error;
|
||||
int granted_mode;
|
||||
int bast_mode;
|
||||
int work_prev_mode;
|
||||
int work_mode;
|
||||
int mode;
|
||||
unsigned int waiters[SCOUTFS_LOCK_NR_MODES];
|
||||
unsigned int users[SCOUTFS_LOCK_NR_MODES];
|
||||
|
||||
@@ -51,6 +44,11 @@ struct scoutfs_lock_coverage {
|
||||
struct list_head head;
|
||||
};
|
||||
|
||||
int scoutfs_lock_grant_response(struct super_block *sb,
|
||||
struct scoutfs_net_lock *nl);
|
||||
int scoutfs_lock_invalidate_request(struct super_block *sb, u64 net_id,
|
||||
struct scoutfs_net_lock *nl);
|
||||
|
||||
int scoutfs_lock_inode(struct super_block *sb, int mode, int flags,
|
||||
struct inode *inode, struct scoutfs_lock **ret_lock);
|
||||
int scoutfs_lock_ino(struct super_block *sb, int mode, int flags, u64 ino,
|
||||
|
||||
+40
-48
@@ -1578,32 +1578,24 @@ DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_shrink_end,
|
||||
TP_ARGS(sb, rng, start, end)
|
||||
);
|
||||
|
||||
#define lock_mode(mode) \
|
||||
__print_symbolic(mode, \
|
||||
{ DLM_LOCK_IV, "IV" }, \
|
||||
{ DLM_LOCK_NL, "NL" }, \
|
||||
{ DLM_LOCK_CR, "CR" }, \
|
||||
{ DLM_LOCK_CW, "CW" }, \
|
||||
{ DLM_LOCK_PR, "PR" }, \
|
||||
{ DLM_LOCK_PW, "PW" }, \
|
||||
{ DLM_LOCK_EX, "EX" })
|
||||
#define lock_mode(mode) \
|
||||
__print_symbolic(mode, \
|
||||
{ SCOUTFS_LOCK_NULL, "NULL" }, \
|
||||
{ SCOUTFS_LOCK_READ, "READ" }, \
|
||||
{ SCOUTFS_LOCK_WRITE, "WRITE" }, \
|
||||
{ SCOUTFS_LOCK_WRITE_ONLY, "WRITE_ONLY" })
|
||||
|
||||
DECLARE_EVENT_CLASS(scoutfs_lock_class,
|
||||
TP_PROTO(struct super_block *sb, struct scoutfs_lock *lck),
|
||||
TP_ARGS(sb, lck),
|
||||
TP_STRUCT__entry(
|
||||
__field(__u64, fsid)
|
||||
__field(u8, name_scope)
|
||||
__field(u8, name_zone)
|
||||
__field(u8, name_type)
|
||||
__field(u64, name_first)
|
||||
__field(u64, name_second)
|
||||
sk_trace_define(start)
|
||||
sk_trace_define(end)
|
||||
__field(u64, refresh_gen)
|
||||
__field(int, error)
|
||||
__field(int, granted_mode)
|
||||
__field(int, bast_mode)
|
||||
__field(int, work_prev_mode)
|
||||
__field(int, work_mode)
|
||||
__field(unsigned char, request_pending)
|
||||
__field(unsigned char, invalidate_pending)
|
||||
__field(int, mode)
|
||||
__field(unsigned int, waiters_cw)
|
||||
__field(unsigned int, waiters_pr)
|
||||
__field(unsigned int, waiters_ex)
|
||||
@@ -1613,33 +1605,29 @@ DECLARE_EVENT_CLASS(scoutfs_lock_class,
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->fsid = FSID_ARG(sb);
|
||||
__entry->name_scope = lck->name.scope;
|
||||
__entry->name_zone = lck->name.zone;
|
||||
__entry->name_type = lck->name.type;
|
||||
__entry->name_first = le64_to_cpu(lck->name.first);
|
||||
__entry->name_second = le64_to_cpu(lck->name.second);
|
||||
|
||||
sk_trace_assign(start, &lck->start);
|
||||
sk_trace_assign(end, &lck->end);
|
||||
__entry->refresh_gen = lck->refresh_gen;
|
||||
__entry->error = lck->error;
|
||||
__entry->granted_mode = lck->granted_mode;
|
||||
__entry->bast_mode = lck->bast_mode;
|
||||
__entry->work_prev_mode = lck->work_prev_mode;
|
||||
__entry->work_mode = lck->work_mode;
|
||||
__entry->waiters_pr = lck->waiters[DLM_LOCK_PR];
|
||||
__entry->waiters_ex = lck->waiters[DLM_LOCK_EX];
|
||||
__entry->waiters_cw = lck->waiters[DLM_LOCK_CW];
|
||||
__entry->users_pr = lck->users[DLM_LOCK_PR];
|
||||
__entry->users_ex = lck->users[DLM_LOCK_EX];
|
||||
__entry->users_cw = lck->users[DLM_LOCK_CW];
|
||||
__entry->request_pending = lck->request_pending;
|
||||
__entry->invalidate_pending = lck->invalidate_pending;
|
||||
__entry->mode = lck->mode;
|
||||
__entry->waiters_pr = lck->waiters[SCOUTFS_LOCK_READ];
|
||||
__entry->waiters_ex = lck->waiters[SCOUTFS_LOCK_WRITE];
|
||||
__entry->waiters_cw = lck->waiters[SCOUTFS_LOCK_WRITE_ONLY];
|
||||
__entry->users_pr = lck->users[SCOUTFS_LOCK_READ];
|
||||
__entry->users_ex = lck->users[SCOUTFS_LOCK_WRITE];
|
||||
__entry->users_cw = lck->users[SCOUTFS_LOCK_WRITE_ONLY];
|
||||
),
|
||||
TP_printk("fsid "FSID_FMT" name %u.%u.%u.%llu.%llu refresh_gen %llu error %d granted %d bast %d prev %d work %d waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u",
|
||||
__entry->fsid, __entry->name_scope, __entry->name_zone,
|
||||
__entry->name_type, __entry->name_first, __entry->name_second,
|
||||
__entry->refresh_gen, __entry->error, __entry->granted_mode,
|
||||
__entry->bast_mode, __entry->work_prev_mode,
|
||||
__entry->work_mode, __entry->waiters_pr,
|
||||
__entry->waiters_ex, __entry->waiters_cw, __entry->users_pr,
|
||||
__entry->users_ex, __entry->users_cw)
|
||||
TP_printk("fsid "FSID_FMT" start "SK_FMT" end "SK_FMT" mode %u reqpnd %u invpnd %u rfrgen %llu waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u",
|
||||
__entry->fsid, sk_trace_args(start), sk_trace_args(end),
|
||||
__entry->mode, __entry->request_pending,
|
||||
__entry->invalidate_pending, __entry->refresh_gen,
|
||||
__entry->waiters_pr, __entry->waiters_ex, __entry->waiters_cw,
|
||||
__entry->users_pr, __entry->users_ex, __entry->users_cw)
|
||||
);
|
||||
DEFINE_EVENT(scoutfs_lock_class, scoutfs_lock_invalidate,
|
||||
TP_PROTO(struct super_block *sb, struct scoutfs_lock *lck),
|
||||
TP_ARGS(sb, lck)
|
||||
);
|
||||
DEFINE_EVENT(scoutfs_lock_class, scoutfs_lock_free,
|
||||
TP_PROTO(struct super_block *sb, struct scoutfs_lock *lck),
|
||||
@@ -1649,19 +1637,23 @@ DEFINE_EVENT(scoutfs_lock_class, scoutfs_lock_alloc,
|
||||
TP_PROTO(struct super_block *sb, struct scoutfs_lock *lck),
|
||||
TP_ARGS(sb, lck)
|
||||
);
|
||||
DEFINE_EVENT(scoutfs_lock_class, scoutfs_lock_ast,
|
||||
DEFINE_EVENT(scoutfs_lock_class, scoutfs_lock_grant_response,
|
||||
TP_PROTO(struct super_block *sb, struct scoutfs_lock *lck),
|
||||
TP_ARGS(sb, lck)
|
||||
);
|
||||
DEFINE_EVENT(scoutfs_lock_class, scoutfs_lock_bast,
|
||||
DEFINE_EVENT(scoutfs_lock_class, scoutfs_lock_granted,
|
||||
TP_PROTO(struct super_block *sb, struct scoutfs_lock *lck),
|
||||
TP_ARGS(sb, lck)
|
||||
);
|
||||
DEFINE_EVENT(scoutfs_lock_class, scoutfs_lock_work,
|
||||
DEFINE_EVENT(scoutfs_lock_class, scoutfs_lock_invalidate_request,
|
||||
TP_PROTO(struct super_block *sb, struct scoutfs_lock *lck),
|
||||
TP_ARGS(sb, lck)
|
||||
);
|
||||
DEFINE_EVENT(scoutfs_lock_class, scoutfs_lock_grace_work,
|
||||
DEFINE_EVENT(scoutfs_lock_class, scoutfs_lock_invalidated,
|
||||
TP_PROTO(struct super_block *sb, struct scoutfs_lock *lck),
|
||||
TP_ARGS(sb, lck)
|
||||
);
|
||||
DEFINE_EVENT(scoutfs_lock_class, scoutfs_lock_locked,
|
||||
TP_PROTO(struct super_block *sb, struct scoutfs_lock *lck),
|
||||
TP_ARGS(sb, lck)
|
||||
);
|
||||
|
||||
+2
-2
@@ -123,7 +123,7 @@ static void scoutfs_put_super(struct super_block *sb)
|
||||
|
||||
scoutfs_data_destroy(sb);
|
||||
|
||||
scoutfs_unlock(sb, sbi->node_id_lock, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, sbi->node_id_lock, SCOUTFS_LOCK_WRITE);
|
||||
sbi->node_id_lock = NULL;
|
||||
|
||||
scoutfs_shutdown_trans(sb);
|
||||
@@ -333,7 +333,7 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
scoutfs_server_setup(sb) ?:
|
||||
scoutfs_client_setup(sb) ?:
|
||||
scoutfs_client_wait_node_id(sb) ?:
|
||||
scoutfs_lock_node_id(sb, DLM_LOCK_EX, 0, sbi->node_id,
|
||||
scoutfs_lock_node_id(sb, SCOUTFS_LOCK_WRITE, 0, sbi->node_id,
|
||||
&sbi->node_id_lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
+7
-7
@@ -291,7 +291,7 @@ ssize_t scoutfs_getxattr(struct dentry *dentry, const char *name, void *buffer,
|
||||
if (!xat)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, 0, inode, &lck);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ, 0, inode, &lck);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -301,7 +301,7 @@ ssize_t scoutfs_getxattr(struct dentry *dentry, const char *name, void *buffer,
|
||||
name, name_len, 0, 0, lck);
|
||||
|
||||
up_read(&si->xattr_rwsem);
|
||||
scoutfs_unlock(sb, lck, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, lck, SCOUTFS_LOCK_READ);
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOENT)
|
||||
@@ -385,8 +385,8 @@ static int scoutfs_xattr_set(struct dentry *dentry, const char *name,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_EX, SCOUTFS_LKF_REFRESH_INODE,
|
||||
inode, &lck);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_WRITE,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &lck);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -466,7 +466,7 @@ release:
|
||||
scoutfs_inode_index_unlock(sb, &ind_locks);
|
||||
unlock:
|
||||
up_write(&si->xattr_rwsem);
|
||||
scoutfs_unlock(sb, lck, DLM_LOCK_EX);
|
||||
scoutfs_unlock(sb, lck, SCOUTFS_LOCK_WRITE);
|
||||
out:
|
||||
kfree(xat);
|
||||
|
||||
@@ -509,7 +509,7 @@ ssize_t scoutfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, 0, inode, &lck);
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ, 0, inode, &lck);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -546,7 +546,7 @@ ssize_t scoutfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
}
|
||||
|
||||
up_read(&si->xattr_rwsem);
|
||||
scoutfs_unlock(sb, lck, DLM_LOCK_PR);
|
||||
scoutfs_unlock(sb, lck, SCOUTFS_LOCK_READ);
|
||||
out:
|
||||
kfree(xat);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user