diff options
author | Namjae Jeon <linkinjeon@kernel.org> | 2023-12-08 14:37:56 +0900 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2023-12-08 10:11:33 -0600 |
commit | c2a721eead71202a0d8ddd9b56ec8dce652c71d1 (patch) | |
tree | fb170fa8b90d4920aae3a6e1ccd6e45ee4803fbe /fs/smb/server/oplock.c | |
parent | d47d9886aeef79feba7adac701a510d65f3682b5 (diff) | |
download | linux-c2a721eead71202a0d8ddd9b56ec8dce652c71d1.tar.gz linux-c2a721eead71202a0d8ddd9b56ec8dce652c71d1.tar.bz2 linux-c2a721eead71202a0d8ddd9b56ec8dce652c71d1.zip |
ksmbd: lazy v2 lease break on smb2_write()
Don't immediately send directory lease break notification on smb2_write().
Instead, It postpones it until smb2_close().
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/smb/server/oplock.c')
-rw-r--r-- | fs/smb/server/oplock.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c index 147d98427ce8..562b180459a1 100644 --- a/fs/smb/server/oplock.c +++ b/fs/smb/server/oplock.c @@ -396,8 +396,8 @@ void close_id_del_oplock(struct ksmbd_file *fp) { struct oplock_info *opinfo; - if (S_ISDIR(file_inode(fp->filp)->i_mode)) - return; + if (fp->reserve_lease_break) + smb_lazy_parent_lease_break_close(fp); opinfo = opinfo_get(fp); if (!opinfo) @@ -1127,6 +1127,47 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, ksmbd_inode_put(p_ci); } +void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp) +{ + struct oplock_info *opinfo; + struct ksmbd_inode *p_ci = NULL; + + rcu_read_lock(); + opinfo = rcu_dereference(fp->f_opinfo); + rcu_read_unlock(); + + if (!opinfo->is_lease || opinfo->o_lease->version != 2) + return; + + p_ci = ksmbd_inode_lookup_lock(fp->filp->f_path.dentry->d_parent); + if (!p_ci) + return; + + read_lock(&p_ci->m_lock); + list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) { + if (!opinfo->is_lease) + continue; + + if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE) { + if (!atomic_inc_not_zero(&opinfo->refcount)) + continue; + + atomic_inc(&opinfo->conn->r_count); + if (ksmbd_conn_releasing(opinfo->conn)) { + 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); + + ksmbd_inode_put(p_ci); +} + /** * smb_grant_oplock() - handle oplock/lease request on file open * @work: smb work |