Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'nfs-for-6.19-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client updates from Trond Myklebust:
"Bugfixes:
- Fix 'nlink' attribute update races when unlinking a file
- Add missing initialisers for the directory verifier in various
places
- Don't regress the NFSv4 open state due to misordered racing replies
- Ensure the NFSv4.x callback server uses the correct transport
connection
- Fix potential use-after-free races when shutting down the NFSv4.x
callback server
- Fix a pNFS layout commit crash
- Assorted fixes to ensure correct propagation of mount options when
the client crosses a filesystem boundary and triggers the VFS
automount code
- More localio fixes

Features and cleanups:
- Add initial support for basic directory delegations
- SunRPC back channel code cleanups"

* tag 'nfs-for-6.19-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (24 commits)
NFSv4: Handle NFS4ERR_NOTSUPP errors for directory delegations
nfs/localio: remove 61 byte hole from needless ____cacheline_aligned
nfs/localio: remove alignment size checking in nfs_is_local_dio_possible
NFS: Fix up the automount fs_context to use the correct cred
NFS: Fix inheritance of the block sizes when automounting
NFS: Automounted filesystems should inherit ro,noexec,nodev,sync flags
Revert "nfs: ignore SB_RDONLY when mounting nfs"
Revert "nfs: clear SB_RDONLY before getting superblock"
Revert "nfs: ignore SB_RDONLY when remounting nfs"
NFS: Add a module option to disable directory delegations
NFS: Shortcut lookup revalidations if we have a directory delegation
NFS: Request a directory delegation during RENAME
NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK
NFS: Add support for sending GDD_GETATTR
NFSv4/pNFS: Clear NFS_INO_LAYOUTCOMMIT in pnfs_mark_layout_stateid_invalid
NFSv4.1: protect destroying and nullifying bc_serv structure
SUNRPC: new helper function for stopping backchannel server
SUNRPC: cleanup common code in backchannel request
NFSv4.1: pass transport for callback shutdown
NFSv4: ensure the open stateid seqid doesn't go backwards
...

+386 -92
+2 -2
fs/nfs/callback.c
··· 258 258 /* 259 259 * Kill the callback thread if it's no longer being used. 260 260 */ 261 - void nfs_callback_down(int minorversion, struct net *net) 261 + void nfs_callback_down(int minorversion, struct net *net, struct rpc_xprt *xprt) 262 262 { 263 263 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 264 264 struct svc_serv *serv; ··· 270 270 if (cb_info->users == 0) { 271 271 svc_set_num_threads(serv, NULL, 0); 272 272 dprintk("nfs_callback_down: service destroyed\n"); 273 - svc_destroy(&cb_info->serv); 273 + xprt_svc_destroy_nullify_bc(xprt, &cb_info->serv); 274 274 } 275 275 mutex_unlock(&nfs_callback_mutex); 276 276 }
+2 -1
fs/nfs/callback.h
··· 188 188 struct cb_process_state *cps); 189 189 #if IS_ENABLED(CONFIG_NFS_V4) 190 190 extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt); 191 - extern void nfs_callback_down(int minorversion, struct net *net); 191 + extern void nfs_callback_down(int minorversion, struct net *net, 192 + struct rpc_xprt *xprt); 192 193 #endif /* CONFIG_NFS_V4 */ 193 194 /* 194 195 * nfs41: Callbacks are expected to not cause substantial latency,
+17 -4
fs/nfs/client.c
··· 784 784 server->fattr_valid = NFS_ATTR_FATTR_V4; 785 785 } 786 786 787 - if (ctx->rsize) 787 + if (ctx->bsize) { 788 + server->bsize = ctx->bsize; 789 + server->automount_inherit |= NFS_AUTOMOUNT_INHERIT_BSIZE; 790 + } 791 + if (ctx->rsize) { 788 792 server->rsize = nfs_io_size(ctx->rsize, clp->cl_proto); 789 - if (ctx->wsize) 793 + server->automount_inherit |= NFS_AUTOMOUNT_INHERIT_RSIZE; 794 + } 795 + if (ctx->wsize) { 790 796 server->wsize = nfs_io_size(ctx->wsize, clp->cl_proto); 797 + server->automount_inherit |= NFS_AUTOMOUNT_INHERIT_WSIZE; 798 + } 791 799 792 800 server->acregmin = ctx->acregmin * HZ; 793 801 server->acregmax = ctx->acregmax * HZ; ··· 985 977 void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) 986 978 { 987 979 target->flags = source->flags; 988 - target->rsize = source->rsize; 989 - target->wsize = source->wsize; 980 + target->automount_inherit = source->automount_inherit; 981 + if (source->automount_inherit & NFS_AUTOMOUNT_INHERIT_BSIZE) 982 + target->bsize = source->bsize; 983 + if (source->automount_inherit & NFS_AUTOMOUNT_INHERIT_RSIZE) 984 + target->rsize = source->rsize; 985 + if (source->automount_inherit & NFS_AUTOMOUNT_INHERIT_WSIZE) 986 + target->wsize = source->wsize; 990 987 target->acregmin = source->acregmin; 991 988 target->acregmax = source->acregmax; 992 989 target->acdirmin = source->acdirmin;
+8
fs/nfs/delegation.c
··· 30 30 static unsigned nfs_delegation_watermark = NFS_DEFAULT_DELEGATION_WATERMARK; 31 31 module_param_named(delegation_watermark, nfs_delegation_watermark, uint, 0644); 32 32 33 + bool directory_delegations = true; 34 + module_param(directory_delegations, bool, 0644); 35 + MODULE_PARM_DESC(directory_delegations, 36 + "Enable the use of directory delegations, defaults to on."); 37 + 33 38 static struct hlist_head *nfs_delegation_hash(struct nfs_server *server, 34 39 const struct nfs_fh *fhandle) 35 40 { ··· 148 143 */ 149 144 int nfs4_have_delegation(struct inode *inode, fmode_t type, int flags) 150 145 { 146 + if (S_ISDIR(inode->i_mode) && !directory_delegations) 147 + nfs_inode_evict_delegation(inode); 151 148 return nfs4_do_check_delegation(inode, type, flags, true); 152 149 } 153 150 ··· 386 379 delegation->inode = NULL; 387 380 rcu_assign_pointer(nfsi->delegation, NULL); 388 381 spin_unlock(&delegation->lock); 382 + clear_bit(NFS_INO_REQ_DIR_DELEG, &nfsi->flags); 389 383 return delegation; 390 384 } 391 385
+13
fs/nfs/delegation.h
··· 124 124 NFS_DELEGATION_FLAG_TIME); 125 125 } 126 126 127 + extern bool directory_delegations; 128 + 129 + static inline void nfs_request_directory_delegation(struct inode *inode) 130 + { 131 + if (S_ISDIR(inode->i_mode)) 132 + set_bit(NFS_INO_REQ_DIR_DELEG, &NFS_I(inode)->flags); 133 + } 134 + 135 + static inline bool nfs_have_directory_delegation(struct inode *inode) 136 + { 137 + return S_ISDIR(inode->i_mode) && nfs_have_delegated_attributes(inode); 138 + } 139 + 127 140 int nfs4_delegation_hash_alloc(struct nfs_server *server); 128 141 129 142 #endif
+37 -9
fs/nfs/dir.c
··· 789 789 goto out; 790 790 } 791 791 792 + nfs_set_verifier(dentry, dir_verifier); 792 793 inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); 793 794 alias = d_splice_alias(inode, dentry); 794 795 d_lookup_done(dentry); 795 796 if (alias) { 796 797 if (IS_ERR(alias)) 797 798 goto out; 799 + nfs_set_verifier(alias, dir_verifier); 798 800 dput(dentry); 799 801 dentry = alias; 800 802 } 801 - nfs_set_verifier(dentry, dir_verifier); 802 803 trace_nfs_readdir_lookup(d_inode(parent), dentry, 0); 803 804 out: 804 805 dput(dentry); ··· 1515 1514 return 0; 1516 1515 if (!nfs_dentry_verify_change(dir, dentry)) 1517 1516 return 0; 1517 + 1518 + /* 1519 + * If we have a directory delegation then we don't need to revalidate 1520 + * the directory. The delegation will either get recalled or we will 1521 + * receive a notification when it changes. 1522 + */ 1523 + if (nfs_have_directory_delegation(dir)) 1524 + return 0; 1525 + 1518 1526 /* Revalidate nfsi->cache_change_attribute before we declare a match */ 1519 1527 if (nfs_mapping_need_revalidate_inode(dir)) { 1520 1528 if (rcu_walk) ··· 1904 1894 } 1905 1895 1906 1896 /* Ensure that we revalidate inode->i_nlink */ 1907 - static void nfs_drop_nlink(struct inode *inode) 1897 + static void nfs_drop_nlink(struct inode *inode, unsigned long gencount) 1908 1898 { 1899 + struct nfs_inode *nfsi = NFS_I(inode); 1900 + 1909 1901 spin_lock(&inode->i_lock); 1910 1902 /* drop the inode if we're reasonably sure this is the last link */ 1911 - if (inode->i_nlink > 0) 1903 + if (inode->i_nlink > 0 && gencount == nfsi->attr_gencount) 1912 1904 drop_nlink(inode); 1913 - NFS_I(inode)->attr_gencount = nfs_inc_attr_generation_counter(); 1905 + nfsi->attr_gencount = nfs_inc_attr_generation_counter(); 1914 1906 nfs_set_cache_invalid( 1915 1907 inode, NFS_INO_INVALID_CHANGE | NFS_INO_INVALID_CTIME | 1916 1908 NFS_INO_INVALID_NLINK); ··· 1926 1914 static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) 1927 1915 { 1928 1916 if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { 1917 + unsigned long gencount = READ_ONCE(NFS_I(inode)->attr_gencount); 1929 1918 nfs_complete_unlink(dentry, inode); 1930 - nfs_drop_nlink(inode); 1919 + nfs_drop_nlink(inode, gencount); 1931 1920 } 1932 1921 iput(inode); 1933 1922 } ··· 2004 1991 nfs_lookup_advise_force_readdirplus(dir, flags); 2005 1992 2006 1993 no_entry: 1994 + nfs_set_verifier(dentry, dir_verifier); 2007 1995 res = d_splice_alias(inode, dentry); 2008 1996 if (res != NULL) { 2009 1997 if (IS_ERR(res)) 2010 1998 goto out; 1999 + nfs_set_verifier(res, dir_verifier); 2011 2000 dentry = res; 2012 2001 } 2013 - nfs_set_verifier(dentry, dir_verifier); 2014 2002 out: 2015 2003 trace_nfs_lookup_exit(dir, dentry, flags, PTR_ERR_OR_ZERO(res)); 2016 2004 nfs_free_fattr(fattr); ··· 2153 2139 d_drop(dentry); 2154 2140 switch (err) { 2155 2141 case -ENOENT: 2156 - d_splice_alias(NULL, dentry); 2157 2142 if (nfs_server_capable(dir, NFS_CAP_CASE_INSENSITIVE)) 2158 2143 dir_verifier = inode_peek_iversion_raw(dir); 2159 2144 else 2160 2145 dir_verifier = nfs_save_change_attribute(dir); 2161 2146 nfs_set_verifier(dentry, dir_verifier); 2147 + d_splice_alias(NULL, dentry); 2162 2148 break; 2163 2149 case -EISDIR: 2164 2150 case -ENOTDIR: ··· 2217 2203 EXPORT_SYMBOL_GPL(nfs_atomic_open); 2218 2204 2219 2205 static int 2206 + nfs_lookup_revalidate_delegated_parent(struct inode *dir, struct dentry *dentry, 2207 + struct inode *inode) 2208 + { 2209 + return nfs_lookup_revalidate_done(dir, dentry, inode, 1); 2210 + } 2211 + 2212 + static int 2220 2213 nfs4_lookup_revalidate(struct inode *dir, const struct qstr *name, 2221 2214 struct dentry *dentry, unsigned int flags) 2222 2215 { ··· 2249 2228 2250 2229 if (nfs_verifier_is_delegated(dentry)) 2251 2230 return nfs_lookup_revalidate_delegated(dir, dentry, inode); 2231 + 2232 + if (nfs_have_directory_delegation(dir)) 2233 + return nfs_lookup_revalidate_delegated_parent(dir, dentry, inode); 2252 2234 2253 2235 /* NFS only supports OPEN on regular files */ 2254 2236 if (!S_ISREG(inode->i_mode)) ··· 2531 2507 2532 2508 trace_nfs_remove_enter(dir, dentry); 2533 2509 if (inode != NULL) { 2510 + unsigned long gencount = READ_ONCE(NFS_I(inode)->attr_gencount); 2511 + 2534 2512 error = NFS_PROTO(dir)->remove(dir, dentry); 2535 2513 if (error == 0) 2536 - nfs_drop_nlink(inode); 2514 + nfs_drop_nlink(inode, gencount); 2537 2515 } else 2538 2516 error = NFS_PROTO(dir)->remove(dir, dentry); 2539 2517 if (error == -ENOENT) ··· 2735 2709 { 2736 2710 struct inode *old_inode = d_inode(old_dentry); 2737 2711 struct inode *new_inode = d_inode(new_dentry); 2712 + unsigned long new_gencount = 0; 2738 2713 struct dentry *dentry = NULL; 2739 2714 struct rpc_task *task; 2740 2715 bool must_unblock = false; ··· 2788 2761 } else { 2789 2762 block_revalidate(new_dentry); 2790 2763 must_unblock = true; 2764 + new_gencount = NFS_I(new_inode)->attr_gencount; 2791 2765 spin_unlock(&new_dentry->d_lock); 2792 2766 } 2793 2767 ··· 2828 2800 new_dir, new_dentry, error); 2829 2801 if (!error) { 2830 2802 if (new_inode != NULL) 2831 - nfs_drop_nlink(new_inode); 2803 + nfs_drop_nlink(new_inode, new_gencount); 2832 2804 /* 2833 2805 * The d_move() should be here instead of in an async RPC completion 2834 2806 * handler because we need the proper locks to move the dentry. If
+3
fs/nfs/inode.c
··· 1389 1389 status = pnfs_sync_inode(inode, false); 1390 1390 if (status) 1391 1391 goto out; 1392 + } else if (nfs_have_directory_delegation(inode)) { 1393 + status = 0; 1394 + goto out; 1392 1395 } 1393 1396 1394 1397 status = -ENOMEM;
+1 -2
fs/nfs/internal.h
··· 13 13 #include <linux/nfslocalio.h> 14 14 #include <linux/wait_bit.h> 15 15 16 - #define NFS_SB_MASK (SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS) 16 + #define NFS_SB_MASK (SB_RDONLY|SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS) 17 17 18 18 extern const struct export_operations nfs_export_ops; 19 19 ··· 152 152 struct super_block *sb; 153 153 struct dentry *dentry; 154 154 struct nfs_fattr *fattr; 155 - unsigned int inherited_bsize; 156 155 } clone_data; 157 156 }; 158 157
+1 -3
fs/nfs/localio.c
··· 43 43 size_t end_len; 44 44 short int end_iter_index; 45 45 atomic_t n_iters; 46 + struct iov_iter iters[NFSLOCAL_MAX_IOS]; 46 47 bool iter_is_dio_aligned[NFSLOCAL_MAX_IOS]; 47 - struct iov_iter iters[NFSLOCAL_MAX_IOS] ____cacheline_aligned; 48 48 /* End mostly DIO-specific members */ 49 49 }; 50 50 ··· 338 338 nf_dio_offset_align = nf_dio_read_offset_align; 339 339 340 340 if (unlikely(!nf_dio_mem_align || !nf_dio_offset_align)) 341 - return false; 342 - if (unlikely(nf_dio_offset_align > PAGE_SIZE)) 343 341 return false; 344 342 if (unlikely(len < nf_dio_offset_align)) 345 343 return false;
+15 -1
fs/nfs/namespace.c
··· 149 149 struct vfsmount *mnt = ERR_PTR(-ENOMEM); 150 150 struct nfs_server *server = NFS_SB(path->dentry->d_sb); 151 151 struct nfs_client *client = server->nfs_client; 152 + unsigned long s_flags = path->dentry->d_sb->s_flags; 152 153 int timeout = READ_ONCE(nfs_mountpoint_expiry_timeout); 153 154 int ret; 154 155 ··· 170 169 if (!ctx->clone_data.fattr) 171 170 goto out_fc; 172 171 172 + if (fc->cred != server->cred) { 173 + put_cred(fc->cred); 174 + fc->cred = get_cred(server->cred); 175 + } 176 + 173 177 if (fc->net_ns != client->cl_net) { 174 178 put_net(fc->net_ns); 175 179 fc->net_ns = get_net(client->cl_net); 176 180 } 181 + 182 + /* Inherit the flags covered by NFS_SB_MASK */ 183 + fc->sb_flags_mask |= NFS_SB_MASK; 184 + fc->sb_flags &= ~NFS_SB_MASK; 185 + fc->sb_flags |= s_flags & NFS_SB_MASK; 177 186 178 187 /* for submounts we want the same server; referrals will reassign */ 179 188 memcpy(&ctx->nfs_server._address, &client->cl_addr, client->cl_addrlen); ··· 194 183 ctx->minorversion = client->cl_minorversion; 195 184 ctx->nfs_mod = client->cl_nfs_mod; 196 185 get_nfs_version(ctx->nfs_mod); 186 + 187 + /* Inherit block sizes if they were specified as mount parameters */ 188 + if (server->automount_inherit & NFS_AUTOMOUNT_INHERIT_BSIZE) 189 + ctx->bsize = server->bsize; 197 190 198 191 ret = client->rpc_ops->submount(fc, server); 199 192 if (ret < 0) { ··· 298 283 return -ENOMEM; 299 284 300 285 ctx->internal = true; 301 - ctx->clone_data.inherited_bsize = ctx->clone_data.sb->s_blocksize_bits; 302 286 303 287 p = nfs_devname(dentry, buffer, 4096); 304 288 if (IS_ERR(p)) {
+2 -1
fs/nfs/nfs3proc.c
··· 483 483 static void 484 484 nfs3_proc_rename_setup(struct rpc_message *msg, 485 485 struct dentry *old_dentry, 486 - struct dentry *new_dentry) 486 + struct dentry *new_dentry, 487 + struct inode *same_parent) 487 488 { 488 489 msg->rpc_proc = &nfs3_procedures[NFS3PROC_RENAME]; 489 490 }
+21 -6
fs/nfs/nfs4client.c
··· 281 281 */ 282 282 static void nfs4_destroy_callback(struct nfs_client *clp) 283 283 { 284 - if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) 285 - nfs_callback_down(clp->cl_mvops->minor_version, clp->cl_net); 284 + if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) { 285 + struct rpc_xprt *xprt; 286 + 287 + xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt); 288 + nfs_callback_down(clp->cl_mvops->minor_version, clp->cl_net, 289 + xprt); 290 + } 286 291 } 287 292 288 293 static void nfs4_shutdown_client(struct nfs_client *clp) ··· 1179 1174 if (error < 0) 1180 1175 return error; 1181 1176 1182 - if (ctx->rsize) 1183 - server->rsize = nfs_io_size(ctx->rsize, server->nfs_client->cl_proto); 1184 - if (ctx->wsize) 1185 - server->wsize = nfs_io_size(ctx->wsize, server->nfs_client->cl_proto); 1177 + if (ctx->bsize) { 1178 + server->bsize = ctx->bsize; 1179 + server->automount_inherit |= NFS_AUTOMOUNT_INHERIT_BSIZE; 1180 + } 1181 + if (ctx->rsize) { 1182 + server->rsize = 1183 + nfs_io_size(ctx->rsize, server->nfs_client->cl_proto); 1184 + server->automount_inherit |= NFS_AUTOMOUNT_INHERIT_RSIZE; 1185 + } 1186 + if (ctx->wsize) { 1187 + server->wsize = 1188 + nfs_io_size(ctx->wsize, server->nfs_client->cl_proto); 1189 + server->automount_inherit |= NFS_AUTOMOUNT_INHERIT_WSIZE; 1190 + } 1186 1191 1187 1192 server->acregmin = ctx->acregmin * HZ; 1188 1193 server->acregmax = ctx->acregmax * HZ;
+91 -20
fs/nfs/nfs4proc.c
··· 1780 1780 if (nfs_stateid_is_sequential(state, stateid)) 1781 1781 break; 1782 1782 1783 - if (status) 1784 - break; 1783 + if (status) { 1784 + if (nfs4_stateid_match_other(stateid, &state->open_stateid) && 1785 + !nfs4_stateid_is_newer(stateid, &state->open_stateid)) { 1786 + trace_nfs4_open_stateid_update_skip(state->inode, 1787 + stateid, status); 1788 + return; 1789 + } else { 1790 + break; 1791 + } 1792 + } 1793 + 1785 1794 /* Rely on seqids for serialisation with NFSv4.0 */ 1786 1795 if (!nfs4_has_session(NFS_SERVER(state->inode)->nfs_client)) 1787 1796 break; ··· 3183 3174 if (opendata->o_res.rflags & NFS4_OPEN_RESULT_PRESERVE_UNLINKED) 3184 3175 set_bit(NFS_INO_PRESERVE_UNLINKED, &NFS_I(state->inode)->flags); 3185 3176 3186 - dentry = opendata->dentry; 3187 - if (d_really_is_negative(dentry)) { 3188 - struct dentry *alias; 3189 - d_drop(dentry); 3190 - alias = d_splice_alias(igrab(state->inode), dentry); 3191 - /* d_splice_alias() can't fail here - it's a non-directory */ 3192 - if (alias) { 3193 - dput(ctx->dentry); 3194 - ctx->dentry = dentry = alias; 3195 - } 3196 - } 3197 - 3198 3177 switch(opendata->o_arg.claim) { 3199 3178 default: 3200 3179 break; ··· 3193 3196 break; 3194 3197 if (opendata->o_res.delegation.type != 0) 3195 3198 dir_verifier = nfs_save_change_attribute(dir); 3196 - nfs_set_verifier(dentry, dir_verifier); 3199 + } 3200 + 3201 + dentry = opendata->dentry; 3202 + nfs_set_verifier(dentry, dir_verifier); 3203 + if (d_really_is_negative(dentry)) { 3204 + struct dentry *alias; 3205 + d_drop(dentry); 3206 + alias = d_splice_alias(igrab(state->inode), dentry); 3207 + /* d_splice_alias() can't fail here - it's a non-directory */ 3208 + if (alias) { 3209 + dput(ctx->dentry); 3210 + nfs_set_verifier(alias, dir_verifier); 3211 + ctx->dentry = dentry = alias; 3212 + } 3197 3213 } 3198 3214 3199 3215 /* Parse layoutget results before we check for access */ ··· 4470 4460 return status; 4471 4461 } 4472 4462 4463 + #if IS_ENABLED(CONFIG_NFS_V4_1) 4464 + static bool should_request_dir_deleg(struct inode *inode) 4465 + { 4466 + if (!directory_delegations) 4467 + return false; 4468 + if (!inode) 4469 + return false; 4470 + if (!S_ISDIR(inode->i_mode)) 4471 + return false; 4472 + if (!nfs_server_capable(inode, NFS_CAP_DIR_DELEG)) 4473 + return false; 4474 + if (!test_and_clear_bit(NFS_INO_REQ_DIR_DELEG, &(NFS_I(inode)->flags))) 4475 + return false; 4476 + if (nfs4_have_delegation(inode, FMODE_READ, 0)) 4477 + return false; 4478 + return true; 4479 + } 4480 + #else 4481 + static bool should_request_dir_deleg(struct inode *inode) 4482 + { 4483 + return false; 4484 + } 4485 + #endif /* CONFIG_NFS_V4_1 */ 4486 + 4473 4487 static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, 4474 4488 struct nfs_fattr *fattr, struct inode *inode) 4475 4489 { ··· 4511 4477 .rpc_argp = &args, 4512 4478 .rpc_resp = &res, 4513 4479 }; 4480 + struct nfs4_gdd_res gdd_res; 4514 4481 unsigned short task_flags = 0; 4482 + int status; 4515 4483 4516 4484 if (nfs4_has_session(server->nfs_client)) 4517 4485 task_flags = RPC_TASK_MOVEABLE; ··· 4522 4486 if (inode && (server->flags & NFS_MOUNT_SOFTREVAL)) 4523 4487 task_flags |= RPC_TASK_TIMEOUT; 4524 4488 4489 + args.get_dir_deleg = should_request_dir_deleg(inode); 4490 + if (args.get_dir_deleg) 4491 + res.gdd_res = &gdd_res; 4492 + 4525 4493 nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, fattr->label), inode, 0); 4526 4494 nfs_fattr_init(fattr); 4527 4495 nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 0); 4528 - return nfs4_do_call_sync(server->client, server, &msg, 4529 - &args.seq_args, &res.seq_res, task_flags); 4496 + 4497 + status = nfs4_do_call_sync(server->client, server, &msg, 4498 + &args.seq_args, &res.seq_res, task_flags); 4499 + if (args.get_dir_deleg) { 4500 + switch (status) { 4501 + case 0: 4502 + if (gdd_res.status != GDD4_OK) 4503 + break; 4504 + status = nfs_inode_set_delegation( 4505 + inode, current_cred(), FMODE_READ, 4506 + &gdd_res.deleg, 0, NFS4_OPEN_DELEGATE_READ); 4507 + break; 4508 + case -ENOTSUPP: 4509 + case -EOPNOTSUPP: 4510 + server->caps &= ~NFS_CAP_DIR_DELEG; 4511 + } 4512 + } 4513 + return status; 4530 4514 } 4531 4515 4532 4516 int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, ··· 4559 4503 do { 4560 4504 err = _nfs4_proc_getattr(server, fhandle, fattr, inode); 4561 4505 trace_nfs4_getattr(server, fhandle, fattr, err); 4562 - err = nfs4_handle_exception(server, err, 4563 - &exception); 4506 + switch (err) { 4507 + default: 4508 + err = nfs4_handle_exception(server, err, &exception); 4509 + break; 4510 + case -ENOTSUPP: 4511 + case -EOPNOTSUPP: 4512 + exception.retry = true; 4513 + } 4564 4514 } while (exception.retry); 4565 4515 return err; 4566 4516 } ··· 4830 4768 int status = 0; 4831 4769 4832 4770 if (!nfs4_have_delegation(inode, FMODE_READ, 0)) { 4771 + nfs_request_directory_delegation(inode); 4833 4772 res.fattr = nfs_alloc_fattr(); 4834 4773 if (res.fattr == NULL) 4835 4774 return -ENOMEM; ··· 4938 4875 4939 4876 ilabel = nfs4_label_init_security(dir, dentry, sattr, &l); 4940 4877 4878 + nfs_request_directory_delegation(dir); 4879 + 4941 4880 if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK)) 4942 4881 sattr->ia_mode &= ~current_umask(); 4943 4882 state = nfs4_do_open(dir, ctx, flags, sattr, ilabel, NULL); ··· 5036 4971 nfs4_init_sequence(&args->seq_args, &res->seq_res, 1, 0); 5037 4972 5038 4973 nfs_fattr_init(res->dir_attr); 4974 + nfs_request_directory_delegation(d_inode(dentry->d_parent)); 5039 4975 5040 4976 if (inode) { 5041 4977 nfs4_inode_return_delegation(inode); ··· 5071 5005 5072 5006 static void nfs4_proc_rename_setup(struct rpc_message *msg, 5073 5007 struct dentry *old_dentry, 5074 - struct dentry *new_dentry) 5008 + struct dentry *new_dentry, 5009 + struct inode *same_parent) 5075 5010 { 5076 5011 struct nfs_renameargs *arg = msg->rpc_argp; 5077 5012 struct nfs_renameres *res = msg->rpc_resp; ··· 5083 5016 nfs4_inode_make_writeable(old_inode); 5084 5017 if (new_inode) 5085 5018 nfs4_inode_return_delegation(new_inode); 5019 + if (same_parent) 5020 + nfs_request_directory_delegation(same_parent); 5086 5021 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; 5087 5022 res->server = NFS_SB(old_dentry->d_sb); 5088 5023 nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1, 0); ··· 10891 10822 .minor_version = 1, 10892 10823 .init_caps = NFS_CAP_READDIRPLUS 10893 10824 | NFS_CAP_ATOMIC_OPEN 10825 + | NFS_CAP_DIR_DELEG 10894 10826 | NFS_CAP_POSIX_LOCK 10895 10827 | NFS_CAP_STATEID_NFSV41 10896 10828 | NFS_CAP_ATOMIC_OPEN_V1 ··· 10918 10848 .minor_version = 2, 10919 10849 .init_caps = NFS_CAP_READDIRPLUS 10920 10850 | NFS_CAP_ATOMIC_OPEN 10851 + | NFS_CAP_DIR_DELEG 10921 10852 | NFS_CAP_POSIX_LOCK 10922 10853 | NFS_CAP_STATEID_NFSV41 10923 10854 | NFS_CAP_ATOMIC_OPEN_V1
+1
fs/nfs/nfs4trace.h
··· 1353 1353 DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_delegreturn); 1354 1354 DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update); 1355 1355 DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update_wait); 1356 + DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update_skip); 1356 1357 DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_close_stateid_update_wait); 1357 1358 1358 1359 DECLARE_EVENT_CLASS(nfs4_getattr_event,
+106
fs/nfs/nfs4xdr.c
··· 393 393 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) 394 394 #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) 395 395 #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) 396 + #define encode_get_dir_deleg_maxsz (op_encode_hdr_maxsz + \ 397 + 4 /* gdda_signal_deleg_avail */ + \ 398 + 8 /* gdda_notification_types */ + \ 399 + nfstime4_maxsz /* gdda_child_attr_delay */ + \ 400 + nfstime4_maxsz /* gdda_dir_attr_delay */ + \ 401 + nfs4_fattr_bitmap_maxsz /* gdda_child_attributes */ + \ 402 + nfs4_fattr_bitmap_maxsz /* gdda_dir_attributes */) 403 + #define decode_get_dir_deleg_maxsz (op_decode_hdr_maxsz + \ 404 + 4 /* gddrnf_status */ + \ 405 + encode_verifier_maxsz /* gddr_cookieverf */ + \ 406 + encode_stateid_maxsz /* gddr_stateid */ + \ 407 + 8 /* gddr_notification */ + \ 408 + nfs4_fattr_maxsz /* gddr_child_attributes */ + \ 409 + nfs4_fattr_maxsz /* gddr_dir_attributes */) 396 410 #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + \ 397 411 XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \ 398 412 1 /* layout type */ + \ ··· 458 444 #else /* CONFIG_NFS_V4_1 */ 459 445 #define encode_sequence_maxsz 0 460 446 #define decode_sequence_maxsz 0 447 + #define encode_get_dir_deleg_maxsz 0 448 + #define decode_get_dir_deleg_maxsz 0 461 449 #define encode_layoutreturn_maxsz 0 462 450 #define decode_layoutreturn_maxsz 0 463 451 #define encode_layoutget_maxsz 0 ··· 647 631 #define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ 648 632 encode_sequence_maxsz + \ 649 633 encode_putfh_maxsz + \ 634 + encode_get_dir_deleg_maxsz + \ 650 635 encode_getattr_maxsz + \ 651 636 encode_renew_maxsz) 652 637 #define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ 653 638 decode_sequence_maxsz + \ 654 639 decode_putfh_maxsz + \ 640 + decode_get_dir_deleg_maxsz + \ 655 641 decode_getattr_maxsz + \ 656 642 decode_renew_maxsz) 657 643 #define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ ··· 2026 2008 2027 2009 #ifdef CONFIG_NFS_V4_1 2028 2010 static void 2011 + encode_get_dir_delegation(struct xdr_stream *xdr, struct compound_hdr *hdr) 2012 + { 2013 + struct timespec64 ts = { 0, 0 }; 2014 + u32 notifications[1] = { 0 }; 2015 + u32 attributes[1] = { 0 }; 2016 + __be32 *p; 2017 + 2018 + encode_op_hdr(xdr, OP_GET_DIR_DELEGATION, decode_get_dir_deleg_maxsz, hdr); 2019 + 2020 + /* We don't handle CB_RECALLABLE_OBJ_AVAIL yet. */ 2021 + xdr_stream_encode_bool(xdr, false); 2022 + 2023 + xdr_encode_bitmap4(xdr, notifications, ARRAY_SIZE(notifications)); 2024 + 2025 + /* Request no delay on attribute updates */ 2026 + p = reserve_space(xdr, 12 + 12); 2027 + p = xdr_encode_nfstime4(p, &ts); 2028 + xdr_encode_nfstime4(p, &ts); 2029 + 2030 + /* Requested child attributes */ 2031 + xdr_encode_bitmap4(xdr, attributes, ARRAY_SIZE(attributes)); 2032 + 2033 + /* Requested dir attributes */ 2034 + xdr_encode_bitmap4(xdr, attributes, ARRAY_SIZE(attributes)); 2035 + } 2036 + 2037 + static void 2029 2038 encode_getdeviceinfo(struct xdr_stream *xdr, 2030 2039 const struct nfs4_getdeviceinfo_args *args, 2031 2040 struct compound_hdr *hdr) ··· 2187 2142 encode_nfs4_stateid(xdr, &args->stateid); 2188 2143 } 2189 2144 #else 2145 + static inline void 2146 + encode_get_dir_delegation(struct xdr_stream *xdr, struct compound_hdr *hdr) 2147 + { 2148 + } 2149 + 2190 2150 static inline void 2191 2151 encode_layoutreturn(struct xdr_stream *xdr, 2192 2152 const struct nfs4_layoutreturn_args *args, ··· 2406 2356 encode_compound_hdr(xdr, req, &hdr); 2407 2357 encode_sequence(xdr, &args->seq_args, &hdr); 2408 2358 encode_putfh(xdr, args->fh, &hdr); 2359 + if (args->get_dir_deleg) 2360 + encode_get_dir_delegation(xdr, &hdr); 2409 2361 encode_getfattr(xdr, args->bitmask, &hdr); 2410 2362 encode_nops(&hdr); 2411 2363 } ··· 6046 5994 return decode_stateid(xdr, stateid); 6047 5995 } 6048 5996 5997 + static int decode_get_dir_delegation(struct xdr_stream *xdr, 5998 + struct nfs4_getattr_res *res) 5999 + { 6000 + struct nfs4_gdd_res *gdd_res = res->gdd_res; 6001 + nfs4_verifier cookieverf; 6002 + u32 bitmap[1]; 6003 + int status; 6004 + 6005 + status = decode_op_hdr(xdr, OP_GET_DIR_DELEGATION); 6006 + if (status) 6007 + return status; 6008 + 6009 + if (xdr_stream_decode_u32(xdr, &gdd_res->status)) 6010 + return -EIO; 6011 + 6012 + if (gdd_res->status == GDD4_UNAVAIL) 6013 + return xdr_inline_decode(xdr, 4) ? 0 : -EIO; 6014 + 6015 + status = decode_verifier(xdr, &cookieverf); 6016 + if (status) 6017 + return status; 6018 + 6019 + status = decode_delegation_stateid(xdr, &gdd_res->deleg); 6020 + if (status) 6021 + return status; 6022 + 6023 + /* Decode supported notification types. */ 6024 + status = decode_bitmap4(xdr, bitmap, ARRAY_SIZE(bitmap)); 6025 + if (status < 0) 6026 + return status; 6027 + 6028 + /* Decode supported child attributes. */ 6029 + status = decode_bitmap4(xdr, bitmap, ARRAY_SIZE(bitmap)); 6030 + if (status < 0) 6031 + return status; 6032 + 6033 + /* Decode supported attributes. */ 6034 + status = decode_bitmap4(xdr, bitmap, ARRAY_SIZE(bitmap)); 6035 + if (status < 0) 6036 + return status; 6037 + return 0; 6038 + } 6039 + 6049 6040 static int decode_getdeviceinfo(struct xdr_stream *xdr, 6050 6041 struct nfs4_getdeviceinfo_res *res) 6051 6042 { ··· 6303 6208 return res->status; 6304 6209 } 6305 6210 #else 6211 + static int decode_get_dir_delegation(struct xdr_stream *xdr, 6212 + struct nfs4_getattr_res *res) 6213 + { 6214 + return 0; 6215 + } 6216 + 6306 6217 static inline 6307 6218 int decode_layoutreturn(struct xdr_stream *xdr, 6308 6219 struct nfs4_layoutreturn_res *res) ··· 6626 6525 status = decode_putfh(xdr); 6627 6526 if (status) 6628 6527 goto out; 6528 + if (res->gdd_res) { 6529 + status = decode_get_dir_delegation(xdr, res); 6530 + if (status) 6531 + goto out; 6532 + } 6629 6533 status = decode_getfattr(xdr, res->fattr, res->server); 6630 6534 out: 6631 6535 return status;
+1
fs/nfs/pnfs.c
··· 464 464 struct pnfs_layout_segment *lseg, *next; 465 465 466 466 set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); 467 + clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(lo->plh_inode)->flags); 467 468 list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) 468 469 pnfs_clear_lseg_state(lseg, lseg_list); 469 470 pnfs_clear_layoutreturn_info(lo);
+2 -1
fs/nfs/proc.c
··· 353 353 static void 354 354 nfs_proc_rename_setup(struct rpc_message *msg, 355 355 struct dentry *old_dentry, 356 - struct dentry *new_dentry) 356 + struct dentry *new_dentry, 357 + struct inode *same_parent) 357 358 { 358 359 msg->rpc_proc = &nfs_procedures[NFSPROC_RENAME]; 359 360 }
+3 -30
fs/nfs/super.c
··· 1052 1052 sync_filesystem(sb); 1053 1053 1054 1054 /* 1055 - * The SB_RDONLY flag has been removed from the superblock during 1056 - * mounts to prevent interference between different filesystems. 1057 - * Similarly, it is also necessary to ignore the SB_RDONLY flag 1058 - * during reconfiguration; otherwise, it may also result in the 1059 - * creation of redundant superblocks when mounting a directory with 1060 - * different rw and ro flags multiple times. 1061 - */ 1062 - fc->sb_flags_mask &= ~SB_RDONLY; 1063 - 1064 - /* 1065 1055 * Userspace mount programs that send binary options generally send 1066 1056 * them populated with default values. We have no way to know which 1067 1057 * ones were explicitly specified. Fall back to legacy behavior and ··· 1091 1101 sb->s_blocksize = 0; 1092 1102 sb->s_xattr = server->nfs_client->cl_nfs_mod->xattr; 1093 1103 sb->s_op = server->nfs_client->cl_nfs_mod->sops; 1094 - if (ctx->bsize) 1095 - sb->s_blocksize = nfs_block_size(ctx->bsize, &sb->s_blocksize_bits); 1104 + if (server->bsize) 1105 + sb->s_blocksize = 1106 + nfs_block_size(server->bsize, &sb->s_blocksize_bits); 1096 1107 1097 1108 switch (server->nfs_client->rpc_ops->version) { 1098 1109 case 2: ··· 1309 1318 if (IS_ERR(server)) 1310 1319 return PTR_ERR(server); 1311 1320 1312 - /* 1313 - * When NFS_MOUNT_UNSHARED is not set, NFS forces the sharing of a 1314 - * superblock among each filesystem that mounts sub-directories 1315 - * belonging to a single exported root path. 1316 - * To prevent interference between different filesystems, the 1317 - * SB_RDONLY flag should be removed from the superblock. 1318 - */ 1319 1321 if (server->flags & NFS_MOUNT_UNSHARED) 1320 1322 compare_super = NULL; 1321 - else 1322 - fc->sb_flags &= ~SB_RDONLY; 1323 1323 1324 1324 /* -o noac implies -o sync */ 1325 1325 if (server->flags & NFS_MOUNT_NOAC) 1326 1326 fc->sb_flags |= SB_SYNCHRONOUS; 1327 - 1328 - if (ctx->clone_data.sb) 1329 - if (ctx->clone_data.sb->s_flags & SB_SYNCHRONOUS) 1330 - fc->sb_flags |= SB_SYNCHRONOUS; 1331 1327 1332 1328 /* Get a superblock - note that we may end up sharing one that already exists */ 1333 1329 fc->s_fs_info = server; ··· 1339 1361 } 1340 1362 1341 1363 if (!s->s_root) { 1342 - unsigned bsize = ctx->clone_data.inherited_bsize; 1343 1364 /* initial superblock/root creation */ 1344 1365 nfs_fill_super(s, ctx); 1345 - if (bsize) { 1346 - s->s_blocksize_bits = bsize; 1347 - s->s_blocksize = 1U << bsize; 1348 - } 1349 1366 error = nfs_get_cache_cookie(s, ctx); 1350 1367 if (error < 0) 1351 1368 goto error_splat_super;
+2 -1
fs/nfs/unlink.c
··· 390 390 391 391 nfs_sb_active(old_dir->i_sb); 392 392 393 - NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dentry, new_dentry); 393 + NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dentry, new_dentry, 394 + old_dir == new_dir ? old_dir : NULL); 394 395 395 396 return rpc_run_task(&task_setup_data); 396 397 }
+1
include/linux/nfs_fs.h
··· 344 344 #define NFS_INO_LAYOUTCOMMITTING (10) /* layoutcommit inflight */ 345 345 #define NFS_INO_LAYOUTSTATS (11) /* layoutstats inflight */ 346 346 #define NFS_INO_ODIRECT (12) /* I/O setting is O_DIRECT */ 347 + #define NFS_INO_REQ_DIR_DELEG (13) /* Request a directory delegation */ 347 348 348 349 static inline struct nfs_inode *NFS_I(const struct inode *inode) 349 350 {
+6
include/linux/nfs_fs_sb.h
··· 172 172 #define NFS_MOUNT_FORCE_RDIRPLUS 0x20000000 173 173 #define NFS_MOUNT_NETUNREACH_FATAL 0x40000000 174 174 175 + unsigned int automount_inherit; /* Properties inherited by automount */ 176 + #define NFS_AUTOMOUNT_INHERIT_BSIZE 0x0001 177 + #define NFS_AUTOMOUNT_INHERIT_RSIZE 0x0002 178 + #define NFS_AUTOMOUNT_INHERIT_WSIZE 0x0004 179 + 175 180 unsigned int caps; /* server capabilities */ 176 181 __u64 fattr_valid; /* Valid attributes */ 177 182 unsigned int rsize; /* read size */ ··· 310 305 #define NFS_CAP_REBOOT_LAYOUTRETURN (1U << 8) 311 306 #define NFS_CAP_OFFLOAD_STATUS (1U << 9) 312 307 #define NFS_CAP_ZERO_RANGE (1U << 10) 308 + #define NFS_CAP_DIR_DELEG (1U << 11) 313 309 #define NFS_CAP_OPEN_XOR (1U << 12) 314 310 #define NFS_CAP_DELEGTIME (1U << 13) 315 311 #define NFS_CAP_POSIX_LOCK (1U << 14)
+9 -1
include/linux/nfs_xdr.h
··· 1092 1092 struct nfs4_sequence_args seq_args; 1093 1093 const struct nfs_fh * fh; 1094 1094 const u32 * bitmask; 1095 + bool get_dir_deleg; 1096 + }; 1097 + 1098 + struct nfs4_gdd_res { 1099 + u32 status; 1100 + nfs4_stateid deleg; 1095 1101 }; 1096 1102 1097 1103 struct nfs4_getattr_res { 1098 1104 struct nfs4_sequence_res seq_res; 1099 1105 const struct nfs_server * server; 1100 1106 struct nfs_fattr * fattr; 1107 + struct nfs4_gdd_res * gdd_res; 1101 1108 }; 1102 1109 1103 1110 struct nfs4_link_arg { ··· 1808 1801 int (*unlink_done) (struct rpc_task *, struct inode *); 1809 1802 void (*rename_setup) (struct rpc_message *msg, 1810 1803 struct dentry *old_dentry, 1811 - struct dentry *new_dentry); 1804 + struct dentry *new_dentry, 1805 + struct inode *same_parent); 1812 1806 void (*rename_rpc_prepare)(struct rpc_task *task, struct nfs_renamedata *); 1813 1807 int (*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir); 1814 1808 int (*link) (struct inode *, struct inode *, const struct qstr *);
+7
include/linux/sunrpc/bc_xprt.h
··· 25 25 void xprt_free_bc_request(struct rpc_rqst *req); 26 26 int xprt_setup_backchannel(struct rpc_xprt *, unsigned int min_reqs); 27 27 void xprt_destroy_backchannel(struct rpc_xprt *, unsigned int max_reqs); 28 + void xprt_enqueue_bc_request(struct rpc_rqst *req); 28 29 29 30 /* Socket backchannel transport methods */ 30 31 int xprt_setup_bc(struct rpc_xprt *xprt, unsigned int min_reqs); 31 32 void xprt_destroy_bc(struct rpc_xprt *xprt, unsigned int max_reqs); 32 33 void xprt_free_bc_rqst(struct rpc_rqst *req); 33 34 unsigned int xprt_bc_max_slots(struct rpc_xprt *xprt); 35 + void xprt_svc_destroy_nullify_bc(struct rpc_xprt *xprt, struct svc_serv **serv); 34 36 35 37 /* 36 38 * Determine if a shared backchannel is in use ··· 69 67 70 68 static inline void xprt_free_bc_request(struct rpc_rqst *req) 71 69 { 70 + } 71 + 72 + static inline void xprt_svc_destroy_nullify_bc(struct rpc_xprt *xprt, struct svc_serv **serv) 73 + { 74 + svc_destroy(serv); 72 75 } 73 76 #endif /* CONFIG_SUNRPC_BACKCHANNEL */ 74 77 #endif /* _LINUX_SUNRPC_BC_XPRT_H */
+33 -4
net/sunrpc/backchannel_rqst.c
··· 25 25 } 26 26 27 27 /* 28 + * Helper function to nullify backchannel server pointer in transport. 29 + * We need to synchronize setting the pointer to NULL (done so after 30 + * the backchannel server is shutdown) with the usage of that pointer 31 + * by the backchannel request processing routines 32 + * xprt_complete_bc_request() and rpcrdma_bc_receive_call(). 33 + */ 34 + void xprt_svc_destroy_nullify_bc(struct rpc_xprt *xprt, struct svc_serv **serv) 35 + { 36 + spin_lock(&xprt->bc_pa_lock); 37 + svc_destroy(serv); 38 + xprt->bc_serv = NULL; 39 + spin_unlock(&xprt->bc_pa_lock); 40 + } 41 + EXPORT_SYMBOL_GPL(xprt_svc_destroy_nullify_bc); 42 + 43 + /* 28 44 * Helper routines that track the number of preallocation elements 29 45 * on the transport. 30 46 */ ··· 370 354 void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied) 371 355 { 372 356 struct rpc_xprt *xprt = req->rq_xprt; 373 - struct svc_serv *bc_serv = xprt->bc_serv; 374 357 375 358 spin_lock(&xprt->bc_pa_lock); 376 359 list_del(&req->rq_bc_pa_list); ··· 380 365 set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); 381 366 382 367 dprintk("RPC: add callback request to list\n"); 383 - xprt_get(xprt); 384 - lwq_enqueue(&req->rq_bc_list, &bc_serv->sv_cb_list); 385 - svc_pool_wake_idle_thread(&bc_serv->sv_pools[0]); 368 + xprt_enqueue_bc_request(req); 386 369 } 370 + 371 + void xprt_enqueue_bc_request(struct rpc_rqst *req) 372 + { 373 + struct rpc_xprt *xprt = req->rq_xprt; 374 + struct svc_serv *bc_serv; 375 + 376 + xprt_get(xprt); 377 + spin_lock(&xprt->bc_pa_lock); 378 + bc_serv = xprt->bc_serv; 379 + if (bc_serv) { 380 + lwq_enqueue(&req->rq_bc_list, &bc_serv->sv_cb_list); 381 + svc_pool_wake_idle_thread(&bc_serv->sv_pools[0]); 382 + } 383 + spin_unlock(&xprt->bc_pa_lock); 384 + } 385 + EXPORT_SYMBOL_GPL(xprt_enqueue_bc_request);
+2 -6
net/sunrpc/xprtrdma/backchannel.c
··· 9 9 #include <linux/sunrpc/svc.h> 10 10 #include <linux/sunrpc/svc_xprt.h> 11 11 #include <linux/sunrpc/svc_rdma.h> 12 + #include <linux/sunrpc/bc_xprt.h> 12 13 13 14 #include "xprt_rdma.h" 14 15 #include <trace/events/rpcrdma.h> ··· 221 220 struct rpcrdma_rep *rep) 222 221 { 223 222 struct rpc_xprt *xprt = &r_xprt->rx_xprt; 224 - struct svc_serv *bc_serv; 225 223 struct rpcrdma_req *req; 226 224 struct rpc_rqst *rqst; 227 225 struct xdr_buf *buf; ··· 261 261 trace_xprtrdma_cb_call(r_xprt, rqst); 262 262 263 263 /* Queue rqst for ULP's callback service */ 264 - bc_serv = xprt->bc_serv; 265 - xprt_get(xprt); 266 - lwq_enqueue(&rqst->rq_bc_list, &bc_serv->sv_cb_list); 267 - 268 - svc_pool_wake_idle_thread(&bc_serv->sv_pools[0]); 264 + xprt_enqueue_bc_request(rqst); 269 265 270 266 r_xprt->rx_stats.bcall_count++; 271 267 return;