Skip to content

Commit

Permalink
ksmbd: use rwsem instead of rwlock for lease break
Browse files Browse the repository at this point in the history
lease break wait for lease break acknowledgment.
rwsem is more suitable than unlock while traversing the list for parent
lease break in ->m_op_list.

Signed-off-by: Namjae Jeon <[email protected]>
  • Loading branch information
namjaejeon committed May 15, 2024
1 parent 13293c2 commit 977866e
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 46 deletions.
30 changes: 11 additions & 19 deletions oplock.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,9 @@ static void opinfo_add(struct oplock_info *opinfo)
{
struct ksmbd_inode *ci = opinfo->o_fp->f_ci;

write_lock(&ci->m_lock);
down_write(&ci->m_lock);
list_add_rcu(&opinfo->op_entry, &ci->m_op_list);
write_unlock(&ci->m_lock);
up_write(&ci->m_lock);
}

static void opinfo_del(struct oplock_info *opinfo)
Expand All @@ -227,9 +227,9 @@ static void opinfo_del(struct oplock_info *opinfo)
lease_del_list(opinfo);
write_unlock(&lease_list_lock);
}
write_lock(&ci->m_lock);
down_write(&ci->m_lock);
list_del_rcu(&opinfo->op_entry);
write_unlock(&ci->m_lock);
up_write(&ci->m_lock);
}

static unsigned long opinfo_count(struct ksmbd_file *fp)
Expand Down Expand Up @@ -625,21 +625,18 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
* Compare lease key and client_guid to know request from same owner
* of same client
*/
read_lock(&ci->m_lock);
down_read(&ci->m_lock);
list_for_each_entry(opinfo, &ci->m_op_list, op_entry) {
if (!opinfo->is_lease || !opinfo->conn)
continue;
read_unlock(&ci->m_lock);
lease = opinfo->o_lease;

ret = compare_guid_key(opinfo, client_guid, lctx->lease_key);
if (ret) {
m_opinfo = opinfo;
/* skip upgrading lease about breaking lease */
if (atomic_read(&opinfo->breaking_cnt)) {
read_lock(&ci->m_lock);
if (atomic_read(&opinfo->breaking_cnt))
continue;
}

/* upgrading lease */
if ((atomic_read(&ci->op_count) +
Expand Down Expand Up @@ -669,9 +666,8 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
lease_none_upgrade(opinfo, lctx->req_state);
}
}
read_lock(&ci->m_lock);
}
read_unlock(&ci->m_lock);
up_read(&ci->m_lock);

return m_opinfo;
}
Expand Down Expand Up @@ -1330,7 +1326,7 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
if (!p_ci)
return;

read_lock(&p_ci->m_lock);
down_read(&p_ci->m_lock);
list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {
if (opinfo->conn == NULL || !opinfo->is_lease)
continue;
Expand All @@ -1348,13 +1344,11 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
continue;
}

read_unlock(&p_ci->m_lock);
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);
opinfo_conn_put(opinfo);
read_lock(&p_ci->m_lock);
}
}
read_unlock(&p_ci->m_lock);
up_read(&p_ci->m_lock);

ksmbd_inode_put(p_ci);
}
Expand All @@ -1375,7 +1369,7 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
if (!p_ci)
return;

read_lock(&p_ci->m_lock);
down_read(&p_ci->m_lock);
list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {
if (opinfo->conn == NULL || !opinfo->is_lease)
continue;
Expand All @@ -1389,13 +1383,11 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
atomic_dec(&opinfo->conn->r_count);
continue;
}
read_unlock(&p_ci->m_lock);
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);
opinfo_conn_put(opinfo);
read_lock(&p_ci->m_lock);
}
}
read_unlock(&p_ci->m_lock);
up_read(&p_ci->m_lock);

ksmbd_inode_put(p_ci);
}
Expand Down
16 changes: 8 additions & 8 deletions smb1pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2642,9 +2642,9 @@ int smb_nt_create_andx(struct ksmbd_work *work)
fp->saccess = req->ShareAccess;
fp->pid = le16_to_cpu(req->hdr.Pid);

write_lock(&fp->f_ci->m_lock);
down_write(&fp->f_ci->m_lock);
list_add(&fp->node, &fp->f_ci->m_fp_list);
write_unlock(&fp->f_ci->m_lock);
up_write(&fp->f_ci->m_lock);

share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp);
if (smb1_oplock_enable &&
Expand Down Expand Up @@ -5098,9 +5098,9 @@ static int smb_posix_open(struct ksmbd_work *work)
}
fp->pid = le16_to_cpu(pSMB_req->hdr.Pid);

write_lock(&fp->f_ci->m_lock);
down_write(&fp->f_ci->m_lock);
list_add(&fp->node, &fp->f_ci->m_fp_list);
write_unlock(&fp->f_ci->m_lock);
up_write(&fp->f_ci->m_lock);

if (smb1_oplock_enable &&
test_share_config_flag(work->tcon->share_conf,
Expand Down Expand Up @@ -6163,9 +6163,9 @@ static int find_first(struct ksmbd_work *work)
path_put(&parent_path);
#endif

write_lock(&dir_fp->f_ci->m_lock);
down_write(&dir_fp->f_ci->m_lock);
list_add(&dir_fp->node, &dir_fp->f_ci->m_fp_list);
write_unlock(&dir_fp->f_ci->m_lock);
up_write(&dir_fp->f_ci->m_lock);

set_ctx_actor(&dir_fp->readdir_data.ctx, ksmbd_fill_dirent);
dir_fp->readdir_data.dirent = (void *)__get_free_page(GFP_KERNEL);
Expand Down Expand Up @@ -8416,9 +8416,9 @@ int smb_open_andx(struct ksmbd_work *work)
}
fp->pid = le16_to_cpu(req->hdr.Pid);

write_lock(&fp->f_ci->m_lock);
down_write(&fp->f_ci->m_lock);
list_add(&fp->node, &fp->f_ci->m_fp_list);
write_unlock(&fp->f_ci->m_lock);
up_write(&fp->f_ci->m_lock);

share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp);
if (smb1_oplock_enable &&
Expand Down
4 changes: 2 additions & 2 deletions smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -3552,9 +3552,9 @@ int smb2_open(struct ksmbd_work *work)
* after daccess, saccess, attrib_only, and stream are
* initialized.
*/
write_lock(&fp->f_ci->m_lock);
down_write(&fp->f_ci->m_lock);
list_add(&fp->node, &fp->f_ci->m_fp_list);
write_unlock(&fp->f_ci->m_lock);
up_write(&fp->f_ci->m_lock);

/* Check delete pending among previous fp before oplock break */
if (ksmbd_inode_pending_delete(fp)) {
Expand Down
4 changes: 2 additions & 2 deletions smb_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)
* Lookup fp in master fp list, and check desired access and
* shared mode between previous open and current open.
*/
read_lock(&curr_fp->f_ci->m_lock);
down_read(&curr_fp->f_ci->m_lock);
list_for_each_entry(prev_fp, &curr_fp->f_ci->m_fp_list, node) {
if (file_inode(filp) != file_inode(prev_fp->filp))
continue;
Expand Down Expand Up @@ -767,7 +767,7 @@ int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)
break;
}
}
read_unlock(&curr_fp->f_ci->m_lock);
up_read(&curr_fp->f_ci->m_lock);

return rc;
}
Expand Down
28 changes: 14 additions & 14 deletions vfs_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp)
ci->m_fattr = 0;
INIT_LIST_HEAD(&ci->m_fp_list);
INIT_LIST_HEAD(&ci->m_op_list);
rwlock_init(&ci->m_lock);
init_rwsem(&ci->m_lock);
ci->m_de = fp->filp->f_path.dentry;
return 0;
}
Expand Down Expand Up @@ -271,14 +271,14 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
}

if (atomic_dec_and_test(&ci->m_count)) {
write_lock(&ci->m_lock);
down_write(&ci->m_lock);
if (ci->m_flags & (S_DEL_ON_CLS | S_DEL_PENDING)) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
dentry = filp->f_path.dentry;
dir = dentry->d_parent;
#endif
ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
write_unlock(&ci->m_lock);
up_write(&ci->m_lock);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)
ksmbd_vfs_unlink(filp);
Expand All @@ -288,9 +288,9 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
#else
ksmbd_vfs_unlink(file_mnt_user_ns(filp), dir, dentry);
#endif
write_lock(&ci->m_lock);
down_write(&ci->m_lock);
}
write_unlock(&ci->m_lock);
up_write(&ci->m_lock);

ksmbd_inode_free(ci);
}
Expand All @@ -311,9 +311,9 @@ static void __ksmbd_remove_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp
if (!has_file_id(fp->volatile_id))
return;

write_lock(&fp->f_ci->m_lock);
down_write(&fp->f_ci->m_lock);
list_del_init(&fp->node);
write_unlock(&fp->f_ci->m_lock);
up_write(&fp->f_ci->m_lock);

write_lock(&ft->lock);
idr_remove(ft->idr, fp->volatile_id);
Expand Down Expand Up @@ -577,17 +577,17 @@ struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry)
if (!ci)
return NULL;

read_lock(&ci->m_lock);
down_read(&ci->m_lock);
list_for_each_entry(lfp, &ci->m_fp_list, node) {
if (inode == file_inode(lfp->filp)) {
atomic_dec(&ci->m_count);
lfp = ksmbd_fp_get(lfp);
read_unlock(&ci->m_lock);
up_read(&ci->m_lock);
return lfp;
}
}
atomic_dec(&ci->m_count);
read_unlock(&ci->m_lock);
up_read(&ci->m_lock);
return NULL;
}

Expand Down Expand Up @@ -765,13 +765,13 @@ static bool session_fd_check(struct ksmbd_tree_connect *tcon,

conn = fp->conn;
ci = fp->f_ci;
write_lock(&ci->m_lock);
down_write(&ci->m_lock);
list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) {
if (op->conn != conn)
continue;
op->conn = NULL;
}
write_unlock(&ci->m_lock);
up_write(&ci->m_lock);

fp->conn = NULL;
fp->tcon = NULL;
Expand Down Expand Up @@ -877,13 +877,13 @@ int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp)
fp->tcon = work->tcon;

ci = fp->f_ci;
write_lock(&ci->m_lock);
down_write(&ci->m_lock);
list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) {
if (op->conn)
continue;
op->conn = fp->conn;
}
write_unlock(&ci->m_lock);
up_write(&ci->m_lock);

__open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
if (!has_file_id(fp->volatile_id)) {
Expand Down
2 changes: 1 addition & 1 deletion vfs_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct stream {
};

struct ksmbd_inode {
rwlock_t m_lock;
struct rw_semaphore m_lock;
atomic_t m_count;
atomic_t op_count;
/* opinfo count for streams */
Expand Down

0 comments on commit 977866e

Please sign in to comment.