NFS Client Updates for Linux 7.2

New Features:
  * XPRTRDMA: Decouple req recycling from RPC completion
  * NFS: Expose FMODE_NOWAIT for read-only files
 
 Bugfixes:
  * SUNRPC: Fix sunrpc sysfs error handling
  * SUNRPC: Fix uninitialized xprt_create_args structure
  * XPRTRDMA: Harden connect and reply handling
  * NFS: Fix EOF updates after fallocate/zero-range
  * NFS: Keep PG_UPTODATE clear after read errors in page groups
  * NFS: Use nfsi->rwsem to protect traversal of the file lock list
  * NFS: Prevent resource leak in nfs_alloc_server()
  * NFSv4: Clear exception state on successful mkdir retry
  * NFSv4: Don't skip revalidate when holding a dir delegation and attrs are stale
  * pNFS: Fix use-after-free in pnfs_update_layout()
  * pNFS: Defer return_range callbacks until after inode unlock
  * pNFS: Fix LAYOUTCOMMIT retry loop on OLD_STATEID
  * pNFS: Reject zero-length r_addr in nfs4_decode_mp_ds_addr
  * NFS/flexfiles: Reject zero-length filehandle version arrays
  * NFS/flexfiles: Fix checking if a layout is striped
  * NFS/flexfiles: Fixes for honoring FF_FLAGS_NO_IO_THRU_MDS
 
 Other Cleanups and Improvements:
  * Remove the fileid field from struct nfs_inode
  * Move long-delayed xprtrdma work onto the system_dfl_long_wq
  * Convert xprtrdma send buffer free list to an llist
  * Show "<redacted>" for cert_serial and privkey_serial mount options
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAmo64NUACgkQ18tUv7Cl
 QOvVMRAAnto2SAwqPkUf2V6dET141qKhWLRKLUqbYxkzc1PKqJBfJuJBwNWHNtyb
 M9JXpx00WSCjfksP5SyD5YugOzom1/SbMJlZB2FCBW6+LTyP/jwsBmqzWXdiKc/d
 x2pD7dkKVdjQUg8siNRLkJR4cyquySUlV39JNKHtPzhHTyWCVYqpvBcsFZwvPPPp
 TKC2ubpbu3zFlZUIYUEKMpPq44dOOlLzMzjWxMO8yTy/s/+5LsNLFRiSadr2sINp
 EWdPn2rpaQT1KmkHdklwUy8xtS+Zw0LaH0g0bVGJfd2ptiMz2VdFIFzxJkQh8jMT
 x0FkUBWDbTdVyiI0OZDo3uh/pJiKzTQI2SecE9to4rNHlNVDeOT9n8UanSYs71rz
 emXQIgszv2juiUvbSRcgzQ+SFKcxq332eDRWmpPIQox+/NvMFK+aMLS7aTd319Up
 bfVMRp5uAp5r2oVz3ETg7RDqatMJ2S0/J2HB3zVf5ONzaBaA//TUrCiSAt49Ep7a
 SsK7VXJCnxw2S23fa3RqlylZ3Gw29QiRjK7INoe8iNjLTqxAvtwcCTum7Ys+IGEl
 VVyxzBzgeGLlT4mU9BpMRZ9BZUjqgmflL8t4FwiFZQD1nZmJLwulZ8zSjIJ7OK2g
 8G8SWP3K7igEbWGCOwqqZWTtkzQC7OYR27vQuz6aPcgIS/fuMxg=
 =hj8e
 -----END PGP SIGNATURE-----

Merge tag 'nfs-for-7.2-1' of git://git.linux-nfs.org/projects/anna/linux-nfs

Pull NFS client updates from Anna Schumaker:
 "New features:
   - XPRTRDMA: Decouple req recycling from RPC completion
   - NFS: Expose FMODE_NOWAIT for read-only files

  Bugfixes:
   - SUNRPC:
      - Fix sunrpc sysfs error handling
      - Fix uninitialized xprt_create_args structure
   - XPRTRDMA:
      - Harden connect and reply handling
   - NFS:
      - Fix EOF updates after fallocate/zero-range
      - Keep PG_UPTODATE clear after read errors in page groups
      - Use nfsi->rwsem to protect traversal of the file lock list
      - Prevent resource leak in nfs_alloc_server()
   - NFSv4:
      - Clear exception state on successful mkdir retry
      - Don't skip revalidate when holding a dir delegation and attrs are stale
   - pNFS:
      - Fix use-after-free in pnfs_update_layout()
      - Defer return_range callbacks until after inode unlock
      - Fix LAYOUTCOMMIT retry loop on OLD_STATEID
      - Reject zero-length r_addr in nfs4_decode_mp_ds_addr
   - NFS/flexfiles:
      - Reject zero-length filehandle version arrays
      - Fix checking if a layout is striped
      - Fixes for honoring FF_FLAGS_NO_IO_THRU_MDS

  Other cleanups and improvements:
   - Remove the fileid field from struct nfs_inode
   - Move long-delayed xprtrdma work onto the system_dfl_long_wq
   - Convert xprtrdma send buffer free list to an llist
   - Show "<redacted>" for cert_serial and privkey_serial mount options"

* tag 'nfs-for-7.2-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (42 commits)
  NFS: Use common error handling code in nfs_alloc_server()
  NFS: Prevent resource leak in nfs_alloc_server()
  NFSv4/pNFS: reject zero-length r_addr in nfs4_decode_mp_ds_addr
  nfs: don't skip revalidate on directory delegation when attrs flagged stale
  xprtrdma: Return sendctx slot after Send preparation failure
  xprtrdma: Repost Receive buffers for malformed replies
  xprtrdma: Sanitize the reply credit grant after parsing
  xprtrdma: Fix bcall rep leak and unbounded peek
  xprtrdma: Resize reply buffers before reposting receives
  xprtrdma: Check frwr_wp_create() during connect
  xprtrdma: Initialize re_id before removal registration
  xprtrdma: Fix ep kref imbalance on ADDR_CHANGE
  xprtrdma: Convert send buffer free list to llist
  NFS: correct CONFIG_NFS_V4 macro name in #endif comment
  nfs: use nfsi->rwsem to protect traversal of the file lock list
  NFSv4.1/pNFS: fix LAYOUTCOMMIT retry loop on OLD_STATEID
  nfs: expose FMODE_NOWAIT for read-only files
  nfs: add nowait version of nfs_start_io_direct
  NFSv4/flexfiles: honor FF_FLAGS_NO_IO_THRU_MDS in pg_get_mirror_count_write
  NFSv4/flexfiles: honor FF_FLAGS_NO_IO_THRU_MDS on fatal DS connect errors
  ...
This commit is contained in:
Linus Torvalds 2026-06-23 18:36:41 -07:00
commit 840ef6c78e
35 changed files with 703 additions and 326 deletions

View File

@ -4288,13 +4288,6 @@ Kernel parameters
Only applies if the softerr mount option is enabled,
and the specified value is >= 0.
nfs.enable_ino64=
[NFS] enable 64-bit inode numbers.
If zero, the NFS client will fake up a 32-bit inode
number for the readdir() and stat() syscalls instead
of returning the full 64-bit number.
The default is to return 64-bit inode numbers.
nfs.idmap_cache_timeout=
[NFS] set the maximum lifetime for idmapper cache
entries.

View File

@ -257,6 +257,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
struct pnfs_layout_hdr *lo;
u32 rv = NFS4ERR_NOMATCHING_LAYOUT;
LIST_HEAD(free_me_list);
bool return_range = false;
ino = nfs_layout_find_inode(clp, &args->cbl_fh, &args->cbl_stateid);
if (IS_ERR(ino)) {
@ -301,13 +302,13 @@ static u32 initiate_file_draining(struct nfs_client *clp,
/* Embrace your forgetfulness! */
rv = NFS4ERR_NOMATCHING_LAYOUT;
if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) {
NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
&args->cbl_range);
}
return_range = true;
}
unlock:
spin_unlock(&ino->i_lock);
if (return_range && NFS_SERVER(ino)->pnfs_curr_ld->return_range)
NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
&args->cbl_range);
pnfs_free_lseg_list(&free_me_list);
/* Free all lsegs that are attached to commit buckets */
nfs_commit_inode(ino, 0);

View File

@ -1063,10 +1063,8 @@ struct nfs_server *nfs_alloc_server(void)
return NULL;
server->s_sysfs_id = ida_alloc(&s_sysfs_ids, GFP_KERNEL);
if (server->s_sysfs_id < 0) {
kfree(server);
return NULL;
}
if (server->s_sysfs_id < 0)
goto free_server;
server->client = server->client_acl = ERR_PTR(-EINVAL);
@ -1088,8 +1086,8 @@ struct nfs_server *nfs_alloc_server(void)
server->io_stats = nfs_alloc_iostats();
if (!server->io_stats) {
kfree(server);
return NULL;
ida_free(&s_sysfs_ids, server->s_sysfs_id);
goto free_server;
}
server->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED;
@ -1103,6 +1101,10 @@ struct nfs_server *nfs_alloc_server(void)
rpc_init_wait_queue(&server->uoc_rpcwaitq, "NFS UOC");
return server;
free_server:
kfree(server);
return NULL;
}
EXPORT_SYMBOL_GPL(nfs_alloc_server);

View File

@ -173,6 +173,7 @@ int nfs4_check_delegation(struct inode *inode, fmode_t type)
static int nfs_delegation_claim_locks(struct nfs4_state *state, const nfs4_stateid *stateid)
{
struct inode *inode = state->inode;
struct nfs_inode *nfsi = NFS_I(inode);
struct file_lock *fl;
struct file_lock_context *flctx = locks_inode_context(inode);
struct list_head *list;
@ -182,6 +183,9 @@ static int nfs_delegation_claim_locks(struct nfs4_state *state, const nfs4_state
goto out;
list = &flctx->flc_posix;
/* Guard against reclaim and new lock/unlock calls */
down_write(&nfsi->rwsem);
spin_lock(&flctx->flc_lock);
restart:
for_each_file_lock(fl, list) {
@ -189,8 +193,10 @@ static int nfs_delegation_claim_locks(struct nfs4_state *state, const nfs4_state
continue;
spin_unlock(&flctx->flc_lock);
status = nfs4_lock_delegation_recall(fl, state, stateid);
if (status < 0)
if (status < 0) {
up_write(&nfsi->rwsem);
goto out;
}
spin_lock(&flctx->flc_lock);
}
if (list == &flctx->flc_posix) {
@ -198,6 +204,7 @@ static int nfs_delegation_claim_locks(struct nfs4_state *state, const nfs4_state
goto restart;
}
spin_unlock(&flctx->flc_lock);
up_write(&nfsi->rwsem);
out:
return status;
}

View File

@ -650,7 +650,7 @@ int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
return 0;
nfsi = NFS_I(inode);
if (entry->fattr->fileid != nfsi->fileid)
if (entry->fattr->fileid != inode->i_ino)
return 0;
if (entry->fh->size && nfs_compare_fh(entry->fh, &nfsi->fh) != 0)
return 0;
@ -1105,7 +1105,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
ent = &array->array[i];
if (!dir_emit(desc->ctx, ent->name, ent->name_len,
nfs_compat_user_ino64(ent->ino), ent->d_type)) {
ent->ino, ent->d_type)) {
desc->eob = true;
break;
}
@ -2301,7 +2301,7 @@ nfs4_lookup_revalidate(struct inode *dir, const struct qstr *name,
return nfs_do_lookup_revalidate(dir, name, dentry, flags);
}
#endif /* CONFIG_NFSV4 */
#endif /* CONFIG_NFS_V4 */
int nfs_atomic_open_v23(struct inode *dir, struct dentry *dentry,
struct file *file, unsigned int open_flags,

View File

@ -466,14 +466,22 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
goto out_release;
}
dreq->l_ctx = l_ctx;
if (!is_sync_kiocb(iocb))
if (!is_sync_kiocb(iocb)) {
dreq->iocb = iocb;
} else if (iocb->ki_flags & IOCB_NOWAIT) {
result = -EAGAIN;
nfs_direct_req_release(dreq);
goto out_release;
}
if (user_backed_iter(iter))
dreq->flags = NFS_ODIRECT_SHOULD_DIRTY;
if (!swap) {
result = nfs_start_io_direct(inode);
if (iocb->ki_flags & IOCB_NOWAIT)
result = nfs_start_io_direct_nowait(inode);
else
result = nfs_start_io_direct(inode);
if (result) {
/* release the reference that would usually be
* consumed by nfs_direct_read_schedule_iovec()

View File

@ -49,14 +49,14 @@ nfs_encode_fh(struct inode *inode, __u32 *p, int *max_len, struct inode *parent)
return FILEID_INVALID;
}
p[FILEID_HIGH_OFF] = NFS_FILEID(inode) >> 32;
p[FILEID_LOW_OFF] = NFS_FILEID(inode);
p[FILEID_HIGH_OFF] = inode->i_ino >> 32;
p[FILEID_LOW_OFF] = inode->i_ino;
p[FILE_I_TYPE_OFF] = inode->i_mode & S_IFMT;
p[len - 1] = 0; /* Padding */
nfs_copy_fh(clnt_fh, server_fh);
*max_len = len;
dprintk("%s: result fh fileid %llu mode %u size %d\n",
__func__, NFS_FILEID(inode), inode->i_mode, *max_len);
__func__, inode->i_ino, inode->i_mode, *max_len);
return *max_len;
}

View File

@ -72,8 +72,12 @@ nfs_file_open(struct inode *inode, struct file *filp)
return res;
res = nfs_open(inode, filp);
if (res == 0)
if (res == 0) {
filp->f_mode |= FMODE_CAN_ODIRECT;
/* flag NOWAIT on read-only files only */
if (!(filp->f_mode & FMODE_WRITE))
filp->f_mode |= FMODE_NOWAIT;
}
return res;
}
@ -166,6 +170,10 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
if (iocb->ki_flags & IOCB_DIRECT)
return nfs_file_direct_read(iocb, to, false);
/* NOWAIT only supported on direct reads */
if (iocb->ki_flags & IOCB_NOWAIT)
return -EAGAIN;
dprintk("NFS: read(%pD2, %zu@%lu)\n",
iocb->ki_filp,
iov_iter_count(to), (unsigned long) iocb->ki_pos);
@ -705,6 +713,12 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
trace_nfs_file_write(iocb, from);
/*
* FMODE_NOWAIT is not set for writable files
*/
if (WARN_ON_ONCE(iocb->ki_flags & IOCB_NOWAIT))
return -EAGAIN;
result = nfs_key_timeout_notify(file, inode);
if (result)
return result;

View File

@ -95,7 +95,7 @@ static void filelayout_reset_write(struct nfs_pgio_header *hdr)
"(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
hdr->task.tk_pid,
hdr->inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(hdr->inode),
(unsigned long long)hdr->inode->i_ino,
hdr->args.count,
(unsigned long long)hdr->args.offset);
@ -112,7 +112,7 @@ static void filelayout_reset_read(struct nfs_pgio_header *hdr)
"(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
hdr->task.tk_pid,
hdr->inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(hdr->inode),
(unsigned long long)hdr->inode->i_ino,
hdr->args.count,
(unsigned long long)hdr->args.offset);
@ -778,6 +778,8 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
static bool
filelayout_lseg_is_striped(const struct nfs4_filelayout_segment *flseg)
{
if (flseg->dsaddr)
return flseg->dsaddr->stripe_count > 1;
return flseg->num_fh > 1;
}

View File

@ -551,6 +551,10 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
if (!p)
goto out_err_free;
fh_count = be32_to_cpup(p);
if (fh_count == 0) {
rc = -EINVAL;
goto out_err_free;
}
dss_info->fh_versions =
kzalloc_objs(struct nfs_fh, fh_count, gfp_flags);
@ -632,6 +636,9 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
if (!p)
goto out_sort_mirrors;
fls->flags = be32_to_cpup(p);
if (fls->flags & FF_FLAGS_NO_IO_THRU_MDS)
set_bit(NFS4_FF_HDR_NO_IO_THRU_MDS,
&FF_LAYOUT_FROM_HDR(lh)->flags);
p = xdr_inline_decode(&stream, 4);
if (!p)
@ -1181,6 +1188,16 @@ ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio,
0, NFS4_MAX_UINT64, IOMODE_RW,
NFS_I(pgio->pg_inode)->layout,
pgio->pg_lseg);
if (NFS_I(pgio->pg_inode)->layout &&
ff_layout_hdr_no_fallback_to_mds(NFS_I(pgio->pg_inode)->layout)) {
/*
* FF_FLAGS_NO_IO_THRU_MDS: no current lseg but the server's
* policy forbids MDS fallback. Surface -EAGAIN so writeback
* retries rather than silently issuing the WRITE via MDS.
*/
pgio->pg_error = -EAGAIN;
goto out;
}
/* no lseg means that pnfs is not in use, so no mirroring here */
nfs_pageio_reset_write_mds(pgio);
out:
@ -1230,7 +1247,7 @@ static void ff_layout_reset_write(struct nfs_pgio_header *hdr, bool retry_pnfs)
"(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
hdr->task.tk_pid,
hdr->inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(hdr->inode),
(unsigned long long)hdr->inode->i_ino,
hdr->args.count,
(unsigned long long)hdr->args.offset);
@ -1243,7 +1260,7 @@ static void ff_layout_reset_write(struct nfs_pgio_header *hdr, bool retry_pnfs)
"(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
hdr->task.tk_pid,
hdr->inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(hdr->inode),
(unsigned long long)hdr->inode->i_ino,
hdr->args.count,
(unsigned long long)hdr->args.offset);
@ -1283,7 +1300,7 @@ static void ff_layout_reset_read(struct nfs_pgio_header *hdr)
"(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
hdr->task.tk_pid,
hdr->inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(hdr->inode),
(unsigned long long)hdr->inode->i_ino,
hdr->args.count,
(unsigned long long)hdr->args.offset);
@ -2200,6 +2217,14 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr)
out_failed:
if (ff_layout_avoid_mds_available_ds(lseg) && !ds_fatal_error)
return PNFS_TRY_AGAIN;
if (ff_layout_no_fallback_to_mds(lseg)) {
/*
* FF_FLAGS_NO_IO_THRU_MDS: force fresh LAYOUTGET,
* never fall through to MDS I/O.
*/
pnfs_error_mark_layout_for_return(hdr->inode, lseg);
return PNFS_TRY_AGAIN;
}
trace_pnfs_mds_fallback_read_pagelist(hdr->inode,
hdr->args.offset, hdr->args.count,
IOMODE_READ, NFS_I(hdr->inode)->layout, lseg);
@ -2285,6 +2310,14 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
out_failed:
if (ff_layout_avoid_mds_available_ds(lseg) && !ds_fatal_error)
return PNFS_TRY_AGAIN;
if (ff_layout_no_fallback_to_mds(lseg)) {
/*
* FF_FLAGS_NO_IO_THRU_MDS: force fresh LAYOUTGET,
* never fall through to MDS I/O.
*/
pnfs_error_mark_layout_for_return(hdr->inode, lseg);
return PNFS_TRY_AGAIN;
}
trace_pnfs_mds_fallback_write_pagelist(hdr->inode,
hdr->args.offset, hdr->args.count,
IOMODE_RW, NFS_I(hdr->inode)->layout, lseg);

View File

@ -112,12 +112,16 @@ struct nfs4_ff_layout_segment {
struct nfs4_ff_layout_mirror *mirror_array[] __counted_by(mirror_array_cnt);
};
/* nfs4_flexfile_layout::flags bit indices */
#define NFS4_FF_HDR_NO_IO_THRU_MDS 0 /* any lseg has had FF_FLAGS_NO_IO_THRU_MDS */
struct nfs4_flexfile_layout {
struct pnfs_layout_hdr generic_hdr;
struct pnfs_ds_commit_info commit_info;
struct list_head mirrors;
struct list_head error_list; /* nfs4_ff_layout_ds_err */
ktime_t last_report_time; /* Layoutstat report times */
unsigned long flags;
};
struct nfs4_flexfile_layoutreturn_args {
@ -184,6 +188,18 @@ ff_layout_no_fallback_to_mds(struct pnfs_layout_segment *lseg)
return FF_LAYOUT_LSEG(lseg)->flags & FF_FLAGS_NO_IO_THRU_MDS;
}
/*
* Sticky hdr-level mirror of FF_FLAGS_NO_IO_THRU_MDS so callers that have
* no current lseg (e.g. between LAYOUTRETURN and the next LAYOUTGET) can
* still honor the no-MDS-fallback policy.
*/
static inline bool
ff_layout_hdr_no_fallback_to_mds(struct pnfs_layout_hdr *lo)
{
return test_bit(NFS4_FF_HDR_NO_IO_THRU_MDS,
&FF_LAYOUT_FROM_HDR(lo)->flags);
}
static inline bool
ff_layout_no_read_on_rw(struct pnfs_layout_segment *lseg)
{

View File

@ -58,21 +58,23 @@
#define NFSDBG_FACILITY NFSDBG_VFS
#define NFS_64_BIT_INODE_NUMBERS_ENABLED 1
static bool enable_ino64;
/* Default is to see 64-bit inode numbers */
static bool enable_ino64 = NFS_64_BIT_INODE_NUMBERS_ENABLED;
static int param_set_enable_ino64(const char *val, const struct kernel_param *kp)
{
pr_notice("enable_ino64 is deprecated and has no effect\n");
return 0;
}
static const struct kernel_param_ops param_ops_enable_ino64 = {
.set = param_set_enable_ino64,
.get = param_get_bool,
};
static int nfs_update_inode(struct inode *, struct nfs_fattr *);
static struct kmem_cache * nfs_inode_cachep;
static inline unsigned long
nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
{
return nfs_fileid_to_ino_t(fattr->fileid);
}
int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
{
if (unlikely(nfs_current_task_exiting()))
@ -84,29 +86,6 @@ int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
}
EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
/**
* nfs_compat_user_ino64 - returns the user-visible inode number
* @fileid: 64-bit fileid
*
* This function returns a 32-bit inode number if the boot parameter
* nfs.enable_ino64 is zero.
*/
u64 nfs_compat_user_ino64(u64 fileid)
{
#ifdef CONFIG_COMPAT
compat_ulong_t ino;
#else
unsigned long ino;
#endif
if (enable_ino64)
return fileid;
ino = fileid;
if (sizeof(ino) < sizeof(fileid))
ino ^= fileid >> (sizeof(fileid)-sizeof(ino)) * 8;
return ino;
}
int nfs_drop_inode(struct inode *inode)
{
return NFS_STALE(inode) || inode_generic_drop(inode);
@ -314,8 +293,7 @@ struct nfs_find_desc {
};
/*
* In NFSv3 we can have 64bit inode numbers. In order to support
* this, and re-exported directories (also seen in NFSv2)
* For re-exported directories (also seen in NFSv2)
* we are forced to allow 2 different inodes to have the same
* i_ino.
*/
@ -326,7 +304,7 @@ nfs_find_actor(struct inode *inode, void *opaque)
struct nfs_fh *fh = desc->fh;
struct nfs_fattr *fattr = desc->fattr;
if (NFS_FILEID(inode) != fattr->fileid)
if (inode->i_ino != fattr->fileid)
return 0;
if (inode_wrong_type(inode, fattr->mode))
return 0;
@ -343,7 +321,7 @@ nfs_init_locked(struct inode *inode, void *opaque)
struct nfs_find_desc *desc = opaque;
struct nfs_fattr *fattr = desc->fattr;
set_nfs_fileid(inode, fattr->fileid);
inode->i_ino = fattr->fileid;
inode->i_mode = fattr->mode;
nfs_copy_fh(NFS_FH(inode), desc->fh);
return 0;
@ -414,13 +392,13 @@ nfs_ilookup(struct super_block *sb, struct nfs_fattr *fattr, struct nfs_fh *fh)
.fattr = fattr,
};
struct inode *inode;
unsigned long hash;
u64 hash;
if (!(fattr->valid & NFS_ATTR_FATTR_FILEID) ||
!(fattr->valid & NFS_ATTR_FATTR_TYPE))
return NULL;
hash = nfs_fattr_to_ino_t(fattr);
hash = fattr->fileid;
inode = ilookup5(sb, hash, nfs_find_actor, &desc);
dprintk("%s: returning %p\n", __func__, inode);
@ -457,7 +435,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
};
struct inode *inode = ERR_PTR(-ENOENT);
u64 fattr_supported = NFS_SB(sb)->fattr_valid;
unsigned long hash;
u64 hash;
nfs_attr_check_mountpoint(sb, fattr);
@ -468,7 +446,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0)
goto out_no_inode;
hash = nfs_fattr_to_ino_t(fattr);
hash = fattr->fileid;
inode = iget5_locked(sb, hash, nfs_find_actor, nfs_init_locked, &desc);
if (inode == NULL) {
@ -480,10 +458,6 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
struct nfs_inode *nfsi = NFS_I(inode);
unsigned long now = jiffies;
/* We set i_ino for the few things that still rely on it,
* such as stat(2) */
inode->i_ino = hash;
/* We can't support update_atime(), since the server will reset it */
inode->i_flags |= S_NOATIME|S_NOCMTIME;
inode->i_mode = fattr->mode;
@ -607,7 +581,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
}
dprintk("NFS: nfs_fhget(%s/%Lu fh_crc=0x%08x ct=%d)\n",
inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(inode),
(unsigned long long)inode->i_ino,
nfs_display_fhandle_hash(fh),
icount_read_once(inode));
@ -1067,7 +1041,6 @@ int nfs_getattr(struct mnt_idmap *idmap, const struct path *path,
stat->result_mask = nfs_get_valid_attrmask(inode) | request_mask;
generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode));
stat->change_cookie = inode_peek_iversion_raw(inode);
stat->attributes_mask |= STATX_ATTR_CHANGE_MONOTONIC;
if (server->change_attr_type != NFS4_CHANGE_TYPE_IS_UNDEFINED)
@ -1385,7 +1358,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
struct nfs_inode *nfsi = NFS_I(inode);
dfprintk(PAGECACHE, "NFS: revalidating (%s/%Lu)\n",
inode->i_sb->s_id, (unsigned long long)NFS_FILEID(inode));
inode->i_sb->s_id, (unsigned long long)inode->i_ino);
trace_nfs_revalidate_inode_enter(inode);
@ -1399,7 +1372,8 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
status = pnfs_sync_inode(inode, false);
if (status)
goto out;
} else if (nfs_have_directory_delegation(inode)) {
} else if (nfs_have_directory_delegation(inode) &&
!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR)) {
status = 0;
goto out;
}
@ -1415,7 +1389,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
if (status != 0) {
dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Lu) getattr failed, error=%d\n",
inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(inode), status);
(unsigned long long)inode->i_ino, status);
switch (status) {
case -ETIMEDOUT:
/* A soft timeout occurred. Use cached information? */
@ -1435,7 +1409,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
if (status) {
dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Lu) refresh failed, error=%d\n",
inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(inode), status);
(unsigned long long)inode->i_ino, status);
goto out;
}
@ -1446,7 +1420,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
dfprintk(PAGECACHE, "NFS: (%s/%Lu) revalidation complete\n",
inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(inode));
(unsigned long long)inode->i_ino);
out:
nfs_free_fattr(fattr);
@ -1495,7 +1469,7 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map
dfprintk(PAGECACHE, "NFS: (%s/%Lu) data cache invalidated\n",
inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(inode));
(unsigned long long)inode->i_ino);
return 0;
}
@ -1687,10 +1661,10 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
if (fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
return 0;
/* Has the inode gone and changed behind our back? */
} else if (nfsi->fileid != fattr->fileid) {
} else if (inode->i_ino != fattr->fileid) {
/* Is this perhaps the mounted-on fileid? */
if ((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) &&
nfsi->fileid == fattr->mounted_on_fileid)
inode->i_ino == fattr->mounted_on_fileid)
return 0;
return -ESTALE;
}
@ -2277,15 +2251,15 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
return 0;
/* Has the inode gone and changed behind our back? */
} else if (nfsi->fileid != fattr->fileid) {
} else if (inode->i_ino != fattr->fileid) {
/* Is this perhaps the mounted-on fileid? */
if ((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) &&
nfsi->fileid == fattr->mounted_on_fileid)
inode->i_ino == fattr->mounted_on_fileid)
return 0;
printk(KERN_ERR "NFS: server %s error: fileid changed\n"
"fsid %s: expected fileid 0x%Lx, got 0x%Lx\n",
NFS_SERVER(inode)->nfs_client->cl_hostname,
inode->i_sb->s_id, (long long)nfsi->fileid,
inode->i_sb->s_id, (long long)inode->i_ino,
(long long)fattr->fileid);
goto out_err;
}
@ -2813,7 +2787,7 @@ static void __exit exit_nfs_fs(void)
MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
MODULE_DESCRIPTION("NFS client support");
MODULE_LICENSE("GPL");
module_param(enable_ino64, bool, 0644);
module_param_cb(enable_ino64, &param_ops_enable_ino64, &enable_ino64, 0644);
module_init(init_nfs_fs)
module_exit(exit_nfs_fs)

View File

@ -535,6 +535,7 @@ extern void nfs_end_io_read(struct inode *inode);
extern __must_check int nfs_start_io_write(struct inode *inode);
extern void nfs_end_io_write(struct inode *inode);
extern __must_check int nfs_start_io_direct(struct inode *inode);
extern __must_check int nfs_start_io_direct_nowait(struct inode *inode);
extern void nfs_end_io_direct(struct inode *inode);
static inline bool nfs_file_io_is_buffered(struct nfs_inode *nfsi)

View File

@ -109,6 +109,16 @@ static void nfs_block_buffered(struct nfs_inode *nfsi, struct inode *inode)
}
}
static int nfs_block_buffered_nowait(struct nfs_inode *nfsi, struct inode *inode)
{
if (!test_bit(NFS_INO_ODIRECT, &nfsi->flags)) {
if (inode->i_mapping->nrpages != 0)
return 1;
set_bit(NFS_INO_ODIRECT, &nfsi->flags);
}
return 0;
}
/**
* nfs_start_io_direct - declare the file is being used for direct i/o
* @inode: file inode
@ -149,6 +159,37 @@ nfs_start_io_direct(struct inode *inode)
return 0;
}
/**
* nfs_start_io_direct_nowait - non-blocking variant of nfs_start_io_direct()
* @inode: file inode
*
* Try to declare that a direct I/O operation is about to start without
* blocking.
* Ensure all buffered I/O is blocked.
* If this could not be done without blocking then returns -EAGAIN.
*/
int
nfs_start_io_direct_nowait(struct inode *inode)
{
struct nfs_inode *nfsi = NFS_I(inode);
if (!down_read_trylock(&inode->i_rwsem))
return -EAGAIN;
if (test_bit(NFS_INO_ODIRECT, &nfsi->flags))
return 0;
up_read(&inode->i_rwsem);
/* Slow path: try to flip NFS_INO_ODIRECT without blocking. */
if (!down_write_trylock(&inode->i_rwsem))
return -EAGAIN;
if (nfs_block_buffered_nowait(nfsi, inode)) {
up_write(&inode->i_rwsem);
return -EAGAIN;
}
downgrade_write(&inode->i_rwsem);
return 0;
}
/**
* nfs_end_io_direct - declare that the direct i/o operation is done
* @inode: file inode

View File

@ -81,12 +81,17 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
status = nfs4_call_sync(server->client, server, msg,
&args.seq_args, &res.seq_res, 0);
if (status == 0) {
if (nfs_should_remove_suid(inode)) {
spin_lock(&inode->i_lock);
loff_t newsize = offset + len;
spin_lock(&inode->i_lock);
if (newsize > i_size_read(inode))
i_size_write(inode, newsize);
nfs_set_cache_invalid(inode, NFS_INO_INVALID_BLOCKS);
if (nfs_should_remove_suid(inode))
nfs_set_cache_invalid(inode,
NFS_INO_REVAL_FORCED | NFS_INO_INVALID_MODE);
spin_unlock(&inode->i_lock);
}
NFS_INO_REVAL_FORCED |
NFS_INO_INVALID_MODE);
spin_unlock(&inode->i_lock);
status = nfs_post_op_update_inode_force_wcc(inode,
res.falloc_fattr);
}

View File

@ -377,7 +377,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
*p++ = htonl(attrs); /* bitmap */
*p++ = htonl(12); /* attribute buffer length */
*p++ = htonl(NF4DIR);
p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry)));
p = xdr_encode_hyper(p, d_inode(dentry)->i_ino);
}
*p++ = xdr_one; /* next */
@ -391,7 +391,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
*p++ = htonl(12); /* attribute buffer length */
*p++ = htonl(NF4DIR);
spin_lock(&dentry->d_lock);
p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry->d_parent)));
p = xdr_encode_hyper(p, d_inode(dentry->d_parent)->i_ino);
spin_unlock(&dentry->d_lock);
readdir->pgbase = (char *)p - (char *)start;
@ -5304,10 +5304,9 @@ static struct dentry *nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
do {
alias = _nfs4_proc_mkdir(dir, dentry, sattr, label, &err);
trace_nfs4_mkdir(dir, &dentry->d_name, err);
err = nfs4_handle_exception(NFS_SERVER(dir), err, &exception);
if (err)
alias = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir),
err,
&exception));
alias = ERR_PTR(err);
} while (exception.retry);
nfs4_label_release_security(label);
@ -7087,7 +7086,6 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
switch (task->tk_status) {
case 0:
renew_lease(calldata->server, calldata->timestamp);
locks_lock_inode_wait(calldata->lsp->ls_state->inode, &calldata->fl);
if (nfs4_update_lock_stateid(calldata->lsp,
&calldata->res.stateid))
break;
@ -7355,11 +7353,6 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
case 0:
renew_lease(NFS_SERVER(d_inode(data->ctx->dentry)),
data->timestamp);
if (data->arg.new_lock && !data->cancelled) {
data->fl.c.flc_flags &= ~(FL_SLEEP | FL_ACCESS);
if (locks_lock_inode_wait(lsp->ls_state->inode, &data->fl) < 0)
goto out_restart;
}
if (data->arg.new_lock_owner != 0) {
nfs_confirm_seqid(&lsp->ls_seqid, 0);
nfs4_stateid_copy(&lsp->ls_stateid, &data->res.stateid);
@ -7470,11 +7463,10 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
msg.rpc_argp = &data->arg;
msg.rpc_resp = &data->res;
task_setup_data.callback_data = data;
if (recovery_type > NFS_LOCK_NEW) {
if (recovery_type == NFS_LOCK_RECLAIM)
data->arg.reclaim = NFS_LOCK_RECLAIM;
} else
data->arg.new_lock = 1;
if (recovery_type == NFS_LOCK_RECLAIM)
data->arg.reclaim = NFS_LOCK_RECLAIM;
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
return PTR_ERR(task);
@ -7584,6 +7576,13 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
up_read(&nfsi->rwsem);
mutex_unlock(&sp->so_delegreturn_mutex);
status = _nfs4_do_setlk(state, cmd, request, NFS_LOCK_NEW);
if (status)
goto out;
down_read(&nfsi->rwsem);
request->c.flc_flags &= ~(FL_SLEEP | FL_ACCESS);
status = locks_lock_inode_wait(state->inode, request);
up_read(&nfsi->rwsem);
out:
request->c.flc_flags = flags;
return status;
@ -9991,6 +9990,38 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
case -NFS4ERR_GRACE: /* loca_recalim always false */
task->tk_status = 0;
break;
case -NFS4ERR_OLD_STATEID: {
u32 old_seqid = be32_to_cpu(data->args.stateid.seqid);
struct pnfs_layout_range range = {
.iomode = IOMODE_ANY,
.offset = 0,
.length = NFS4_MAX_UINT64,
};
if (nfs4_layout_refresh_old_stateid(&data->args.stateid,
&range,
data->args.inode)) {
struct pnfs_layout_hdr *lo;
spin_lock(&data->args.inode->i_lock);
lo = NFS_I(data->args.inode)->layout;
if (lo && pnfs_layout_is_valid(lo) &&
nfs4_stateid_match_other(&data->args.stateid,
&lo->plh_stateid))
pnfs_set_layout_stateid(lo, &data->args.stateid,
NULL, false);
spin_unlock(&data->args.inode->i_lock);
dprintk("%s: refreshed OLD_STATEID inode %llu seq %u->%u\n",
__func__, data->args.inode->i_ino,
old_seqid,
be32_to_cpu(data->args.stateid.seqid));
rpc_restart_call_prepare(task);
return;
}
fallthrough;
}
case 0:
break;
default:

View File

@ -597,13 +597,13 @@ DECLARE_EVENT_CLASS(nfs4_open_event,
__entry->openstateid_hash = 0;
}
if (inode != NULL) {
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
} else {
__entry->fileid = 0;
__entry->fhandle = 0;
}
__entry->dir = NFS_FILEID(d_inode(ctx->dentry->d_parent));
__entry->dir = d_inode(ctx->dentry->d_parent)->i_ino;
__assign_str(name);
),
@ -658,7 +658,7 @@ TRACE_EVENT(nfs4_cached_open,
const struct inode *inode = state->inode;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->fmode = (__force unsigned int)state->state;
__entry->stateid_seq =
@ -703,7 +703,7 @@ TRACE_EVENT(nfs4_close,
const struct inode *inode = state->inode;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->fmode = (__force unsigned int)state->state;
__entry->error = error < 0 ? -error : 0;
@ -759,7 +759,7 @@ DECLARE_EVENT_CLASS(nfs4_lock_event,
__entry->start = request->fl_start;
__entry->end = request->fl_end;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->stateid_seq =
be32_to_cpu(state->stateid.seqid);
@ -831,7 +831,7 @@ TRACE_EVENT(nfs4_set_lock,
__entry->start = request->fl_start;
__entry->end = request->fl_end;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->stateid_seq =
be32_to_cpu(state->stateid.seqid);
@ -922,7 +922,7 @@ TRACE_EVENT(nfs4_state_lock_reclaim,
const struct inode *inode = state->inode;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->state_flags = state->flags;
__entry->lock_flags = lock->ls_flags;
@ -960,7 +960,7 @@ DECLARE_EVENT_CLASS(nfs4_set_delegation_event,
TP_fast_assign(
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->fmode = (__force unsigned int)fmode;
),
@ -1087,7 +1087,7 @@ DECLARE_EVENT_CLASS(nfs4_test_stateid_event,
__entry->error = error < 0 ? -error : 0;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->stateid_seq =
be32_to_cpu(state->stateid.seqid);
@ -1137,7 +1137,7 @@ DECLARE_EVENT_CLASS(nfs4_lookup_event,
TP_fast_assign(
__entry->dev = dir->i_sb->s_dev;
__entry->dir = NFS_FILEID(dir);
__entry->dir = dir->i_ino;
__entry->error = -error;
__assign_str(name);
),
@ -1185,7 +1185,7 @@ TRACE_EVENT(nfs4_lookupp,
TP_fast_assign(
__entry->dev = inode->i_sb->s_dev;
__entry->ino = NFS_FILEID(inode);
__entry->ino = inode->i_ino;
__entry->error = error < 0 ? -error : 0;
),
@ -1220,8 +1220,8 @@ TRACE_EVENT(nfs4_rename,
TP_fast_assign(
__entry->dev = olddir->i_sb->s_dev;
__entry->olddir = NFS_FILEID(olddir);
__entry->newdir = NFS_FILEID(newdir);
__entry->olddir = olddir->i_ino;
__entry->newdir = newdir->i_ino;
__entry->error = error < 0 ? -error : 0;
__assign_str(oldname);
__assign_str(newname);
@ -1258,7 +1258,7 @@ DECLARE_EVENT_CLASS(nfs4_inode_event,
TP_fast_assign(
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->error = error < 0 ? -error : 0;
),
@ -1311,7 +1311,7 @@ DECLARE_EVENT_CLASS(nfs4_inode_stateid_event,
TP_fast_assign(
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->error = error < 0 ? -error : 0;
__entry->stateid_seq =
@ -1421,7 +1421,7 @@ DECLARE_EVENT_CLASS(nfs4_inode_callback_event,
__entry->error = error < 0 ? -error : 0;
__entry->fhandle = nfs_fhandle_hash(fhandle);
if (!IS_ERR_OR_NULL(inode)) {
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->dev = inode->i_sb->s_dev;
} else {
__entry->fileid = 0;
@ -1478,7 +1478,7 @@ DECLARE_EVENT_CLASS(nfs4_inode_stateid_callback_event,
__entry->error = error < 0 ? -error : 0;
__entry->fhandle = nfs_fhandle_hash(fhandle);
if (!IS_ERR_OR_NULL(inode)) {
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->dev = inode->i_sb->s_dev;
} else {
__entry->fileid = 0;
@ -1655,7 +1655,7 @@ DECLARE_EVENT_CLASS(nfs4_read_event,
const struct pnfs_layout_segment *lseg = hdr->lseg;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
__entry->offset = hdr->args.offset;
__entry->arg_count = hdr->args.count;
@ -1727,7 +1727,7 @@ DECLARE_EVENT_CLASS(nfs4_write_event,
const struct pnfs_layout_segment *lseg = hdr->lseg;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
__entry->offset = hdr->args.offset;
__entry->arg_count = hdr->args.count;
@ -1795,7 +1795,7 @@ DECLARE_EVENT_CLASS(nfs4_commit_event,
const struct pnfs_layout_segment *lseg = data->lseg;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
__entry->offset = data->args.offset;
__entry->count = data->args.count;
@ -1857,7 +1857,7 @@ TRACE_EVENT(nfs4_layoutget,
const struct inode *inode = d_inode(ctx->dentry);
const struct nfs4_state *state = ctx->state;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->iomode = args->iomode;
__entry->offset = args->offset;
@ -1957,7 +1957,7 @@ TRACE_EVENT(pnfs_update_layout,
),
TP_fast_assign(
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->pos = pos;
__entry->count = count;
@ -2012,7 +2012,7 @@ DECLARE_EVENT_CLASS(pnfs_layout_event,
),
TP_fast_assign(
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->pos = pos;
__entry->count = count;
@ -2194,7 +2194,7 @@ DECLARE_EVENT_CLASS(nfs4_flexfiles_io_event,
__entry->error = -error;
__entry->nfs_error = hdr->res.op_status;
__entry->fhandle = nfs_fhandle_hash(hdr->args.fh);
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->dev = inode->i_sb->s_dev;
__entry->offset = hdr->args.offset;
__entry->count = hdr->args.count;
@ -2258,7 +2258,7 @@ TRACE_EVENT(ff_layout_commit_error,
__entry->error = -error;
__entry->nfs_error = data->res.op_status;
__entry->fhandle = nfs_fhandle_hash(data->args.fh);
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->dev = inode->i_sb->s_dev;
__entry->offset = data->args.offset;
__entry->count = data->args.count;
@ -2423,7 +2423,7 @@ TRACE_EVENT(nfs4_llseek,
TP_STRUCT__entry(
__field(unsigned long, error)
__field(u32, fhandle)
__field(u32, fileid)
__field(u64, fileid)
__field(dev_t, dev)
__field(int, stateid_seq)
__field(u32, stateid_hash)
@ -2434,10 +2434,9 @@ TRACE_EVENT(nfs4_llseek,
),
TP_fast_assign(
const struct nfs_inode *nfsi = NFS_I(inode);
const struct nfs_fh *fh = args->sa_fh;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->dev = inode->i_sb->s_dev;
__entry->fhandle = nfs_fhandle_hash(fh);
__entry->offset_s = args->sa_offset;
@ -2499,7 +2498,7 @@ DECLARE_EVENT_CLASS(nfs4_sparse_event,
__entry->offset = args->falloc_offset;
__entry->len = args->falloc_length;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__entry->stateid_seq =
be32_to_cpu(args->falloc_stateid.seqid);
@ -2568,14 +2567,11 @@ TRACE_EVENT(nfs4_copy,
),
TP_fast_assign(
const struct nfs_inode *src_nfsi = NFS_I(src_inode);
const struct nfs_inode *dst_nfsi = NFS_I(dst_inode);
__entry->src_fileid = src_nfsi->fileid;
__entry->src_fileid = src_inode->i_ino;
__entry->src_dev = src_inode->i_sb->s_dev;
__entry->src_fhandle = nfs_fhandle_hash(args->src_fh);
__entry->src_offset = args->src_pos;
__entry->dst_fileid = dst_nfsi->fileid;
__entry->dst_fileid = dst_inode->i_ino;
__entry->dst_dev = dst_inode->i_sb->s_dev;
__entry->dst_fhandle = nfs_fhandle_hash(args->dst_fh);
__entry->dst_offset = args->dst_pos;
@ -2666,14 +2662,11 @@ TRACE_EVENT(nfs4_clone,
),
TP_fast_assign(
const struct nfs_inode *src_nfsi = NFS_I(src_inode);
const struct nfs_inode *dst_nfsi = NFS_I(dst_inode);
__entry->src_fileid = src_nfsi->fileid;
__entry->src_fileid = src_inode->i_ino;
__entry->src_dev = src_inode->i_sb->s_dev;
__entry->src_fhandle = nfs_fhandle_hash(args->src_fh);
__entry->src_offset = args->src_offset;
__entry->dst_fileid = dst_nfsi->fileid;
__entry->dst_fileid = dst_inode->i_ino;
__entry->dst_dev = dst_inode->i_sb->s_dev;
__entry->dst_fhandle = nfs_fhandle_hash(args->dst_fh);
__entry->dst_offset = args->dst_offset;
@ -2724,7 +2717,7 @@ TRACE_EVENT(nfs4_copy_notify,
TP_STRUCT__entry(
__field(unsigned long, error)
__field(u32, fhandle)
__field(u32, fileid)
__field(u64, fileid)
__field(dev_t, dev)
__field(int, stateid_seq)
__field(u32, stateid_hash)
@ -2733,9 +2726,7 @@ TRACE_EVENT(nfs4_copy_notify,
),
TP_fast_assign(
const struct nfs_inode *nfsi = NFS_I(inode);
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->dev = inode->i_sb->s_dev;
__entry->fhandle = nfs_fhandle_hash(args->cna_src_fh);
__entry->stateid_seq =
@ -2830,7 +2821,7 @@ DECLARE_EVENT_CLASS(nfs4_xattr_event,
TP_fast_assign(
__entry->error = error < 0 ? -error : 0;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
__assign_str(name);
),

View File

@ -80,7 +80,7 @@ DECLARE_EVENT_CLASS(nfs_inode_event,
TP_fast_assign(
const struct nfs_inode *nfsi = NFS_I(inode);
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->version = inode_peek_iversion_raw(inode);
__entry->cache_validity = nfsi->cache_validity;
@ -121,7 +121,7 @@ DECLARE_EVENT_CLASS(nfs_inode_event_done,
const struct nfs_inode *nfsi = NFS_I(inode);
__entry->error = error < 0 ? -error : 0;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->type = nfs_umode_to_dtype(inode->i_mode);
__entry->version = inode_peek_iversion_raw(inode);
@ -211,7 +211,7 @@ TRACE_EVENT(nfs_access_exit,
const struct nfs_inode *nfsi = NFS_I(inode);
__entry->error = error < 0 ? -error : 0;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->type = nfs_umode_to_dtype(inode->i_mode);
__entry->version = inode_peek_iversion_raw(inode);
@ -265,7 +265,7 @@ DECLARE_EVENT_CLASS(nfs_update_size_class,
__entry->dev = inode->i_sb->s_dev;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->version = inode_peek_iversion_raw(inode);
__entry->cur_size = i_size_read(inode);
__entry->new_size = new_size;
@ -317,7 +317,7 @@ DECLARE_EVENT_CLASS(nfs_inode_range_event,
__entry->dev = inode->i_sb->s_dev;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->version = inode_peek_iversion_raw(inode);
__entry->range_start = range_start;
__entry->range_end = range_end;
@ -371,7 +371,7 @@ DECLARE_EVENT_CLASS(nfs_readdir_event,
const struct nfs_inode *nfsi = NFS_I(dir);
__entry->dev = dir->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = dir->i_ino;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->version = inode_peek_iversion_raw(dir);
if (cookie != 0)
@ -429,9 +429,9 @@ DECLARE_EVENT_CLASS(nfs_lookup_event,
TP_fast_assign(
__entry->dev = dir->i_sb->s_dev;
__entry->dir = NFS_FILEID(dir);
__entry->dir = dir->i_ino;
__entry->flags = flags;
__entry->fileid = d_is_negative(dentry) ? 0 : NFS_FILEID(d_inode(dentry));
__entry->fileid = d_is_negative(dentry) ? 0 : d_inode(dentry)->i_ino;
__assign_str(name);
),
@ -476,10 +476,10 @@ DECLARE_EVENT_CLASS(nfs_lookup_event_done,
TP_fast_assign(
__entry->dev = dir->i_sb->s_dev;
__entry->dir = NFS_FILEID(dir);
__entry->dir = dir->i_ino;
__entry->error = error < 0 ? -error : 0;
__entry->flags = flags;
__entry->fileid = d_is_negative(dentry) ? 0 : NFS_FILEID(d_inode(dentry));
__entry->fileid = d_is_negative(dentry) ? 0 : d_inode(dentry)->i_ino;
__assign_str(name);
),
@ -532,7 +532,7 @@ TRACE_EVENT(nfs_atomic_open_enter,
TP_fast_assign(
__entry->dev = dir->i_sb->s_dev;
__entry->dir = NFS_FILEID(dir);
__entry->dir = dir->i_ino;
__entry->flags = flags;
__entry->fmode = (__force unsigned long)ctx->mode;
__assign_str(name);
@ -571,7 +571,7 @@ TRACE_EVENT(nfs_atomic_open_exit,
TP_fast_assign(
__entry->error = -error;
__entry->dev = dir->i_sb->s_dev;
__entry->dir = NFS_FILEID(dir);
__entry->dir = dir->i_ino;
__entry->flags = flags;
__entry->fmode = (__force unsigned long)ctx->mode;
__assign_str(name);
@ -608,7 +608,7 @@ TRACE_EVENT(nfs_create_enter,
TP_fast_assign(
__entry->dev = dir->i_sb->s_dev;
__entry->dir = NFS_FILEID(dir);
__entry->dir = dir->i_ino;
__entry->flags = flags;
__assign_str(name);
),
@ -644,7 +644,7 @@ TRACE_EVENT(nfs_create_exit,
TP_fast_assign(
__entry->error = -error;
__entry->dev = dir->i_sb->s_dev;
__entry->dir = NFS_FILEID(dir);
__entry->dir = dir->i_ino;
__entry->flags = flags;
__assign_str(name);
),
@ -676,7 +676,7 @@ DECLARE_EVENT_CLASS(nfs_directory_event,
TP_fast_assign(
__entry->dev = dir->i_sb->s_dev;
__entry->dir = NFS_FILEID(dir);
__entry->dir = dir->i_ino;
__assign_str(name);
),
@ -714,7 +714,7 @@ DECLARE_EVENT_CLASS(nfs_directory_event_done,
TP_fast_assign(
__entry->dev = dir->i_sb->s_dev;
__entry->dir = NFS_FILEID(dir);
__entry->dir = dir->i_ino;
__entry->error = error < 0 ? -error : 0;
__assign_str(name);
),
@ -768,8 +768,8 @@ TRACE_EVENT(nfs_link_enter,
TP_fast_assign(
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->dir = NFS_FILEID(dir);
__entry->fileid = inode->i_ino;
__entry->dir = dir->i_ino;
__assign_str(name);
),
@ -803,8 +803,8 @@ TRACE_EVENT(nfs_link_exit,
TP_fast_assign(
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = NFS_FILEID(inode);
__entry->dir = NFS_FILEID(dir);
__entry->fileid = inode->i_ino;
__entry->dir = dir->i_ino;
__entry->error = error < 0 ? -error : 0;
__assign_str(name);
),
@ -840,8 +840,8 @@ DECLARE_EVENT_CLASS(nfs_rename_event,
TP_fast_assign(
__entry->dev = old_dir->i_sb->s_dev;
__entry->old_dir = NFS_FILEID(old_dir);
__entry->new_dir = NFS_FILEID(new_dir);
__entry->old_dir = old_dir->i_ino;
__entry->new_dir = new_dir->i_ino;
__assign_str(old_name);
__assign_str(new_name);
),
@ -889,8 +889,8 @@ DECLARE_EVENT_CLASS(nfs_rename_event_done,
TP_fast_assign(
__entry->dev = old_dir->i_sb->s_dev;
__entry->error = -error;
__entry->old_dir = NFS_FILEID(old_dir);
__entry->new_dir = NFS_FILEID(new_dir);
__entry->old_dir = old_dir->i_ino;
__entry->new_dir = new_dir->i_ino;
__assign_str(old_name);
__assign_str(new_name);
),
@ -943,7 +943,7 @@ TRACE_EVENT(nfs_sillyrename_unlink,
struct inode *dir = d_inode(data->dentry->d_parent);
size_t len = data->args.name.len;
__entry->dev = dir->i_sb->s_dev;
__entry->dir = NFS_FILEID(dir);
__entry->dir = dir->i_ino;
__entry->error = -error;
memcpy(__get_str(name),
data->args.name.name, len);
@ -981,7 +981,7 @@ DECLARE_EVENT_CLASS(nfs_folio_event,
const struct nfs_inode *nfsi = NFS_I(inode);
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->version = inode_peek_iversion_raw(inode);
__entry->offset = offset;
@ -1031,7 +1031,7 @@ DECLARE_EVENT_CLASS(nfs_folio_event_done,
const struct nfs_inode *nfsi = NFS_I(inode);
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->version = inode_peek_iversion_raw(inode);
__entry->offset = offset;
@ -1109,7 +1109,7 @@ DECLARE_EVENT_CLASS(nfs_kiocb_event,
const struct nfs_inode *nfsi = NFS_I(inode);
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->version = inode_peek_iversion_raw(inode);
__entry->offset = iocb->ki_pos;
@ -1160,7 +1160,7 @@ TRACE_EVENT(nfs_aop_readahead,
const struct nfs_inode *nfsi = NFS_I(inode);
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->version = inode_peek_iversion_raw(inode);
__entry->offset = pos;
@ -1199,7 +1199,7 @@ TRACE_EVENT(nfs_aop_readahead_done,
const struct nfs_inode *nfsi = NFS_I(inode);
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->version = inode_peek_iversion_raw(inode);
__entry->nr_pages = nr_pages;
@ -1239,7 +1239,7 @@ TRACE_EVENT(nfs_initiate_read,
__entry->offset = hdr->args.offset;
__entry->count = hdr->args.count;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
),
@ -1284,7 +1284,7 @@ TRACE_EVENT(nfs_readpage_done,
__entry->res_count = hdr->res.count;
__entry->eof = hdr->res.eof;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
),
@ -1330,7 +1330,7 @@ TRACE_EVENT(nfs_readpage_short,
__entry->res_count = hdr->res.count;
__entry->eof = hdr->res.eof;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
),
@ -1377,7 +1377,7 @@ TRACE_EVENT(nfs_pgio_error,
__entry->arg_count = hdr->args.count;
__entry->res_count = hdr->res.count;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
),
@ -1416,7 +1416,7 @@ TRACE_EVENT(nfs_initiate_write,
__entry->count = hdr->args.count;
__entry->stable = hdr->args.stable;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
),
@ -1467,7 +1467,7 @@ TRACE_EVENT(nfs_writeback_done,
&verf->verifier,
NFS4_VERIFIER_SIZE);
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
),
@ -1507,7 +1507,7 @@ DECLARE_EVENT_CLASS(nfs_page_class,
const struct nfs_inode *nfsi = NFS_I(inode);
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->req = req;
__entry->offset = req_offset(req);
@ -1555,7 +1555,7 @@ DECLARE_EVENT_CLASS(nfs_page_error_class,
TP_fast_assign(
const struct nfs_inode *nfsi = NFS_I(inode);
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
__entry->offset = req_offset(req);
__entry->count = req->wb_bytes;
@ -1609,7 +1609,7 @@ TRACE_EVENT(nfs_initiate_commit,
__entry->offset = data->args.offset;
__entry->count = data->args.count;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
),
@ -1655,7 +1655,7 @@ TRACE_EVENT(nfs_commit_done,
&verf->verifier,
NFS4_VERIFIER_SIZE);
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
),
@ -1701,7 +1701,7 @@ DECLARE_EVENT_CLASS(nfs_direct_req_class,
const struct nfs_fh *fh = &nfsi->fh;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
__entry->offset = dreq->io_start;
__entry->count = dreq->count;
@ -1765,7 +1765,7 @@ DECLARE_EVENT_CLASS(nfs_local_dio_class,
const struct nfs_fh *fh = &nfsi->fh;
__entry->dev = inode->i_sb->s_dev;
__entry->fileid = nfsi->fileid;
__entry->fileid = inode->i_ino;
__entry->fhandle = nfs_fhandle_hash(fh);
__entry->offset = offset;
__entry->count = count;

View File

@ -759,7 +759,7 @@ int nfs_initiate_pgio(struct rpc_clnt *clnt, struct nfs_pgio_header *hdr,
dprintk("NFS: initiated pgio call "
"(req %s/%llu, %u bytes @ offset %llu)\n",
hdr->inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(hdr->inode),
(unsigned long long)hdr->inode->i_ino,
hdr->args.count,
(unsigned long long)hdr->args.offset);

View File

@ -1463,8 +1463,6 @@ _pnfs_return_layout(struct inode *ino)
pnfs_clear_layoutcommit(ino, &tmp_list);
pnfs_mark_matching_lsegs_return(lo, &tmp_list, &range, 0);
if (NFS_SERVER(ino)->pnfs_curr_ld->return_range)
NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo, &range);
/* Don't send a LAYOUTRETURN if list was initially empty */
if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags) ||
@ -1476,6 +1474,8 @@ _pnfs_return_layout(struct inode *ino)
send = pnfs_prepare_layoutreturn(lo, &stateid, &cred, NULL);
spin_unlock(&ino->i_lock);
if (NFS_SERVER(ino)->pnfs_curr_ld->return_range)
NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo, &range);
if (send)
status = pnfs_send_layoutreturn(lo, &stateid, &cred, IOMODE_ANY,
0);
@ -2229,11 +2229,11 @@ pnfs_update_layout(struct inode *ino,
dprintk("%s wait for layoutreturn\n", __func__);
lseg = ERR_PTR(pnfs_prepare_to_retry_layoutget(lo));
if (!IS_ERR(lseg)) {
pnfs_put_layout_hdr(lo);
dprintk("%s retrying\n", __func__);
trace_pnfs_update_layout(ino, pos, count, iomode, lo,
lseg,
PNFS_UPDATE_LAYOUT_RETRY);
pnfs_put_layout_hdr(lo);
goto lookup_again;
}
trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
@ -2373,7 +2373,7 @@ pnfs_update_layout(struct inode *ino,
dprintk("%s: inode %s/%llu pNFS layout segment %s for "
"(%s, offset: %llu, length: %llu)\n",
__func__, ino->i_sb->s_id,
(unsigned long long)NFS_FILEID(ino),
(unsigned long long)ino->i_ino,
IS_ERR_OR_NULL(lseg) ? "not found" : "found",
iomode==IOMODE_RW ? "read/write" : "read-only",
(unsigned long long)pos,

View File

@ -1075,14 +1075,14 @@ nfs4_decode_mp_ds_addr(struct net *net, struct xdr_stream *xdr, gfp_t gfp_flags)
/* r_netid */
nlen = xdr_stream_decode_string_dup(xdr, &netid, XDR_MAX_NETOBJ,
gfp_flags);
if (unlikely(nlen < 0))
if (unlikely(nlen <= 0))
goto out_err;
/* r_addr: ip/ip6addr with port in dec octets - see RFC 5665 */
/* port is ".ABC.DEF", 8 chars max */
rlen = xdr_stream_decode_string_dup(xdr, &buf, INET6_ADDRSTRLEN +
IPV6_SCOPE_ID_LEN + 8, gfp_flags);
if (unlikely(rlen < 0))
if (unlikely(rlen <= 0))
goto out_free_netid;
/* replace port '.' with '-' */

View File

@ -132,10 +132,32 @@ static void nfs_readpage_release(struct nfs_page *req, int error)
static void nfs_page_group_set_uptodate(struct nfs_page *req)
{
if (nfs_page_group_sync_on_bit(req, PG_UPTODATE))
bool uptodate = false;
nfs_page_group_lock(req);
if (!test_bit(PG_READ_FAILED, &req->wb_head->wb_flags) &&
nfs_page_group_sync_on_bit_locked(req, PG_UPTODATE))
uptodate = true;
nfs_page_group_unlock(req);
if (uptodate)
folio_mark_uptodate(nfs_page_to_folio(req));
}
static void nfs_page_group_mark_read_failed(struct nfs_page *req)
{
struct nfs_page *tmp;
nfs_page_group_lock(req);
set_bit(PG_READ_FAILED, &req->wb_head->wb_flags);
tmp = req;
do {
clear_bit(PG_UPTODATE, &tmp->wb_flags);
tmp = tmp->wb_this_page;
} while (tmp != req);
nfs_page_group_unlock(req);
}
static void nfs_read_completion(struct nfs_pgio_header *hdr)
{
unsigned long bytes = 0;
@ -172,6 +194,7 @@ static void nfs_read_completion(struct nfs_pgio_header *hdr)
if (bytes <= hdr->good_bytes)
nfs_page_group_set_uptodate(req);
else {
nfs_page_group_mark_read_failed(req);
error = hdr->error;
xchg(&nfs_req_openctx(req)->error, error);
}

View File

@ -509,6 +509,10 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
default:
break;
}
if (clp->cl_xprtsec.cert_serial)
seq_puts(m, ",cert_serial=<redacted>");
if (clp->cl_xprtsec.privkey_serial)
seq_puts(m, ",privkey_serial=<redacted>");
if (version != 4)
nfs_show_mountd_options(m, nfss, showdefaults);

View File

@ -460,7 +460,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
goto out;
fileid = NFS_FILEID(d_inode(dentry));
fileid = d_inode(dentry)->i_ino;
sdentry = NULL;
do {

View File

@ -1817,7 +1817,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
dprintk("NFS: commit (%s/%llu %d@%lld)",
nfs_req_openctx(req)->dentry->d_sb->s_id,
(unsigned long long)NFS_FILEID(d_inode(nfs_req_openctx(req)->dentry)),
(unsigned long long)d_inode(nfs_req_openctx(req)->dentry)->i_ino,
req->wb_bytes,
(long long)req_offset(req));
if (status < 0) {

View File

@ -145,11 +145,6 @@ struct nfs4_xattr_cache;
* nfs fs inode data in memory
*/
struct nfs_inode {
/*
* The 64bit 'inode number'
*/
__u64 fileid;
/*
* NFS file handle
*/
@ -394,16 +389,6 @@ static inline int NFS_STALE(const struct inode *inode)
return test_bit(NFS_INO_STALE, &NFS_I(inode)->flags);
}
static inline __u64 NFS_FILEID(const struct inode *inode)
{
return NFS_I(inode)->fileid;
}
static inline void set_nfs_fileid(struct inode *inode, __u64 fileid)
{
NFS_I(inode)->fileid = fileid;
}
static inline void nfs_mark_for_revalidate(struct inode *inode)
{
struct nfs_inode *nfsi = NFS_I(inode);
@ -473,7 +458,6 @@ extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context
extern void nfs_file_clear_open_context(struct file *flip);
extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx);
extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);
extern u64 nfs_compat_user_ino64(u64 fileid);
extern void nfs_fattr_init(struct nfs_fattr *fattr);
extern void nfs_fattr_set_barrier(struct nfs_fattr *fattr);
extern unsigned long nfs_inc_attr_generation_counter(void);
@ -668,15 +652,6 @@ static inline loff_t nfs_size_to_loff_t(__u64 size)
return min_t(u64, size, OFFSET_MAX);
}
static inline ino_t
nfs_fileid_to_ino_t(u64 fileid)
{
ino_t ino = (ino_t) fileid;
if (sizeof(ino_t) < sizeof(u64))
ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8;
return ino;
}
static inline void nfs_ooo_clear(struct nfs_inode *nfsi)
{
nfsi->cache_validity &= ~NFS_INO_DATA_INVAL_DEFER;

View File

@ -33,6 +33,7 @@ enum {
PG_TEARDOWN, /* page group sync for destroy */
PG_UNLOCKPAGE, /* page group sync bit in read path */
PG_UPTODATE, /* page group sync bit in read path */
PG_READ_FAILED, /* page group saw a read error */
PG_WB_END, /* page group sync bit in write path */
PG_REMOVE, /* page group sync bit in write path */
PG_CONTENDED1, /* Is someone waiting for a lock? */

View File

@ -582,7 +582,6 @@ struct nfs_lock_args {
struct nfs_lowner lock_owner;
unsigned char block : 1;
unsigned char reclaim : 1;
unsigned char new_lock : 1;
unsigned char new_lock_owner : 1;
};

View File

@ -327,7 +327,7 @@ static ssize_t rpc_sysfs_xprt_switch_add_xprt_store(struct kobject *kobj,
{
struct rpc_xprt_switch *xprt_switch =
rpc_sysfs_xprt_switch_kobj_get_xprt(kobj);
struct xprt_create xprt_create_args;
struct xprt_create xprt_create_args = {};
struct rpc_xprt *xprt, *new;
if (!xprt_switch)
@ -348,7 +348,7 @@ static ssize_t rpc_sysfs_xprt_switch_add_xprt_store(struct kobject *kobj,
xprt_create_args.reconnect_timeout = xprt->max_reconnect_timeout;
new = xprt_create_transport(&xprt_create_args);
if (IS_ERR_OR_NULL(new)) {
if (IS_ERR(new)) {
count = PTR_ERR(new);
goto out_put_xprt;
}

View File

@ -159,9 +159,7 @@ void xprt_rdma_bc_free_rqst(struct rpc_rqst *rqst)
rpcrdma_rep_put(&r_xprt->rx_buf, rep);
req->rl_reply = NULL;
spin_lock(&xprt->bc_pa_lock);
list_add_tail(&rqst->rq_bc_pa_list, &xprt->bc_pa_list);
spin_unlock(&xprt->bc_pa_lock);
rpcrdma_req_put(req);
xprt_put(xprt);
}
@ -203,6 +201,7 @@ static struct rpc_rqst *rpcrdma_bc_rqst_get(struct rpcrdma_xprt *r_xprt)
rqst->rq_xprt = xprt;
__set_bit(RPC_BC_PA_IN_USE, &rqst->rq_bc_pa_state);
xdr_buf_init(&rqst->rq_snd_buf, rdmab_data(req->rl_sendbuf), size);
kref_init(&req->rl_kref);
return rqst;
}

View File

@ -474,7 +474,7 @@ int frwr_send(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
++num_wrs;
}
if ((kref_read(&req->rl_kref) > 1) || num_wrs > ep->re_send_count) {
if (req->rl_sendctx->sc_unmap_count || num_wrs > ep->re_send_count) {
send_wr->send_flags |= IB_SEND_SIGNALED;
ep->re_send_count = min_t(unsigned int, ep->re_send_batch,
num_wrs - ep->re_send_count);

View File

@ -467,29 +467,11 @@ static int rpcrdma_encode_reply_chunk(struct rpcrdma_xprt *r_xprt,
return 0;
}
static void rpcrdma_sendctx_done(struct kref *kref)
{
struct rpcrdma_req *req =
container_of(kref, struct rpcrdma_req, rl_kref);
struct rpcrdma_rep *rep = req->rl_reply;
rpcrdma_complete_rqst(rep);
rep->rr_rxprt->rx_stats.reply_waits_for_send++;
}
/**
* rpcrdma_sendctx_unmap - DMA-unmap Send buffer
* @sc: sendctx containing SGEs to unmap
*
*/
void rpcrdma_sendctx_unmap(struct rpcrdma_sendctx *sc)
static void rpcrdma_sendctx_dma_unmap(struct rpcrdma_sendctx *sc)
{
struct rpcrdma_regbuf *rb = sc->sc_req->rl_sendbuf;
struct ib_sge *sge;
if (!sc->sc_unmap_count)
return;
/* The first two SGEs contain the transport header and
* the inline buffer. These are always left mapped so
* they can be cheaply re-used.
@ -498,8 +480,33 @@ void rpcrdma_sendctx_unmap(struct rpcrdma_sendctx *sc)
++sge, --sc->sc_unmap_count)
ib_dma_unmap_page(rdmab_device(rb), sge->addr, sge->length,
DMA_TO_DEVICE);
}
kref_put(&sc->sc_req->rl_kref, rpcrdma_sendctx_done);
/**
* rpcrdma_sendctx_unmap - DMA-unmap Send buffer and release Send owner
* @sc: sendctx containing SGEs to unmap
*
*/
void rpcrdma_sendctx_unmap(struct rpcrdma_sendctx *sc)
{
struct rpcrdma_req *req = sc->sc_req;
rpcrdma_sendctx_dma_unmap(sc);
sc->sc_req = NULL;
req->rl_sendctx = NULL;
rpcrdma_req_put(req);
}
/* No Send was posted. Release DMA mappings prepared for this
* sendctx, but leave the request reference count alone.
*/
static void rpcrdma_sendctx_cancel(struct rpcrdma_sendctx *sc)
{
struct rpcrdma_req *req = sc->sc_req;
rpcrdma_sendctx_dma_unmap(sc);
sc->sc_req = NULL;
req->rl_sendctx = NULL;
}
/* Prepare an SGE for the RPC-over-RDMA transport header.
@ -691,8 +698,6 @@ static bool rpcrdma_prepare_noch_mapped(struct rpcrdma_xprt *r_xprt,
tail->iov_len))
return false;
if (req->rl_sendctx->sc_unmap_count)
kref_get(&req->rl_kref);
return true;
}
@ -722,7 +727,6 @@ static bool rpcrdma_prepare_readch(struct rpcrdma_xprt *r_xprt,
len -= len & 3;
if (!rpcrdma_prepare_tail_iov(req, xdr, page_base, len))
return false;
kref_get(&req->rl_kref);
}
return true;
@ -743,6 +747,7 @@ inline int rpcrdma_prepare_send_sges(struct rpcrdma_xprt *r_xprt,
struct xdr_buf *xdr,
enum rpcrdma_chunktype rtype)
{
struct rpcrdma_sendctx *sc;
int ret;
ret = -EAGAIN;
@ -751,7 +756,6 @@ inline int rpcrdma_prepare_send_sges(struct rpcrdma_xprt *r_xprt,
goto out_nosc;
req->rl_sendctx->sc_unmap_count = 0;
req->rl_sendctx->sc_req = req;
kref_init(&req->rl_kref);
req->rl_wr.wr_cqe = &req->rl_sendctx->sc_cqe;
req->rl_wr.sg_list = req->rl_sendctx->sc_sges;
req->rl_wr.num_sge = 0;
@ -779,10 +783,16 @@ inline int rpcrdma_prepare_send_sges(struct rpcrdma_xprt *r_xprt,
goto out_unmap;
}
/* The Send-side owner releases this reference when the
* Send has completed.
*/
kref_get(&req->rl_kref);
return 0;
out_unmap:
rpcrdma_sendctx_unmap(req->rl_sendctx);
sc = req->rl_sendctx;
rpcrdma_sendctx_cancel(sc);
rpcrdma_sendctx_unget_locked(r_xprt, sc);
out_nosc:
trace_xprtrdma_prepsend_failed(&req->rl_slot, ret);
return ret;
@ -1081,6 +1091,8 @@ rpcrdma_is_bcall(struct rpcrdma_xprt *r_xprt, struct rpcrdma_rep *rep)
/* Peek at stream contents without advancing. */
p = xdr_inline_decode(xdr, 0);
if ((char *)xdr->end - (char *)p < 5 * XDR_UNIT)
return false;
/* Chunk lists */
if (xdr_item_is_present(p++))
@ -1105,7 +1117,7 @@ rpcrdma_is_bcall(struct rpcrdma_xprt *r_xprt, struct rpcrdma_rep *rep)
*/
p = xdr_inline_decode(xdr, 3 * sizeof(*p));
if (unlikely(!p))
return true;
return false;
rpcrdma_bc_receive_call(r_xprt, rep);
return true;
@ -1329,6 +1341,11 @@ void rpcrdma_complete_rqst(struct rpcrdma_rep *rep)
struct rpc_rqst *rqst = rep->rr_rqst;
int status;
/* I3: rl_registered has been drained by frwr_unmap before
* complete_rqst runs.
*/
WARN_ON_ONCE(!list_empty(&rpcr_to_rdmar(rqst)->rl_registered));
switch (rep->rr_proc) {
case rdma_msg:
status = rpcrdma_decode_msg(r_xprt, rep, rqst);
@ -1360,13 +1377,69 @@ void rpcrdma_complete_rqst(struct rpcrdma_rep *rep)
goto out;
}
static void rpcrdma_reply_done(struct kref *kref)
{
struct rpcrdma_req *req =
container_of(kref, struct rpcrdma_req, rl_kref);
rpcrdma_complete_rqst(req->rl_reply);
}
/* Reply-side ownership invariants
*
* I1 (Receive WR ownership). A struct rpcrdma_rep is owned by the
* HCA between ib_post_recv() and the matching Receive completion.
* After ib_dma_sync_single_for_cpu() in rpcrdma_wc_receive() it is
* owned by the CPU until rpcrdma_rep_put() returns it to
* rb_free_reps; a rep on rb_free_reps is not re-posted until
* rpcrdma_post_recvs() pulls it off. Asserted: rpcrdma_post_recvs()
* WARNs that a pulled rep has rr_rqst == NULL.
*
* I2 (rep attachment). While req->rl_reply == rep, the rep cannot be
* re-posted. rpcrdma_reply_put() NULLs req->rl_reply before handing
* the rep to rpcrdma_rep_put(). Asserted: rpcrdma_reply_put() WARNs
* that rl_reply is NULL after the put.
*
* I3 (Registered-MR fence). On entry to rpcrdma_complete_rqst() every
* MR that was on req->rl_registered has had its rkey invalidated
* (remotely via IB_WC_WITH_INVALIDATE or locally via IB_WR_LOCAL_INV)
* and its pages ib_dma_unmap_sg()'d. The LocalInv chain is posted
* on a single QP; strong send-queue ordering makes the last
* completion (frwr_wc_localinv_done) observe the
* ib_dma_unmap_sg() that ran from each earlier completion's
* frwr_mr_put() before complete_rqst is called. The inline
* frwr_reminv() path unmaps its one MR synchronously before
* rpcrdma_reply_handler() reaches complete_rqst. Asserted:
* rpcrdma_complete_rqst() WARNs that rl_registered is empty.
*
* I4 (Send-buffer release). req->rl_kref carries two unconditional
* owners while a Send is outstanding: the RPC-layer reference (set
* at xprt_rdma_alloc_slot / xprt_rdma_bc_rqst_get / rpcrdma_req_release
* pool-entry) and the Send-side reference (kref_get() in
* rpcrdma_prepare_send_sges()). rpcrdma_req_release() runs only
* after both have dropped, so the req does not return to its free
* pool until rpcrdma_sendctx_unmap() has fired -- the HCA has
* released the send buffer before the req can be reused. Asserted:
* rpcrdma_req_release() WARNs that rl_sendctx is NULL.
*
* I5 (req lifecycle). A req is owned by the RPC layer between slot
* acquisition and the matching xprt_rdma_free_slot() (or, for the
* backchannel, xprt_rdma_bc_free_rqst()). While owned, rl_kref >= 1.
* The pools (rb_send_bufs, bc_pa_list, backlog wake target) never
* contain a req with outstanding Send-side or Reply-side work.
*
* Non-hazards. The following claims have been raised by adversarial
* review and are each closed by the invariants above:
*
* * "Reply completes the RPC while the HCA still holds the send
* buffer" -- excluded by I4. The Send-side kref reference is held
* until rpcrdma_sendctx_unmap() runs from Send completion.
*
* * "Signal-driven release races the in-flight Send" -- same
* resolution. xprt_rdma_free() does not touch rl_kref; the
* Send-side reference keeps the req out of its pool until Send
* completion fires.
*
* * "Receive completion races rep reuse" -- excluded by I1. A rep
* is on rb_free_reps only after rpcrdma_rep_put() has been called
* and rpcrdma_post_recvs() owns the next transition back to the HCA.
*
* * "Pages still DMA-mapped when call_decode reads them" -- excluded
* by I3. The matching ib_dma_unmap_sg() for every MR has run on
* the same CPU thread that calls rpcrdma_complete_rqst().
*/
/**
* rpcrdma_reply_handler - Process received RPC/RDMA messages
@ -1402,6 +1475,14 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
credits = be32_to_cpu(*p++);
rep->rr_proc = *p++;
/* The credit grant from the wire is not trustworthy;
* sanitize it before any code path consumes it.
*/
if (credits == 0)
credits = 1; /* don't deadlock */
else if (credits > r_xprt->rx_ep->re_max_requests)
credits = r_xprt->rx_ep->re_max_requests;
if (rep->rr_vers != rpcrdma_version)
goto out_badversion;
@ -1418,10 +1499,6 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
xprt_pin_rqst(rqst);
spin_unlock(&xprt->queue_lock);
if (credits == 0)
credits = 1; /* don't deadlock */
else if (credits > r_xprt->rx_ep->re_max_requests)
credits = r_xprt->rx_ep->re_max_requests;
if (buf->rb_credits != credits)
rpcrdma_update_cwnd(r_xprt, credits);
@ -1439,7 +1516,7 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
frwr_unmap_async(r_xprt, req);
/* LocalInv completion will complete the RPC */
else
kref_put(&req->rl_kref, rpcrdma_reply_done);
rpcrdma_complete_rqst(rep);
out_post:
rpcrdma_post_recvs(r_xprt,
@ -1454,11 +1531,13 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
out_badversion:
trace_xprtrdma_reply_vers_err(rep);
goto out;
rpcrdma_rep_put(buf, rep);
credits = buf->rb_credits;
goto out_post;
out_shortreply:
trace_xprtrdma_reply_short_err(rep);
out:
rpcrdma_rep_put(buf, rep);
credits = buf->rb_credits;
goto out_post;
}

View File

@ -279,6 +279,13 @@ xprt_rdma_destroy(struct rpc_xprt *xprt)
cancel_delayed_work_sync(&r_xprt->rx_connect_worker);
rpcrdma_xprt_disconnect(r_xprt);
/* The disconnect's sendctx drain can return bc_prealloc reqs
* to bc_pa_list after xprt_destroy_backchannel() emptied it.
*/
#if defined(CONFIG_SUNRPC_BACKCHANNEL)
xprt_rdma_bc_destroy(xprt, 0);
#endif
rpcrdma_buffer_destroy(&r_xprt->rx_buf);
xprt_rdma_free_addresses(xprt);
@ -484,7 +491,52 @@ xprt_rdma_connect(struct rpc_xprt *xprt, struct rpc_task *task)
xprt_reconnect_backoff(xprt, RPCRDMA_INIT_REEST_TO);
}
trace_xprtrdma_op_connect(r_xprt, delay);
queue_delayed_work(system_long_wq, &r_xprt->rx_connect_worker, delay);
queue_delayed_work(system_dfl_long_wq, &r_xprt->rx_connect_worker,
delay);
}
/* rl_kref has two owners while a Send is outstanding: the rpc_rqst
* owner and the sendctx. Replies complete the RPC but do not drop
* either reference. The req returns to its free pool only after
* xprt_rdma_free_slot() or xprt_rdma_bc_free_rqst() has dropped the
* RPC-layer reference and rpcrdma_sendctx_unmap() has dropped the
* Send-side reference.
*/
static void rpcrdma_req_release(struct kref *kref)
{
struct rpcrdma_req *req =
container_of(kref, struct rpcrdma_req, rl_kref);
struct rpc_rqst *rqst = &req->rl_slot;
struct rpc_xprt *xprt = rqst->rq_xprt;
struct rpcrdma_xprt *r_xprt;
/* I4: both the RPC-layer and Send-side owners have dropped,
* so rpcrdma_sendctx_unmap() has cleared rl_sendctx.
*/
WARN_ON_ONCE(req->rl_sendctx);
kref_init(&req->rl_kref);
#if defined(CONFIG_SUNRPC_BACKCHANNEL)
if (bc_prealloc(rqst)) {
spin_lock(&xprt->bc_pa_lock);
list_add_tail(&rqst->rq_bc_pa_list, &xprt->bc_pa_list);
spin_unlock(&xprt->bc_pa_lock);
return;
}
#endif
if (xprt_wake_up_backlog(xprt, rqst))
return;
r_xprt = rpcx_to_rdmax(xprt);
memset(rqst, 0, sizeof(*rqst));
rpcrdma_buffer_put(&r_xprt->rx_buf, req);
}
void rpcrdma_req_put(struct rpcrdma_req *req)
{
kref_put(&req->rl_kref, rpcrdma_req_release);
}
/**
@ -505,6 +557,7 @@ xprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
req = rpcrdma_buffer_get(&r_xprt->rx_buf);
if (!req)
goto out_sleep;
kref_init(&req->rl_kref);
task->tk_rqstp = &req->rl_slot;
task->tk_status = 0;
return;
@ -520,6 +573,7 @@ xprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
if (req) {
struct rpc_rqst *rqst = &req->rl_slot;
kref_init(&req->rl_kref);
if (!xprt_wake_up_backlog(xprt, rqst)) {
memset(rqst, 0, sizeof(*rqst));
rpcrdma_buffer_put(&r_xprt->rx_buf, req);
@ -540,10 +594,7 @@ xprt_rdma_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *rqst)
container_of(xprt, struct rpcrdma_xprt, rx_xprt);
rpcrdma_reply_put(&r_xprt->rx_buf, rpcr_to_rdmar(rqst));
if (!xprt_wake_up_backlog(xprt, rqst)) {
memset(rqst, 0, sizeof(*rqst));
rpcrdma_buffer_put(&r_xprt->rx_buf, rpcr_to_rdmar(rqst));
}
rpcrdma_req_put(rpcr_to_rdmar(rqst));
}
static bool rpcrdma_check_regbuf(struct rpcrdma_xprt *r_xprt,
@ -607,10 +658,10 @@ xprt_rdma_free(struct rpc_task *task)
frwr_unmap_sync(rpcx_to_rdmax(rqst->rq_xprt), req);
}
/* XXX: If the RPC is completing because of a signal and
* not because a reply was received, we ought to ensure
* that the Send completion has fired, so that memory
* involved with the Send is not still visible to the NIC.
/* The Send-side rl_kref owner keeps req out of its free pool
* until rpcrdma_sendctx_unmap() has fired -- see I4 above
* rpcrdma_reply_handler() -- so signal-driven release here
* does not let the HCA touch a recycled send buffer.
*/
}
@ -716,7 +767,7 @@ void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
r_xprt->rx_stats.mrs_allocated,
r_xprt->rx_stats.local_inv_needed,
r_xprt->rx_stats.empty_sendctx_q,
r_xprt->rx_stats.reply_waits_for_send);
0LU); /* was reply_waits_for_send; column preserved */
}
static int

View File

@ -65,6 +65,8 @@
static int rpcrdma_sendctxs_create(struct rpcrdma_xprt *r_xprt);
static void rpcrdma_sendctxs_destroy(struct rpcrdma_xprt *r_xprt);
static unsigned long rpcrdma_sendctx_next(struct rpcrdma_buffer *buf,
unsigned long item);
static void rpcrdma_sendctx_put_locked(struct rpcrdma_xprt *r_xprt,
struct rpcrdma_sendctx *sc);
static int rpcrdma_reqs_setup(struct rpcrdma_xprt *r_xprt);
@ -79,6 +81,8 @@ rpcrdma_regbuf_alloc_node(size_t size, enum dma_data_direction direction,
int node);
static struct rpcrdma_regbuf *
rpcrdma_regbuf_alloc(size_t size, enum dma_data_direction direction);
static bool rpcrdma_regbuf_realloc_node(struct rpcrdma_regbuf *rb,
size_t size, gfp_t flags, int node);
static void rpcrdma_regbuf_dma_unmap(struct rpcrdma_regbuf *rb);
static void rpcrdma_regbuf_free(struct rpcrdma_regbuf *rb);
@ -243,8 +247,17 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
complete(&ep->re_done);
return 0;
case RDMA_CM_EVENT_ADDR_CHANGE:
ep->re_connect_status = -ENODEV;
goto disconnected;
switch (xchg(&ep->re_connect_status, -ENODEV)) {
case 0:
goto wake_connect_worker;
case 1:
/* The later DISCONNECTED event balances the
* ESTABLISHED get; do not put here.
*/
rpcrdma_force_disconnect(ep);
return 0;
}
return 0;
case RDMA_CM_EVENT_ESTABLISHED:
rpcrdma_ep_get(ep);
ep->re_connect_status = 1;
@ -267,7 +280,6 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
return 0;
case RDMA_CM_EVENT_DISCONNECTED:
ep->re_connect_status = -ECONNABORTED;
disconnected:
rpcrdma_force_disconnect(ep);
return rpcrdma_ep_put(ep);
default:
@ -324,6 +336,7 @@ static struct rdma_cm_id *rpcrdma_create_id(struct rpcrdma_xprt *r_xprt,
if (rc)
goto out;
ep->re_id = id;
rc = rpcrdma_rn_register(id->device, &ep->re_rn, rpcrdma_ep_removal_done);
if (rc)
goto out;
@ -396,7 +409,6 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
}
__module_get(THIS_MODULE);
device = id->device;
ep->re_id = id;
reinit_completion(&ep->re_done);
ep->re_max_requests = r_xprt->rx_xprt.max_reqs;
@ -539,7 +551,17 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt)
goto out;
}
rpcrdma_mrs_create(r_xprt);
frwr_wp_create(r_xprt);
/*
* rpcrdma_encode_write_list() dereferences the write-pad
* MR with no NULL check, so fail the connect rather than
* publish a transport whose write-pad MR is NULL.
*/
rc = frwr_wp_create(r_xprt);
if (rc) {
rc = -ENOTCONN;
goto out;
}
out:
trace_xprtrdma_connect(r_xprt, rc);
@ -571,9 +593,9 @@ void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt)
rpcrdma_xprt_drain(r_xprt);
rpcrdma_reps_unmap(r_xprt);
rpcrdma_sendctxs_destroy(r_xprt);
rpcrdma_reqs_reset(r_xprt);
rpcrdma_mrs_destroy(r_xprt);
rpcrdma_sendctxs_destroy(r_xprt);
if (rpcrdma_ep_put(ep))
rdma_destroy_id(id);
@ -605,6 +627,25 @@ static void rpcrdma_sendctxs_destroy(struct rpcrdma_xprt *r_xprt)
if (!buf->rb_sc_ctxs)
return;
/* The QP is drained, but the final unsignaled Sends might not
* have been walked by a signaled Send completion. Release those
* Send owners before request buffers are reset.
*
* Unlike the completion sweep, this walk can visit slots with
* no Send posted: after a partial rpcrdma_sendctxs_create()
* failure on reconnect, rb_sc_head and rb_sc_tail are stale,
* and slots between them can be NULL or have sc_req clear.
*/
for (i = rpcrdma_sendctx_next(buf, buf->rb_sc_tail);
i != rpcrdma_sendctx_next(buf, buf->rb_sc_head);
i = rpcrdma_sendctx_next(buf, i)) {
struct rpcrdma_sendctx *sc = buf->rb_sc_ctxs[i];
if (sc && sc->sc_req)
rpcrdma_sendctx_unmap(sc);
}
for (i = 0; i <= buf->rb_sc_last; i++)
kfree(buf->rb_sc_ctxs[i]);
kfree(buf->rb_sc_ctxs);
@ -667,6 +708,12 @@ static unsigned long rpcrdma_sendctx_next(struct rpcrdma_buffer *buf,
return likely(item < buf->rb_sc_last) ? item + 1 : 0;
}
static unsigned long rpcrdma_sendctx_prev(struct rpcrdma_buffer *buf,
unsigned long item)
{
return item > 0 ? item - 1 : buf->rb_sc_last;
}
/**
* rpcrdma_sendctx_get_locked - Acquire a send context
* @r_xprt: controlling transport instance
@ -723,6 +770,29 @@ struct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_xprt *r_xprt)
return NULL;
}
/**
* rpcrdma_sendctx_unget_locked - Release an unposted send context
* @r_xprt: controlling transport instance
* @sc: send context to release
*
* Usage: Called when no Send is posted for the sendctx most
* recently returned by rpcrdma_sendctx_get_locked().
*
* The caller serializes calls to this function and to
* rpcrdma_sendctx_get_locked() (per transport).
*/
void rpcrdma_sendctx_unget_locked(struct rpcrdma_xprt *r_xprt,
struct rpcrdma_sendctx *sc)
{
struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
if (WARN_ON_ONCE(buf->rb_sc_ctxs[buf->rb_sc_head] != sc))
return;
buf->rb_sc_head = rpcrdma_sendctx_prev(buf, buf->rb_sc_head);
xprt_write_space(&r_xprt->rx_xprt);
}
/**
* rpcrdma_sendctx_put_locked - Release a send context
* @r_xprt: controlling transport instance
@ -739,15 +809,18 @@ static void rpcrdma_sendctx_put_locked(struct rpcrdma_xprt *r_xprt,
struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
unsigned long next_tail;
/* Unmap SGEs of previously completed but unsignaled
* Sends by walking up the queue until @sc is found.
/* Release previously completed but unsignaled Sends by walking
* up the queue until @sc is found.
*/
next_tail = buf->rb_sc_tail;
do {
struct rpcrdma_sendctx *cur;
next_tail = rpcrdma_sendctx_next(buf, next_tail);
/* ORDER: item must be accessed _before_ tail is updated */
rpcrdma_sendctx_unmap(buf->rb_sc_ctxs[next_tail]);
cur = buf->rb_sc_ctxs[next_tail];
rpcrdma_sendctx_unmap(cur);
} while (buf->rb_sc_ctxs[next_tail] != sc);
@ -1022,9 +1095,15 @@ static struct rpcrdma_rep *rpcrdma_rep_get_locked(struct rpcrdma_buffer *buf)
* @buf: buffer pool
* @rep: rep to release
*
* The rep's transient association with an rpc_rqst, established
* by rpcrdma_reply_handler() and torn down here, must not survive
* onto rb_free_reps: rpcrdma_post_recvs() pulls reps from the free
* list to re-post them, and a non-NULL rr_rqst on a free-listed rep
* would imply the rep is still referenced by a req.
*/
void rpcrdma_rep_put(struct rpcrdma_buffer *buf, struct rpcrdma_rep *rep)
{
rep->rr_rqst = NULL;
llist_add(&rep->rr_node, &buf->rb_free_reps);
}
@ -1059,6 +1138,22 @@ static void rpcrdma_reps_destroy(struct rpcrdma_buffer *buf)
spin_unlock(&buf->rb_lock);
}
static unsigned int rpcrdma_req_pool_slack(unsigned int max_reqs)
{
/* The sendctx ring can hold up to one Send-signaling batch
* (re_send_batch, set by frwr_open() to re_max_requests >> 3)
* of unfinished Sends. Each pins its req until a signaled Send
* completion releases the sendctx. Size the pool above max_reqs
* by that batch so the recycle delay does not stall a slot
* allocation that the RPC/RDMA credit window would admit.
*
* Round up: re_max_requests >> 3 is zero when max_reqs < 8, but
* a single unsignaled Send is still enough to pin one req. One
* slack slot covers that case.
*/
return DIV_ROUND_UP(max_reqs, 8);
}
/**
* rpcrdma_buffer_create - Create initial set of req/rep objects
* @r_xprt: transport instance to (re)initialize
@ -1068,6 +1163,7 @@ static void rpcrdma_reps_destroy(struct rpcrdma_buffer *buf)
int rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
{
struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
unsigned int max_reqs;
int i, rc;
buf->rb_bc_srv_max_requests = 0;
@ -1076,19 +1172,21 @@ int rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
INIT_LIST_HEAD(&buf->rb_all_mrs);
INIT_WORK(&buf->rb_refresh_worker, rpcrdma_mr_refresh_worker);
INIT_LIST_HEAD(&buf->rb_send_bufs);
init_llist_head(&buf->rb_send_bufs);
INIT_LIST_HEAD(&buf->rb_allreqs);
INIT_LIST_HEAD(&buf->rb_all_reps);
rc = -ENOMEM;
for (i = 0; i < r_xprt->rx_xprt.max_reqs; i++) {
max_reqs = r_xprt->rx_xprt.max_reqs;
max_reqs += rpcrdma_req_pool_slack(max_reqs);
for (i = 0; i < max_reqs; i++) {
struct rpcrdma_req *req;
req = rpcrdma_req_create(r_xprt,
RPCRDMA_V1_DEF_INLINE_SIZE * 2);
if (!req)
goto out;
list_add(&req->rl_list, &buf->rb_send_bufs);
llist_add(&req->rl_node, &buf->rb_send_bufs);
}
init_llist_head(&buf->rb_free_reps);
@ -1168,16 +1266,14 @@ static void rpcrdma_mrs_destroy(struct rpcrdma_xprt *r_xprt)
void
rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf)
{
struct rpcrdma_req *req, *next;
struct llist_node *node;
rpcrdma_reps_destroy(buf);
while (!list_empty(&buf->rb_send_bufs)) {
struct rpcrdma_req *req;
req = list_first_entry(&buf->rb_send_bufs,
struct rpcrdma_req, rl_list);
list_del(&req->rl_list);
node = llist_del_all(&buf->rb_send_bufs);
llist_for_each_entry_safe(req, next, node, rl_node)
rpcrdma_req_destroy(req);
}
}
/**
@ -1207,9 +1303,11 @@ rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt)
*/
void rpcrdma_reply_put(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req)
{
if (req->rl_reply) {
rpcrdma_rep_put(buffers, req->rl_reply);
struct rpcrdma_rep *rep = req->rl_reply;
if (rep) {
req->rl_reply = NULL;
rpcrdma_rep_put(buffers, rep);
}
}
@ -1222,15 +1320,15 @@ void rpcrdma_reply_put(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req)
struct rpcrdma_req *
rpcrdma_buffer_get(struct rpcrdma_buffer *buffers)
{
struct rpcrdma_req *req;
struct llist_node *node;
/* Calls to llist_del_first are required to be serialized */
spin_lock(&buffers->rb_lock);
req = list_first_entry_or_null(&buffers->rb_send_bufs,
struct rpcrdma_req, rl_list);
if (req)
list_del_init(&req->rl_list);
node = llist_del_first(&buffers->rb_send_bufs);
spin_unlock(&buffers->rb_lock);
return req;
if (!node)
return NULL;
return llist_entry(node, struct rpcrdma_req, rl_node);
}
/**
@ -1243,9 +1341,7 @@ void rpcrdma_buffer_put(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req)
{
rpcrdma_reply_put(buffers, req);
spin_lock(&buffers->rb_lock);
list_add(&req->rl_list, &buffers->rb_send_bufs);
spin_unlock(&buffers->rb_lock);
llist_add(&req->rl_node, &buffers->rb_send_bufs);
}
/* Returns a pointer to a rpcrdma_regbuf object, or NULL.
@ -1291,10 +1387,16 @@ rpcrdma_regbuf_alloc(size_t size, enum dma_data_direction direction)
* returned, @rb is left untouched.
*/
bool rpcrdma_regbuf_realloc(struct rpcrdma_regbuf *rb, size_t size, gfp_t flags)
{
return rpcrdma_regbuf_realloc_node(rb, size, flags, NUMA_NO_NODE);
}
static bool rpcrdma_regbuf_realloc_node(struct rpcrdma_regbuf *rb,
size_t size, gfp_t flags, int node)
{
void *buf;
buf = kmalloc(size, flags);
buf = kmalloc_node(size, flags, node);
if (!buf)
return false;
@ -1306,6 +1408,23 @@ bool rpcrdma_regbuf_realloc(struct rpcrdma_regbuf *rb, size_t size, gfp_t flags)
return true;
}
static bool rpcrdma_rep_resize(struct rpcrdma_xprt *r_xprt,
struct rpcrdma_rep *rep)
{
struct rpcrdma_regbuf *rb = rep->rr_rdmabuf;
struct rpcrdma_ep *ep = r_xprt->rx_ep;
size_t size = ep->re_inline_recv;
if (likely(rdmab_length(rb) >= size))
return true;
if (!rpcrdma_regbuf_realloc_node(rb, size, XPRTRDMA_GFP_FLAGS,
ibdev_to_node(ep->re_id->device)))
return false;
xdr_buf_init(&rep->rr_hdrbuf, rdmab_data(rb), rdmab_length(rb));
return true;
}
/**
* __rpcrdma_regbuf_dma_map - DMA-map a regbuf
* @r_xprt: controlling transport instance
@ -1387,6 +1506,12 @@ void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed)
rep = rpcrdma_rep_create(r_xprt);
if (!rep)
break;
/* I1: a rep on rb_free_reps must carry no rqst pointer. */
WARN_ON_ONCE(rep->rr_rqst);
if (!rpcrdma_rep_resize(r_xprt, rep)) {
rpcrdma_rep_put(buf, rep);
break;
}
if (!rpcrdma_regbuf_dma_map(r_xprt, rep->rr_rdmabuf)) {
rpcrdma_rep_put(buf, rep);
break;

View File

@ -332,7 +332,7 @@ enum {
struct rpcrdma_buffer;
struct rpcrdma_req {
struct list_head rl_list;
struct llist_node rl_node;
struct rpc_rqst rl_slot;
struct rpcrdma_rep *rl_reply;
struct xdr_stream rl_stream;
@ -374,14 +374,14 @@ rpcrdma_mr_pop(struct list_head *list)
}
/*
* struct rpcrdma_buffer -- holds list/queue of pre-registered memory for
* inline requests/replies, and client/server credits.
* struct rpcrdma_buffer -- holds pre-registered memory for inline
* requests/replies, and client/server credits.
*
* One of these is associated with a transport instance
*/
struct rpcrdma_buffer {
spinlock_t rb_lock;
struct list_head rb_send_bufs;
struct llist_head rb_send_bufs;
struct list_head rb_mrs;
unsigned long rb_sc_head;
@ -427,7 +427,6 @@ struct rpcrdma_stats {
/* accessed when receiving a reply */
unsigned long long total_rdma_reply;
unsigned long long fixup_copy_count;
unsigned long reply_waits_for_send;
unsigned long local_inv_needed;
unsigned long nomsg_call_count;
unsigned long bcall_count;
@ -496,6 +495,8 @@ void rpcrdma_req_destroy(struct rpcrdma_req *req);
int rpcrdma_buffer_create(struct rpcrdma_xprt *);
void rpcrdma_buffer_destroy(struct rpcrdma_buffer *);
struct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_xprt *r_xprt);
void rpcrdma_sendctx_unget_locked(struct rpcrdma_xprt *r_xprt,
struct rpcrdma_sendctx *sc);
struct rpcrdma_mr *rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt);
void rpcrdma_mrs_refresh(struct rpcrdma_xprt *r_xprt);
@ -505,6 +506,7 @@ void rpcrdma_buffer_put(struct rpcrdma_buffer *buffers,
struct rpcrdma_req *req);
void rpcrdma_rep_put(struct rpcrdma_buffer *buf, struct rpcrdma_rep *rep);
void rpcrdma_reply_put(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req);
void rpcrdma_req_put(struct rpcrdma_req *req);
bool rpcrdma_regbuf_realloc(struct rpcrdma_regbuf *rb, size_t size,
gfp_t flags);