On Wed, 2025-09-24 at 14:06 -0400, Jeff Layton wrote:
> Add the necessary parts to accept a fsnotify callback for directory
> change event and create a CB_NOTIFY request for it. When a dir nfsd_file
> is created set a handle_event callback to handle the notification.
> 
> Use that to allocate a nfsd_notify_event object and then hand off a
> reference to each delegation's CB_NOTIFY. If anything fails along the
> way, recall any affected delegations.
> 
> Signed-off-by: Jeff Layton <jlay...@kernel.org>
> ---
>  fs/nfsd/filecache.c    |  51 ++++++++++----
>  fs/nfsd/nfs4callback.c |  19 +++--
>  fs/nfsd/nfs4state.c    | 185 
> +++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/nfsd/nfs4xdr.c      |  95 +++++++++++++++++++++++++
>  fs/nfsd/state.h        |   2 +
>  fs/nfsd/xdr4.h         |   2 +
>  6 files changed, 337 insertions(+), 17 deletions(-)
> 

[...]

> +
> +int
> +nfsd_handle_dir_event(u32 mask, const struct inode *dir, const void *data,
> +                   int data_type, const struct qstr *name)
> +{
> +     struct dentry *dentry = fsnotify_data_dentry(data, data_type);
> +     struct file_lock_context *ctx;
> +     struct file_lock_core *flc;
> +     struct nfsd_notify_event *evt;
> +
> +     ctx = locks_inode_context(dir);
> +     if (!ctx || list_empty(&ctx->flc_lease))
> +             return 0;
> +
> +     evt = alloc_nfsd_notify_event(mask, name, dentry);
> +     if (!evt) {
> +             nfsd_recall_all_dir_delegs(dir);
> +             return 0;
> +     }
> +
> +     spin_lock(&ctx->flc_lock);
> +     list_for_each_entry(flc, &ctx->flc_lease, flc_list) {
> +             struct file_lease *fl = container_of(flc, struct file_lease, c);
> +             struct nfs4_delegation *dp = flc->flc_owner;
> +             struct nfsd4_cb_notify *ncn = &dp->dl_cb_notify;
> +
> +             if (!should_notify_deleg(mask, fl))
> +                     continue;
> +
> +             spin_lock(&ncn->ncn_lock);
> +             if (ncn->ncn_evt_cnt >= NOTIFY4_EVENT_QUEUE_SIZE) {
> +                     /* We're generating notifications too fast. Recall. */
> +                     spin_unlock(&ncn->ncn_lock);
> +                     nfsd_break_deleg_cb(fl);
> +                     continue;
> +             }
> +             ncn->ncn_evt[ncn->ncn_evt_cnt++] = nfsd_notify_event_get(evt);

The above nfsd_notify_event_get() causes a refcount leak. Fixed in
tree.
-- 
Jeff Layton <jlay...@kernel.org>

Reply via email to