From: Namjae Jeon Date: Sun, 31 Dec 2023 07:19:18 +0000 (+0900) Subject: ksmbd: lazy v2 lease break on smb2_write() X-Git-Tag: v6.6.14~893 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ab5a0a1c40befa1fdfe9e018c2fab52c5fc3d44b;p=platform%2Fkernel%2Flinux-starfive.git ksmbd: lazy v2 lease break on smb2_write() [ Upstream commit c2a721eead71202a0d8ddd9b56ec8dce652c71d1 ] Don't immediately send directory lease break notification on smb2_write(). Instead, It postpones it until smb2_close(). Signed-off-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Sasha Levin --- diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c index 147d984..562b180 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 diff --git a/fs/smb/server/oplock.h b/fs/smb/server/oplock.h index b64d153..5b93ea9 100644 --- a/fs/smb/server/oplock.h +++ b/fs/smb/server/oplock.h @@ -129,4 +129,5 @@ int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci, void destroy_lease_table(struct ksmbd_conn *conn); void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, struct lease_ctx_info *lctx); +void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp); #endif /* __KSMBD_OPLOCK_H */ diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c index 9091dcd..4277750 100644 --- a/fs/smb/server/vfs.c +++ b/fs/smb/server/vfs.c @@ -517,6 +517,9 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp, } } + /* Reserve lease break for parent dir at closing time */ + fp->reserve_lease_break = true; + /* Do we need to break any of a levelII oplock? */ smb_break_all_levII_oplock(work, fp, 1); diff --git a/fs/smb/server/vfs_cache.h b/fs/smb/server/vfs_cache.h index 4d4938d..a528f0c 100644 --- a/fs/smb/server/vfs_cache.h +++ b/fs/smb/server/vfs_cache.h @@ -105,6 +105,7 @@ struct ksmbd_file { struct ksmbd_readdir_data readdir_data; int dot_dotdot[2]; unsigned int f_state; + bool reserve_lease_break; }; static inline void set_ctx_actor(struct dir_context *ctx,