From: ChenXiaoSong <chenxiaosong@chenxiaosong.com>
To: linkinjeon@kernel.org, tom@talpey.com, senozhatsky@chromium.org,
chenxiaosong@chenxiaosong.com
Cc: linux-cifs@vger.kernel.org, ChenXiaoSong <chenxiaosong@kylinos.cn>
Subject: [PATCH 06/12] smb/server: keep notify watches on file handles
Date: Sat, 26 Sep 2026 09:05:12 +0000 [thread overview]
Message-ID: <20260926090518.78547-7-chenxiaosong@chenxiaosong.com> (raw)
In-Reply-To: <20260926090518.78547-1-chenxiaosong@chenxiaosong.com>
From: ChenXiaoSong <chenxiaosong@kylinos.cn>
Keep one notify watch on each file handle. Reuse it for later requests,
and remove it when the handle is closed.
Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
---
fs/smb/server/notify.c | 44 +++++++++++++++++++++++++++++++++++----
fs/smb/server/notify.h | 2 ++
fs/smb/server/vfs_cache.c | 3 +++
fs/smb/server/vfs_cache.h | 4 ++++
4 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/fs/smb/server/notify.c b/fs/smb/server/notify.c
index b34f2f9b6d3f..b49c0ec5117d 100644
--- a/fs/smb/server/notify.c
+++ b/fs/smb/server/notify.c
@@ -305,6 +305,18 @@ static int ksmbd_notify_add(struct ksmbd_file *fp, u32 mask, u32 filter,
struct fsnotify_mark *mark, *tree_mark;
int err = 0;
+ mutex_lock(&fp->notify_lock);
+ if (fp->notify) {
+ /* Further requests on this open use the first request's options. */
+ ksmbd_debug(NOTIFY,
+ "Reusing fsnotify mark, inode %llu, mask 0x%x, filter 0x%x, watch tree %d\n",
+ (unsigned long long)file_inode(fp->filp)->i_ino,
+ fp->notify->mark->mask, fp->notify->filter,
+ fp->notify->watch_tree);
+ *notify_out = fp->notify;
+ goto out;
+ }
+
notify = kzalloc_obj(*notify, KSMBD_DEFAULT_GFP);
if (!notify) {
pr_err("Failed to allocate notify watch\n");
@@ -351,6 +363,7 @@ static int ksmbd_notify_add(struct ksmbd_file *fp, u32 mask, u32 filter,
notify->tree_mark = tree_mark;
}
+ fp->notify = notify;
*notify_out = notify;
ksmbd_debug(NOTIFY,
"Added fsnotify mark, inode %llu, mask 0x%x, filter 0x%x, watch tree %d\n",
@@ -363,9 +376,36 @@ static int ksmbd_notify_add(struct ksmbd_file *fp, u32 mask, u32 filter,
kfree(notify);
out:
+ mutex_unlock(&fp->notify_lock);
return err;
}
+/**
+ * ksmbd_notify_remove() - remove the notify watch for a closing handle
+ * @fp: file handle whose watch is being removed
+ *
+ * A cancelled CHANGE_NOTIFY request leaves this watch installed. The watch is
+ * owned by @fp and removed only when the file handle is finally closed.
+ */
+void ksmbd_notify_remove(struct ksmbd_file *fp)
+{
+ struct ksmbd_notify *notify;
+
+ mutex_lock(&fp->notify_lock);
+ notify = fp->notify;
+ fp->notify = NULL;
+ mutex_unlock(&fp->notify_lock);
+ if (!notify)
+ return;
+
+ ksmbd_debug(NOTIFY,
+ "Removing fsnotify mark, inode %llu, mask 0x%x, watch tree %d\n",
+ (unsigned long long)file_inode(fp->filp)->i_ino,
+ notify->mark->mask, notify->watch_tree);
+ ksmbd_notify_destroy_marks(notify);
+ kfree(notify);
+}
+
static struct ksmbd_file *
ksmbd_notify_validate_req(struct ksmbd_work *work,
struct smb2_change_notify_req *req,
@@ -587,10 +627,6 @@ int ksmbd_handle_notify(struct ksmbd_work *work,
release_async_work(work);
else
kfree(argv);
- if (notify) {
- ksmbd_notify_destroy_marks(notify);
- kfree(notify);
- }
if (fp)
ksmbd_fd_put(work, fp);
return err;
diff --git a/fs/smb/server/notify.h b/fs/smb/server/notify.h
index 8de46e07b02e..1132b91c1d54 100644
--- a/fs/smb/server/notify.h
+++ b/fs/smb/server/notify.h
@@ -14,11 +14,13 @@
#define __SMB_SERVER_NOTIFY_H__
struct ksmbd_work;
+struct ksmbd_file;
struct smb2_change_notify_req;
struct smb2_change_notify_rsp;
int ksmbd_handle_notify(struct ksmbd_work *work,
struct smb2_change_notify_req *req,
struct smb2_change_notify_rsp *rsp);
+void ksmbd_notify_remove(struct ksmbd_file *fp);
#endif /* __SMB_SERVER_NOTIFY_H__ */
diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c
index a96b764c4db5..b242babf5771 100644
--- a/fs/smb/server/vfs_cache.c
+++ b/fs/smb/server/vfs_cache.c
@@ -18,6 +18,7 @@
#include "vfs.h"
#include "connection.h"
#include "misc.h"
+#include "notify.h"
#include "mgmt/tree_connect.h"
#include "mgmt/user_session.h"
#include "mgmt/user_config.h"
@@ -626,6 +627,7 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
close_id_del_oplock(fp);
filp = fp->filp;
+ ksmbd_notify_remove(fp);
__ksmbd_inode_close(fp);
if (!IS_ERR_OR_NULL(filp))
fput(filp);
@@ -1220,6 +1222,7 @@ struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp)
INIT_LIST_HEAD(&fp->node);
INIT_LIST_HEAD(&fp->lock_list);
spin_lock_init(&fp->f_lock);
+ mutex_init(&fp->notify_lock);
mutex_init(&fp->readdir_lock);
atomic_set(&fp->refcount, 1);
diff --git a/fs/smb/server/vfs_cache.h b/fs/smb/server/vfs_cache.h
index 732ae26dd6a7..fe8a01b062cd 100644
--- a/fs/smb/server/vfs_cache.h
+++ b/fs/smb/server/vfs_cache.h
@@ -33,6 +33,7 @@
#define SMB2_NO_FID (0xFFFFFFFFFFFFFFFFULL)
struct ksmbd_conn;
+struct ksmbd_notify;
struct ksmbd_session;
struct ksmbd_lock {
@@ -96,6 +97,9 @@ struct ksmbd_file {
u64 durable_volatile_id;
spinlock_t f_lock;
+ /* Protects notify watch creation and removal. */
+ struct mutex notify_lock;
+ struct ksmbd_notify *notify;
struct ksmbd_inode *f_ci;
struct ksmbd_inode *f_parent_ci;
--
2.55.0
next prev parent reply other threads:[~2026-09-26 9:06 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-26 9:05 [PATCH 00/12] smb/server: change notify support ChenXiaoSong
2026-09-26 9:05 ` [PATCH 01/12] smb/server: move change notify handling into notify.c ChenXiaoSong
2026-09-26 9:05 ` [PATCH 02/12] smb/server: add more validation for change notify requests ChenXiaoSong
2026-09-26 9:05 ` [PATCH 03/12] smb/server: add debug type for change notify ChenXiaoSong
2026-09-26 9:05 ` [PATCH 04/12] smb/server: support non-recursive directory change watches ChenXiaoSong
2026-09-27 10:51 ` Namjae Jeon
2026-09-28 0:38 ` ChenXiaoSong
2026-09-26 9:05 ` [PATCH 05/12] smb/server: support recursive " ChenXiaoSong
2026-09-26 9:05 ` ChenXiaoSong [this message]
2026-09-26 9:05 ` [PATCH 07/12] smb/server: save simple notify events ChenXiaoSong
2026-09-27 10:31 ` Namjae Jeon
2026-09-28 1:27 ` ChenXiaoSong
2026-09-26 9:05 ` [PATCH 08/12] smb/server: save old names for rename " ChenXiaoSong
2026-09-26 9:05 ` [PATCH 09/12] smb/server: match " ChenXiaoSong
2026-09-26 9:05 ` [PATCH 10/12] smb/server: encode " ChenXiaoSong
2026-09-26 9:05 ` [PATCH 11/12] smb/server: send notify events to the client ChenXiaoSong
2026-09-26 9:05 ` [PATCH 12/12] smb/server: break directory leases before sending notify events ChenXiaoSong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260926090518.78547-7-chenxiaosong@chenxiaosong.com \
--to=chenxiaosong@chenxiaosong.com \
--cc=chenxiaosong@kylinos.cn \
--cc=linkinjeon@kernel.org \
--cc=linux-cifs@vger.kernel.org \
--cc=senozhatsky@chromium.org \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox