All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Layton <jlayton@kernel.org>
To: Anna Schumaker <anna@kernel.org>,
	linux-nfs@vger.kernel.org,  trond.myklebust@hammerspace.com
Subject: Re: [PATCH v2 2/4] NFS: Add support for CB_NOTIFY4_REMOVE_ENTRY
Date: Tue, 25 Aug 2026 12:11:01 -0400	[thread overview]
Message-ID: <c0704acb89cdf5593970c6d7a7f000c6ef9f24c6.camel@kernel.org> (raw)
In-Reply-To: <20260825150209.694646-3-anna@kernel.org>

On Tue, 2026-08-25 at 11:02 -0400, Anna Schumaker wrote:
> From: Anna Schumaker <anna.schumaker@oracle.com>
> 
> When the server tells us that a directory entry has been removed then we
> need to take that as an indication that our knowledge of the directory
> has changed and needs to be refreshed.
> 
> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
> Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
> ---
> v2:
>   * Initialize 'res' to 0 in nfs4_callback_notify()
>   * Add missing error handling
>   * Remove nfs4_cb_notify_lookup()
> ---
>  fs/nfs/callback.h      | 16 ++++++++++-
>  fs/nfs/callback_proc.c | 63 +++++++++++++++++++++++++++++++++++++++++-
>  fs/nfs/callback_xdr.c  | 62 +++++++++++++++++++++++++++++++++++++++++
>  fs/nfs/nfs4xdr.c       |  3 +-
>  include/linux/nfs4.h   |  1 +
>  5 files changed, 142 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
> index f7cc5b6931bf..3740c999bb82 100644
> --- a/fs/nfs/callback.h
> +++ b/fs/nfs/callback.h
> @@ -143,8 +143,22 @@ struct cb_layoutrecallargs {
>  extern __be32 nfs4_callback_layoutrecall(void *argp, void *resp,
>  		struct cb_process_state *cps);
>  
> +struct cb_notify_entry {
> +	u32			ne_namelen;
> +	const char		*ne_name;
> +	struct nfs_fattr	ne_attrs;
> +};
> +
> +struct cb_notify_remove {
> +	struct cb_notify_entry	nrm_old_entry;
> +	u64			nrm_old_entry_cookie;
> +};
> +
>  struct cb_notify_changes {
> -	u32 notify_mask;
> +	u32	notify_mask;
> +	union {
> +		struct cb_notify_remove notify_remove;
> +	};
>  };
>  
>  struct cb_notifyargs {
> diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
> index 01600d75f2d9..d8ad3cd792df 100644
> --- a/fs/nfs/callback_proc.c
> +++ b/fs/nfs/callback_proc.c
> @@ -9,6 +9,7 @@
>  
>  #include <linux/errno.h>
>  #include <linux/math.h>
> +#include <linux/namei.h>
>  #include <linux/nfs4.h>
>  #include <linux/nfs_fs.h>
>  #include <linux/slab.h>
> @@ -369,13 +370,73 @@ static void pnfs_recall_all_layouts(struct nfs_client *clp,
>  	do_callback_layoutrecall(clp, &args, cps);
>  }
>  
> +static __be32 nfs4_cb_notify_remove(struct cb_process_state *cps,
> +				    struct dentry *parent,
> +				    struct cb_notify_remove *cb_remove)
> +{
> +	struct qstr filename = QSTR_INIT(cb_remove->nrm_old_entry.ne_name,
> +					 cb_remove->nrm_old_entry.ne_namelen);
> +	struct dentry *child;
> +
> +	filename.hash = full_name_hash(parent, filename.name, filename.len);
> +	child = d_lookup(parent, &filename);
> +	if (IS_ERR_OR_NULL(child))
> +		return htonl(NFS4ERR_BADHANDLE);
> +
> +	d_drop(child);

Should this instead make this a negative dentry?

I think this will just drop the existing dentry and it'll trigger a
lookup next time we end up trying to hit it.

> +	dput(child);
> +
> +	nfs_set_cache_invalid(parent->d_inode, NFS_INO_INVALID_DATA);
> +	return 0;
> +}
> +
>  __be32 nfs4_callback_notify(void *argp, void *resp,
>  			    struct cb_process_state *cps)
>  {
>  	struct cb_notifyargs *args = argp;
> +	struct dentry *parent;
> +	struct inode *inode;
> +	unsigned int i;
> +	__be32 res = 0;
>  
> +	if (!cps->clp) {
> +		res = htonl(NFS4ERR_OP_NOT_IN_SESSION);
> +		goto out;
> +	}
> +
> +	inode = nfs_delegation_find_inode(cps->clp, &args->cna_fh);
> +	if (IS_ERR(inode)) {
> +		res = htonl(NFS4ERR_BADHANDLE);
> +		goto out;
> +	}
> +	parent = d_find_alias(inode);
> +	if (!parent)
> +		goto out_iput;
> +
> +	for (i = 0; i < args->cna_n_changes; i++) {
> +		struct cb_notify_changes *change = &args->cna_changes[i];
> +
> +		switch (change->notify_mask) {
> +		case CB_NOTIFY4_REMOVE_ENTRY:
> +			res = nfs4_cb_notify_remove(cps, parent,
> +						    &change->notify_remove);
> +			break;
> +		default:
> +			res = htonl(NFS4ERR_NOTSUPP);
> +			goto out_dput;
> +		}
> +
> +		if (unlikely(res != 0))
> +			break;
> +	}
> +
> +out_dput:
> +	dput(parent);
> +out_iput:
> +	nfs_iput_and_deactive(inode);
> +out:
>  	kfree(args->cna_changes);
> -	return 0;
> +	return res;
>  }
>  
>  __be32 nfs4_callback_devicenotify(void *argp, void *resp,
> diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
> index 8d822a3ee248..612d215ac66e 100644
> --- a/fs/nfs/callback_xdr.c
> +++ b/fs/nfs/callback_xdr.c
> @@ -252,6 +252,50 @@ static __be32 decode_layoutrecall_args(struct svc_rqst *rqstp,
>  	return 0;
>  }
>  
> +static __be32 decode_notify_entry(struct xdr_stream *xdr,
> +				  struct cb_notify_entry *args)
> +{
> +	uint32_t bitmap[3] = {0};
> +	__be32 status;
> +	u32 attrlen;
> +	__be32 *p;
> +
> +	status = decode_string(xdr, &args->ne_namelen, &args->ne_name,
> +				NFS4_OPAQUE_LIMIT);
> +	if (unlikely(status != 0))
> +		return status;
> +
> +	status = decode_bitmap(xdr, bitmap);
> +	if (unlikely(status != 0))
> +		return status;
> +
> +	p = xdr_inline_decode(xdr, 4);
> +	if (unlikely(!p))
> +		return htonl(NFS4ERR_BADXDR);
> +
> +	attrlen = be32_to_cpup(p);
> +	if (attrlen != 0)
> +		return htonl(NFS4ERR_BADXDR);
> +	return 0;
> +}
> +
> +static __be32 decode_notify_remove(struct xdr_stream *xdr,
> +				   struct cb_notify_remove *args)
> +{
> +	__be32 status;
> +	__be32 *p;
> +
> +	status = decode_notify_entry(xdr, &args->nrm_old_entry);
> +	if (unlikely(status != 0))
> +		return status;
> +
> +	p = xdr_inline_decode(xdr, 8);
> +	if (unlikely(!p))
> +		return htonl(NFS4ERR_BADXDR);
> +	xdr_decode_hyper(p, &args->nrm_old_entry_cookie);
> +	return 0;
> +}
> +
>  static
>  __be32 decode_notify_args(struct svc_rqst *rqstp,
>  			  struct xdr_stream *xdr,
> @@ -289,6 +333,24 @@ __be32 decode_notify_args(struct svc_rqst *rqstp,
>  						     &change->notify_mask, 1);
>  		if (unlikely(res < 0))
>  			goto err;
> +
> +		/* Decode opaque size */
> +		p = xdr_inline_decode(xdr, 4);
> +		if (unlikely(!p))
> +			goto err;
> +		res = ntohl(*p);
> +
> +		switch (change->notify_mask) {
> +		case CB_NOTIFY4_REMOVE_ENTRY:
> +			status = decode_notify_remove(xdr,
> +						      &change->notify_remove);
> +			break;
> +		default:
> +			goto err;
> +		}
> +
> +		if (unlikely(status != 0))
> +			goto err;
>  	}
>  
>  	return 0;
> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
> index 5c51691fff03..e275fbfd395e 100644
> --- a/fs/nfs/nfs4xdr.c
> +++ b/fs/nfs/nfs4xdr.c
> @@ -2012,7 +2012,8 @@ static void
>  encode_get_dir_delegation(struct xdr_stream *xdr, struct compound_hdr *hdr)
>  {
>  	struct timespec64 ts = { 0, 0 };
> -	u32 notifications[1] = { CB_NOTIFY4_GFLAG_EXTEND };
> +	u32 notifications[1] = { CB_NOTIFY4_REMOVE_ENTRY |
> +				 CB_NOTIFY4_GFLAG_EXTEND };
>  	u32 attributes[1] = { 0 };
>  	__be32 *p;
>  
> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
> index 2e33f2ffdc31..8de3ea283767 100644
> --- a/include/linux/nfs4.h
> +++ b/include/linux/nfs4.h
> @@ -492,6 +492,7 @@ enum {
>  #define THRESHOLD_WR_IO                 (1UL << 3)
>  
>  /* Directory Delegation / CB_NOTIFY bits */
> +#define CB_NOTIFY4_REMOVE_ENTRY		(1UL << 2)
>  #define CB_NOTIFY4_GFLAG_EXTEND		(1UL << 6)
>  
>  #define NFSPROC4_NULL 0

-- 
Jeff Layton <jlayton@kernel.org>

  reply	other threads:[~2026-08-25 16:11 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-25 15:02 [PATCH v2 0/4] NFS: Add directory delegation support for CB_NOTIFY Anna Schumaker
2026-08-25 15:02 ` [PATCH v2 1/4] NFS: Add an outline for the CB_NOTIFY operation Anna Schumaker
2026-08-25 15:02 ` [PATCH v2 2/4] NFS: Add support for CB_NOTIFY4_REMOVE_ENTRY Anna Schumaker
2026-08-25 16:11   ` Jeff Layton [this message]
2026-08-25 15:02 ` [PATCH v2 3/4] NFS: Add support for CB_NOTIFY4_ADD_ENTRY Anna Schumaker
2026-08-25 15:02 ` [PATCH v2 4/4] NFS: Add support for CB_NOTIFY4_RENAME_ENTRY Anna Schumaker

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=c0704acb89cdf5593970c6d7a7f000c6ef9f24c6.camel@kernel.org \
    --to=jlayton@kernel.org \
    --cc=anna@kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=trond.myklebust@hammerspace.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.