Pull NFS client updates from Anna Schumaker: "Stable bugfixes: - Fix -EACCESS on commit to DS handling - Fix initialization of nfs_page_array->npages - Only invalidate dentries that are actually invalid Features: - Enable NFSoRDMA transparent state migration - Add support for lookup-by-filehandle - Add support for nfs re-exporting Other bugfixes and cleanups: - Christoph cleaned up the way we declare NFS operations - Clean up various internal structures - Various cleanups to commits - Various improvements to error handling - Set the dt_type of . and .. entries in NFS v4 - Make slot allocation more reliable - Fix fscache stat printing - Fix uninitialized variable warnings - Fix potential list overrun in nfs_atomic_open() - Fix a race in NFSoRDMA RPC reply handler - Fix return size for nfs42_proc_copy() - Fix against MAC forgery timing attacks" * tag 'nfs-for-4.13-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (68 commits) NFS: Don't run wake_up_bit() when nobody is waiting... nfs: add export operations nfs4: add NFSv4 LOOKUPP handlers nfs: add a nfs_ilookup helper nfs: replace d_add with d_splice_alias in atomic_open sunrpc: use constant time memory comparison for mac NFSv4.2 fix size storage for nfs42_proc_copy xprtrdma: Fix documenting comments in frwr_ops.c xprtrdma: Replace PAGE_MASK with offset_in_page() xprtrdma: FMR does not need list_del_init() xprtrdma: Demote "connect" log messages NFSv4.1: Use seqid returned by EXCHANGE_ID after state migration NFSv4.1: Handle EXCHGID4_FLAG_CONFIRMED_R during NFSv4.1 migration xprtrdma: Don't defer MR recovery if ro_map fails xprtrdma: Fix FRWR invalidation error recovery xprtrdma: Fix client lock-up after application signal fires xprtrdma: Rename rpcrdma_req::rl_free xprtrdma: Pass only the list of registered MRs to ro_unmap_sync xprtrdma: Pre-mark remotely invalidated MRs xprtrdma: On invalidation failure, remove MWs from rl_registered ...
Unified · Split
| @@ -7,7 +7,7 @@ obj-$(CONFIG_NFS_FS) += nfs.o · 6 unmodified lines | |||
| 7 | CFLAGS_nfstrace.o += -I$(src) | 7 | CFLAGS_nfstrace.o += -I$(src) |
| 8 | nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ | 8 | nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ |
| 9 | io.o direct.o pagelist.o read.o symlink.o unlink.o \ | 9 | io.o direct.o pagelist.o read.o symlink.o unlink.o \ |
| 10 | write.o namespace.o mount_clnt.o nfstrace.o | 10 | write.o namespace.o mount_clnt.o nfstrace.o export.o |
| 11 | nfs-$(CONFIG_ROOT_NFS) += nfsroot.o | 11 | nfs-$(CONFIG_ROOT_NFS) += nfsroot.o |
| 12 | nfs-$(CONFIG_SYSCTL) += sysctl.o | 12 | nfs-$(CONFIG_SYSCTL) += sysctl.o |
| 13 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o | 13 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o |
| @@ -151,7 +151,7 @@ struct nfs_cache_array { · 150 unmodified lines | |||
| 151 | struct nfs_cache_array_entry array[0]; | 151 | struct nfs_cache_array_entry array[0]; |
| 152 | }; | 152 | }; |
| 153 | 153 | ||
| 154 | typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, int); | 154 | typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, bool); |
| 155 | typedef struct { | 155 | typedef struct { |
| 156 | struct file *file; | 156 | struct file *file; |
| 157 | struct page *page; | 157 | struct page *page; |
| @@ -165,8 +165,8 @@ typedef struct { · 7 unmodified lines | |||
| 165 | unsigned long timestamp; | 165 | unsigned long timestamp; |
| 166 | unsigned long gencount; | 166 | unsigned long gencount; |
| 167 | unsigned int cache_entry_index; | 167 | unsigned int cache_entry_index; |
| 168 | unsigned int plus:1; | 168 | bool plus; |
| 169 | unsigned int eof:1; | 169 | bool eof; |
| 170 | } nfs_readdir_descriptor_t; | 170 | } nfs_readdir_descriptor_t; |
| 171 | 171 | ||
| 172 | /* | 172 | /* |
| @@ -355,7 +355,7 @@ int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc, · 182 unmodified lines | |||
| 355 | if (error == -ENOTSUPP && desc->plus) { | 355 | if (error == -ENOTSUPP && desc->plus) { |
| 356 | NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS; | 356 | NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS; |
| 357 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); | 357 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
| 358 | desc->plus = 0; | 358 | desc->plus = false; |
| 359 | goto again; | 359 | goto again; |
| 360 | } | 360 | } |
| 361 | goto error; | 361 | goto error; |
| @@ -557,7 +557,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en · 195 unmodified lines | |||
| 557 | 557 | ||
| 558 | count++; | 558 | count++; |
| 559 | 559 | ||
| 560 | if (desc->plus != 0) | 560 | if (desc->plus) |
| 561 | nfs_prime_dcache(file_dentry(desc->file), entry); | 561 | nfs_prime_dcache(file_dentry(desc->file), entry); |
| 562 | 562 | ||
| 563 | status = nfs_readdir_add_to_array(entry, page); | 563 | status = nfs_readdir_add_to_array(entry, page); |
| @@ -860,7 +860,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) · 296 unmodified lines | |||
| 860 | desc->ctx = ctx; | 860 | desc->ctx = ctx; |
| 861 | desc->dir_cookie = &dir_ctx->dir_cookie; | 861 | desc->dir_cookie = &dir_ctx->dir_cookie; |
| 862 | desc->decode = NFS_PROTO(inode)->decode_dirent; | 862 | desc->decode = NFS_PROTO(inode)->decode_dirent; |
| 863 | desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0; | 863 | desc->plus = nfs_use_readdirplus(inode, ctx); |
| 864 | 864 | ||
| 865 | if (ctx->pos == 0 || nfs_attribute_cache_expired(inode)) | 865 | if (ctx->pos == 0 || nfs_attribute_cache_expired(inode)) |
| 866 | res = nfs_revalidate_mapping(inode, file->f_mapping); | 866 | res = nfs_revalidate_mapping(inode, file->f_mapping); |
| @@ -885,8 +885,8 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) · 18 unmodified lines | |||
| 885 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); | 885 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
| 886 | nfs_zap_caches(inode); | 886 | nfs_zap_caches(inode); |
| 887 | desc->page_index = 0; | 887 | desc->page_index = 0; |
| 888 | desc->plus = 0; | 888 | desc->plus = false; |
| 889 | desc->eof = 0; | 889 | desc->eof = false; |
| 890 | continue; | 890 | continue; |
| 891 | } | 891 | } |
| 892 | if (res < 0) | 892 | if (res < 0) |
| @@ -1115,11 +1115,13 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) · 222 unmodified lines | |||
| 1115 | /* Force a full look up iff the parent directory has changed */ | 1115 | /* Force a full look up iff the parent directory has changed */ |
| 1116 | if (!nfs_is_exclusive_create(dir, flags) && | 1116 | if (!nfs_is_exclusive_create(dir, flags) && |
| 1117 | nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU)) { | 1117 | nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU)) { |
| 1118 | 1118 | error = nfs_lookup_verify_inode(inode, flags); | |
| 1119 | if (nfs_lookup_verify_inode(inode, flags)) { | 1119 | if (error) { |
| 1120 | if (flags & LOOKUP_RCU) | 1120 | if (flags & LOOKUP_RCU) |
| 1121 | return -ECHILD; | 1121 | return -ECHILD; |
| 1122 | goto out_zap_parent; | 1122 | if (error == -ESTALE) |
| 1123 | goto out_zap_parent; | ||
| 1124 | goto out_error; | ||
| 1123 | } | 1125 | } |
| 1124 | nfs_advise_use_readdirplus(dir); | 1126 | nfs_advise_use_readdirplus(dir); |
| 1125 | goto out_valid; | 1127 | goto out_valid; |
| @@ -1144,8 +1146,10 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) · 18 unmodified lines | |||
| 1144 | trace_nfs_lookup_revalidate_enter(dir, dentry, flags); | 1146 | trace_nfs_lookup_revalidate_enter(dir, dentry, flags); |
| 1145 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); | 1147 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); |
| 1146 | trace_nfs_lookup_revalidate_exit(dir, dentry, flags, error); | 1148 | trace_nfs_lookup_revalidate_exit(dir, dentry, flags, error); |
| 1147 | if (error) | 1149 | if (error == -ESTALE || error == -ENOENT) |
| 1148 | goto out_bad; | 1150 | goto out_bad; |
| 1151 | if (error) | ||
| 1152 | goto out_error; | ||
| 1149 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) | 1153 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) |
| 1150 | goto out_bad; | 1154 | goto out_bad; |
| 1151 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) | 1155 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) |
| @@ -1427,8 +1431,10 @@ static int nfs_finish_open(struct nfs_open_context *ctx, · 275 unmodified lines | |||
| 1427 | err = finish_open(file, dentry, do_open, opened); | 1431 | err = finish_open(file, dentry, do_open, opened); |
| 1428 | if (err) | 1432 | if (err) |
| 1429 | goto out; | 1433 | goto out; |
| 1430 | nfs_file_set_open_context(file, ctx); | 1434 | if (S_ISREG(file->f_path.dentry->d_inode->i_mode)) |
| 1431 | 1435 | nfs_file_set_open_context(file, ctx); | |
| 1436 | else | ||
| 1437 | err = -ESTALE; | ||
| 1432 | out: | 1438 | out: |
| 1433 | return err; | 1439 | return err; |
| 1434 | } | 1440 | } |
| @@ -1512,7 +1518,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, · 77 unmodified lines | |||
| 1512 | d_drop(dentry); | 1518 | d_drop(dentry); |
| 1513 | switch (err) { | 1519 | switch (err) { |
| 1514 | case -ENOENT: | 1520 | case -ENOENT: |
| 1515 | d_add(dentry, NULL); | 1521 | d_splice_alias(NULL, dentry); |
| 1516 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1522 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
| 1517 | break; | 1523 | break; |
| 1518 | case -EISDIR: | 1524 | case -EISDIR: |
| @@ -2035,7 +2041,11 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, · 516 unmodified lines | |||
| 2035 | } | 2041 | } |
| 2036 | 2042 | ||
| 2037 | error = rpc_wait_for_completion_task(task); | 2043 | error = rpc_wait_for_completion_task(task); |
| 2038 | if (error == 0) | 2044 | if (error != 0) { |
| 2045 | ((struct nfs_renamedata *)task->tk_calldata)->cancelled = 1; | ||
| 2046 | /* Paired with the atomic_dec_and_test() barrier in rpc_do_put_task() */ | ||
| 2047 | smp_wmb(); | ||
| 2048 | } else | ||
| 2039 | error = task->tk_status; | 2049 | error = task->tk_status; |
| 2040 | rpc_put_task(task); | 2050 | rpc_put_task(task); |
| 2041 | nfs_mark_for_revalidate(old_inode); | 2051 | nfs_mark_for_revalidate(old_inode); |
| @@ -0,0 +1,177 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2015, Primary Data, Inc. All rights reserved. | ||
| 3 | * | ||
| 4 | * Tao Peng <bergwolf@primarydata.com> | ||
| 5 | */ | ||
| 6 | #include <linux/dcache.h> | ||
| 7 | #include <linux/exportfs.h> | ||
| 8 | #include <linux/nfs.h> | ||
| 9 | #include <linux/nfs_fs.h> | ||
| 10 | |||
| 11 | #include "internal.h" | ||
| 12 | #include "nfstrace.h" | ||
| 13 | |||
| 14 | #define NFSDBG_FACILITY NFSDBG_VFS | ||
| 15 | |||
| 16 | enum { | ||
| 17 | FILEID_HIGH_OFF = 0, /* inode fileid high */ | ||
| 18 | FILEID_LOW_OFF, /* inode fileid low */ | ||
| 19 | FILE_I_TYPE_OFF, /* inode type */ | ||
| 20 | EMBED_FH_OFF /* embeded server fh */ | ||
| 21 | }; | ||
| 22 | |||
| 23 | |||
| 24 | static struct nfs_fh *nfs_exp_embedfh(__u32 *p) | ||
| 25 | { | ||
| 26 | return (struct nfs_fh *)(p + EMBED_FH_OFF); | ||
| 27 | } | ||
| 28 | |||
| 29 | /* | ||
| 30 | * Let's break subtree checking for now... otherwise we'll have to embed parent fh | ||
| 31 | * but there might not be enough space. | ||
| 32 | */ | ||
| 33 | static int | ||
| 34 | nfs_encode_fh(struct inode *inode, __u32 *p, int *max_len, struct inode *parent) | ||
| 35 | { | ||
| 36 | struct nfs_fh *server_fh = NFS_FH(inode); | ||
| 37 | struct nfs_fh *clnt_fh = nfs_exp_embedfh(p); | ||
| 38 | size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size; | ||
| 39 | int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size); | ||
| 40 | |||
| 41 | dprintk("%s: max fh len %d inode %p parent %p", | ||
| 42 | __func__, *max_len, inode, parent); | ||
| 43 | |||
| 44 | if (*max_len < len || IS_AUTOMOUNT(inode)) { | ||
| 45 | dprintk("%s: fh len %d too small, required %d\n", | ||
| 46 | __func__, *max_len, len); | ||
| 47 | *max_len = len; | ||
| 48 | return FILEID_INVALID; | ||
| 49 | } | ||
| 50 | if (IS_AUTOMOUNT(inode)) { | ||
| 51 | *max_len = FILEID_INVALID; | ||
| 52 | goto out; | ||
| 53 | } | ||
| 54 | |||
| 55 | p[FILEID_HIGH_OFF] = NFS_FILEID(inode) >> 32; | ||
| 56 | p[FILEID_LOW_OFF] = NFS_FILEID(inode); | ||
| 57 | p[FILE_I_TYPE_OFF] = inode->i_mode & S_IFMT; | ||
| 58 | p[len - 1] = 0; /* Padding */ | ||
| 59 | nfs_copy_fh(clnt_fh, server_fh); | ||
| 60 | *max_len = len; | ||
| 61 | out: | ||
| 62 | dprintk("%s: result fh fileid %llu mode %u size %d\n", | ||
| 63 | __func__, NFS_FILEID(inode), inode->i_mode, *max_len); | ||
| 64 | return *max_len; | ||
| 65 | } | ||
| 66 | |||
| 67 | static struct dentry * | ||
| 68 | nfs_fh_to_dentry(struct super_block *sb, struct fid *fid, | ||
| 69 | int fh_len, int fh_type) | ||
| 70 | { | ||
| 71 | struct nfs4_label *label = NULL; | ||
| 72 | struct nfs_fattr *fattr = NULL; | ||
| 73 | struct nfs_fh *server_fh = nfs_exp_embedfh(fid->raw); | ||
| 74 | size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size; | ||
| 75 | const struct nfs_rpc_ops *rpc_ops; | ||
| 76 | struct dentry *dentry; | ||
| 77 | struct inode *inode; | ||
| 78 | int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size); | ||
| 79 | u32 *p = fid->raw; | ||
| 80 | int ret; | ||
| 81 | |||
| 82 | /* NULL translates to ESTALE */ | ||
| 83 | if (fh_len < len || fh_type != len) | ||
| 84 | return NULL; | ||
| 85 | |||
| 86 | fattr = nfs_alloc_fattr(); | ||
| 87 | if (fattr == NULL) { | ||
| 88 | dentry = ERR_PTR(-ENOMEM); | ||
| 89 | goto out; | ||
| 90 | } | ||
| 91 | |||
| 92 | fattr->fileid = ((u64)p[FILEID_HIGH_OFF] << 32) + p[FILEID_LOW_OFF]; | ||
| 93 | fattr->mode = p[FILE_I_TYPE_OFF]; | ||
| 94 | fattr->valid |= NFS_ATTR_FATTR_FILEID | NFS_ATTR_FATTR_TYPE; | ||
| 95 | |||
| 96 | dprintk("%s: fileid %llu mode %d\n", __func__, fattr->fileid, fattr->mode); | ||
| 97 | |||
| 98 | inode = nfs_ilookup(sb, fattr, server_fh); | ||
| 99 | if (inode) | ||
| 100 | goto out_found; | ||
| 101 | |||
| 102 | label = nfs4_label_alloc(NFS_SB(sb), GFP_KERNEL); | ||
| 103 | if (IS_ERR(label)) { | ||
| 104 | dentry = ERR_CAST(label); | ||
| 105 | goto out_free_fattr; | ||
| 106 | } | ||
| 107 | |||
| 108 | rpc_ops = NFS_SB(sb)->nfs_client->rpc_ops; | ||
| 109 | ret = rpc_ops->getattr(NFS_SB(sb), server_fh, fattr, label); | ||
| 110 | if (ret) { | ||
| 111 | dprintk("%s: getattr failed %d\n", __func__, ret); | ||
| 112 | dentry = ERR_PTR(ret); | ||
| 113 | goto out_free_label; | ||
| 114 | } | ||
| 115 | |||
| 116 | inode = nfs_fhget(sb, server_fh, fattr, label); | ||
| 117 | |||
| 118 | out_found: | ||
| 119 | dentry = d_obtain_alias(inode); | ||
| 120 | |||
| 121 | out_free_label: | ||
| 122 | nfs4_label_free(label); | ||
| 123 | out_free_fattr: | ||
| 124 | nfs_free_fattr(fattr); | ||
| 125 | out: | ||
| 126 | return dentry; | ||
| 127 | } | ||
| 128 | |||
| 129 | static struct dentry * | ||
| 130 | nfs_get_parent(struct dentry *dentry) | ||
| 131 | { | ||
| 132 | int ret; | ||
| 133 | struct inode *inode = d_inode(dentry), *pinode; | ||
| 134 | struct super_block *sb = inode->i_sb; | ||
| 135 | struct nfs_server *server = NFS_SB(sb); | ||
| 136 | struct nfs_fattr *fattr = NULL; | ||
| 137 | struct nfs4_label *label = NULL; | ||
| 138 | struct dentry *parent; | ||
| 139 | struct nfs_rpc_ops const *ops = server->nfs_client->rpc_ops; | ||
| 140 | struct nfs_fh fh; | ||
| 141 | |||
| 142 | if (!ops->lookupp) | ||
| 143 | return ERR_PTR(-EACCES); | ||
| 144 | |||
| 145 | fattr = nfs_alloc_fattr(); | ||
| 146 | if (fattr == NULL) { | ||
| 147 | parent = ERR_PTR(-ENOMEM); | ||
| 148 | goto out; | ||
| 149 | } | ||
| 150 | |||
| 151 | label = nfs4_label_alloc(server, GFP_KERNEL); | ||
| 152 | if (IS_ERR(label)) { | ||
| 153 | parent = ERR_CAST(label); | ||
| 154 | goto out_free_fattr; | ||
| 155 | } | ||
| 156 | |||
| 157 | ret = ops->lookupp(inode, &fh, fattr, label); | ||
| 158 | if (ret) { | ||
| 159 | parent = ERR_PTR(ret); | ||
| 160 | goto out_free_label; | ||
| 161 | } | ||
| 162 | |||
| 163 | pinode = nfs_fhget(sb, &fh, fattr, label); | ||
| 164 | parent = d_obtain_alias(pinode); | ||
| 165 | out_free_label: | ||
| 166 | nfs4_label_free(label); | ||
| 167 | out_free_fattr: | ||
| 168 | nfs_free_fattr(fattr); | ||
| 169 | out: | ||
| 170 | return parent; | ||
| 171 | } | ||
| 172 | |||
| 173 | const struct export_operations nfs_export_ops = { | ||
| 174 | .encode_fh = nfs_encode_fh, | ||
| 175 | .fh_to_dentry = nfs_fh_to_dentry, | ||
| 176 | .get_parent = nfs_get_parent, | ||
| 177 | }; | ||
| @@ -126,32 +126,13 @@ static int filelayout_async_handle_error(struct rpc_task *task, · 125 unmodified lines | |||
| 126 | { | 126 | { |
| 127 | struct pnfs_layout_hdr *lo = lseg->pls_layout; | 127 | struct pnfs_layout_hdr *lo = lseg->pls_layout; |
| 128 | struct inode *inode = lo->plh_inode; | 128 | struct inode *inode = lo->plh_inode; |
| 129 | struct nfs_server *mds_server = NFS_SERVER(inode); | ||
| 130 | struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); | 129 | struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); |
| 131 | struct nfs_client *mds_client = mds_server->nfs_client; | ||
| 132 | struct nfs4_slot_table *tbl = &clp->cl_session->fc_slot_table; | 130 | struct nfs4_slot_table *tbl = &clp->cl_session->fc_slot_table; |
| 133 | 131 | ||
| 134 | if (task->tk_status >= 0) | 132 | if (task->tk_status >= 0) |
| 135 | return 0; | 133 | return 0; |
| 136 | 134 | ||
| 137 | switch (task->tk_status) { | 135 | switch (task->tk_status) { |
| 138 | /* MDS state errors */ | ||
| 139 | case -NFS4ERR_DELEG_REVOKED: | ||
| 140 | case -NFS4ERR_ADMIN_REVOKED: | ||
| 141 | case -NFS4ERR_BAD_STATEID: | ||
| 142 | case -NFS4ERR_OPENMODE: | ||
| 143 | if (state == NULL) | ||
| 144 | break; | ||
| 145 | if (nfs4_schedule_stateid_recovery(mds_server, state) < 0) | ||
| 146 | goto out_bad_stateid; | ||
| 147 | goto wait_on_recovery; | ||
| 148 | case -NFS4ERR_EXPIRED: | ||
| 149 | if (state != NULL) { | ||
| 150 | if (nfs4_schedule_stateid_recovery(mds_server, state) < 0) | ||
| 151 | goto out_bad_stateid; | ||
| 152 | } | ||
| 153 | nfs4_schedule_lease_recovery(mds_client); | ||
| 154 | goto wait_on_recovery; | ||
| 155 | /* DS session errors */ | 136 | /* DS session errors */ |
| 156 | case -NFS4ERR_BADSESSION: | 137 | case -NFS4ERR_BADSESSION: |
| 157 | case -NFS4ERR_BADSLOT: | 138 | case -NFS4ERR_BADSLOT: |
| @@ -172,6 +153,7 @@ static int filelayout_async_handle_error(struct rpc_task *task, · 14 unmodified lines | |||
| 172 | case -NFS4ERR_RETRY_UNCACHED_REP: | 153 | case -NFS4ERR_RETRY_UNCACHED_REP: |
| 173 | break; | 154 | break; |
| 174 | /* Invalidate Layout errors */ | 155 | /* Invalidate Layout errors */ |
| 156 | case -NFS4ERR_ACCESS: | ||
| 175 | case -NFS4ERR_PNFS_NO_LAYOUT: | 157 | case -NFS4ERR_PNFS_NO_LAYOUT: |
| 176 | case -ESTALE: /* mapped NFS4ERR_STALE */ | 158 | case -ESTALE: /* mapped NFS4ERR_STALE */ |
| 177 | case -EBADHANDLE: /* mapped NFS4ERR_BADHANDLE */ | 159 | case -EBADHANDLE: /* mapped NFS4ERR_BADHANDLE */ |
| @@ -202,26 +184,17 @@ static int filelayout_async_handle_error(struct rpc_task *task, · 24 unmodified lines | |||
| 202 | task->tk_status); | 184 | task->tk_status); |
| 203 | nfs4_mark_deviceid_unavailable(devid); | 185 | nfs4_mark_deviceid_unavailable(devid); |
| 204 | pnfs_error_mark_layout_for_return(inode, lseg); | 186 | pnfs_error_mark_layout_for_return(inode, lseg); |
| 187 | pnfs_set_lo_fail(lseg); | ||
| 205 | rpc_wake_up(&tbl->slot_tbl_waitq); | 188 | rpc_wake_up(&tbl->slot_tbl_waitq); |
| 206 | /* fall through */ | 189 | /* fall through */ |
| 207 | default: | 190 | default: |
| 208 | pnfs_set_lo_fail(lseg); | ||
| 209 | reset: | 191 | reset: |
| 210 | dprintk("%s Retry through MDS. Error %d\n", __func__, | 192 | dprintk("%s Retry through MDS. Error %d\n", __func__, |
| 211 | task->tk_status); | 193 | task->tk_status); |
| 212 | return -NFS4ERR_RESET_TO_MDS; | 194 | return -NFS4ERR_RESET_TO_MDS; |
| 213 | } | 195 | } |
| 214 | out: | ||
| 215 | task->tk_status = 0; | 196 | task->tk_status = 0; |
| 216 | return -EAGAIN; | 197 | return -EAGAIN; |
| 217 | out_bad_stateid: | ||
| 218 | task->tk_status = -EIO; | ||
| 219 | return 0; | ||
| 220 | wait_on_recovery: | ||
| 221 | rpc_sleep_on(&mds_client->cl_rpcwaitq, task, NULL); | ||
| 222 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &mds_client->cl_state) == 0) | ||
| 223 | rpc_wake_up_queued_task(&mds_client->cl_rpcwaitq, task); | ||
| 224 | goto out; | ||
| 225 | } | 198 | } |
| 226 | 199 | ||
| 227 | /* NFS_PROTO call done callback routines */ | 200 | /* NFS_PROTO call done callback routines */ |
| @@ -1050,34 +1050,10 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task, · 1049 unmodified lines | |||
| 1050 | { | 1050 | { |
| 1051 | struct pnfs_layout_hdr *lo = lseg->pls_layout; | 1051 | struct pnfs_layout_hdr *lo = lseg->pls_layout; |
| 1052 | struct inode *inode = lo->plh_inode; | 1052 | struct inode *inode = lo->plh_inode; |
| 1053 | struct nfs_server *mds_server = NFS_SERVER(inode); | ||
| 1054 | |||
| 1055 | struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx); | 1053 | struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx); |
| 1056 | struct nfs_client *mds_client = mds_server->nfs_client; | ||
| 1057 | struct nfs4_slot_table *tbl = &clp->cl_session->fc_slot_table; | 1054 | struct nfs4_slot_table *tbl = &clp->cl_session->fc_slot_table; |
| 1058 | 1055 | ||
| 1059 | switch (task->tk_status) { | 1056 | switch (task->tk_status) { |
| 1060 | /* MDS state errors */ | ||
| 1061 | case -NFS4ERR_DELEG_REVOKED: | ||
| 1062 | case -NFS4ERR_ADMIN_REVOKED: | ||
| 1063 | case -NFS4ERR_BAD_STATEID: | ||
| 1064 | if (state == NULL) | ||
| 1065 | break; | ||
| 1066 | nfs_remove_bad_delegation(state->inode, NULL); | ||
| 1067 | case -NFS4ERR_OPENMODE: | ||
| 1068 | if (state == NULL) | ||
| 1069 | break; | ||
| 1070 | if (nfs4_schedule_stateid_recovery(mds_server, state) < 0) | ||
| 1071 | goto out_bad_stateid; | ||
| 1072 | goto wait_on_recovery; | ||
| 1073 | case -NFS4ERR_EXPIRED: | ||
| 1074 | if (state != NULL) { | ||
| 1075 | if (nfs4_schedule_stateid_recovery(mds_server, state) < 0) | ||
| 1076 | goto out_bad_stateid; | ||
| 1077 | } | ||
| 1078 | nfs4_schedule_lease_recovery(mds_client); | ||
| 1079 | goto wait_on_recovery; | ||
| 1080 | /* DS session errors */ | ||
| 1081 | case -NFS4ERR_BADSESSION: | 1057 | case -NFS4ERR_BADSESSION: |
| 1082 | case -NFS4ERR_BADSLOT: | 1058 | case -NFS4ERR_BADSLOT: |
| 1083 | case -NFS4ERR_BAD_HIGH_SLOT: | 1059 | case -NFS4ERR_BAD_HIGH_SLOT: |
| @@ -1137,17 +1113,8 @@ reset: · 53 unmodified lines | |||
| 1137 | task->tk_status); | 1113 | task->tk_status); |
| 1138 | return -NFS4ERR_RESET_TO_MDS; | 1114 | return -NFS4ERR_RESET_TO_MDS; |
| 1139 | } | 1115 | } |
| 1140 | out: | ||
| 1141 | task->tk_status = 0; | 1116 | task->tk_status = 0; |
| 1142 | return -EAGAIN; | 1117 | return -EAGAIN; |
| 1143 | out_bad_stateid: | ||
| 1144 | task->tk_status = -EIO; | ||
| 1145 | return 0; | ||
| 1146 | wait_on_recovery: | ||
| 1147 | rpc_sleep_on(&mds_client->cl_rpcwaitq, task, NULL); | ||
| 1148 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &mds_client->cl_state) == 0) | ||
| 1149 | rpc_wake_up_queued_task(&mds_client->cl_rpcwaitq, task); | ||
| 1150 | goto out; | ||
| 1151 | } | 1118 | } |
| 1152 | 1119 | ||
| 1153 | /* Retry all errors through either pNFS or MDS except for -EJUKEBOX */ | 1120 | /* Retry all errors through either pNFS or MDS except for -EJUKEBOX */ |
| @@ -386,6 +386,28 @@ void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, · 385 unmodified lines | |||
| 386 | #endif | 386 | #endif |
| 387 | EXPORT_SYMBOL_GPL(nfs_setsecurity); | 387 | EXPORT_SYMBOL_GPL(nfs_setsecurity); |
| 388 | 388 | ||
| 389 | /* Search for inode identified by fh, fileid and i_mode in inode cache. */ | ||
| 390 | struct inode * | ||
| 391 | nfs_ilookup(struct super_block *sb, struct nfs_fattr *fattr, struct nfs_fh *fh) | ||
| 392 | { | ||
| 393 | struct nfs_find_desc desc = { | ||
| 394 | .fh = fh, | ||
| 395 | .fattr = fattr, | ||
| 396 | }; | ||
| 397 | struct inode *inode; | ||
| 398 | unsigned long hash; | ||
| 399 | |||
| 400 | if (!(fattr->valid & NFS_ATTR_FATTR_FILEID) || | ||
| 401 | !(fattr->valid & NFS_ATTR_FATTR_TYPE)) | ||
| 402 | return NULL; | ||
| 403 | |||
| 404 | hash = nfs_fattr_to_ino_t(fattr); | ||
| 405 | inode = ilookup5(sb, hash, nfs_find_actor, &desc); | ||
| 406 | |||
| 407 | dprintk("%s: returning %p\n", __func__, inode); | ||
| 408 | return inode; | ||
| 409 | } | ||
| 410 | |||
| 389 | /* | 411 | /* |
| 390 | * This is our front-end to iget that looks up inodes by file handle | 412 | * This is our front-end to iget that looks up inodes by file handle |
| 391 | * instead of inode number. | 413 | * instead of inode number. |
| @@ -525,8 +547,14 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st · 133 unmodified lines | |||
| 525 | nfs_fscache_init_inode(inode); | 547 | nfs_fscache_init_inode(inode); |
| 526 | 548 | ||
| 527 | unlock_new_inode(inode); | 549 | unlock_new_inode(inode); |
| 528 | } else | 550 | } else { |
| 529 | nfs_refresh_inode(inode, fattr); | 551 | int err = nfs_refresh_inode(inode, fattr); |
| 552 | if (err < 0) { | ||
| 553 | iput(inode); | ||
| 554 | inode = ERR_PTR(err); | ||
| 555 | goto out_no_inode; | ||
| 556 | } | ||
| 557 | } | ||
| 530 | dprintk("NFS: nfs_fhget(%s/%Lu fh_crc=0x%08x ct=%d)\n", | 558 | dprintk("NFS: nfs_fhget(%s/%Lu fh_crc=0x%08x ct=%d)\n", |
| 531 | inode->i_sb->s_id, | 559 | inode->i_sb->s_id, |
| 532 | (unsigned long long)NFS_FILEID(inode), | 560 | (unsigned long long)NFS_FILEID(inode), |
| @@ -1315,9 +1343,9 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat · 782 unmodified lines | |||
| 1315 | return 0; | 1343 | return 0; |
| 1316 | /* Has the inode gone and changed behind our back? */ | 1344 | /* Has the inode gone and changed behind our back? */ |
| 1317 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) | 1345 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) |
| 1318 | return -EIO; | 1346 | return -ESTALE; |
| 1319 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | 1347 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) |
| 1320 | return -EIO; | 1348 | return -ESTALE; |
| 1321 | 1349 | ||
| 1322 | if (!nfs_file_has_buffered_writers(nfsi)) { | 1350 | if (!nfs_file_has_buffered_writers(nfsi)) { |
| 1323 | /* Verify a few of the more important attributes */ | 1351 | /* Verify a few of the more important attributes */ |
| @@ -11,6 +11,8 @@ · 10 unmodified lines | |||
| 11 | 11 | ||
| 12 | #define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS) | 12 | #define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS) |
| 13 | 13 | ||
| 14 | extern const struct export_operations nfs_export_ops; | ||
| 15 | |||
| 14 | struct nfs_string; | 16 | struct nfs_string; |
| 15 | 17 | ||
| 16 | /* Maximum number of readahead requests | 18 | /* Maximum number of readahead requests |
| @@ -273,17 +275,17 @@ static inline bool nfs_match_open_context(const struct nfs_open_context *ctx1, · 256 unmodified lines | |||
| 273 | /* nfs2xdr.c */ | 275 | /* nfs2xdr.c */ |
| 274 | extern const struct rpc_procinfo nfs_procedures[]; | 276 | extern const struct rpc_procinfo nfs_procedures[]; |
| 275 | extern int nfs2_decode_dirent(struct xdr_stream *, | 277 | extern int nfs2_decode_dirent(struct xdr_stream *, |
| 276 | struct nfs_entry *, int); | 278 | struct nfs_entry *, bool); |
| 277 | 279 | ||
| 278 | /* nfs3xdr.c */ | 280 | /* nfs3xdr.c */ |
| 279 | extern const struct rpc_procinfo nfs3_procedures[]; | 281 | extern const struct rpc_procinfo nfs3_procedures[]; |
| 280 | extern int nfs3_decode_dirent(struct xdr_stream *, | 282 | extern int nfs3_decode_dirent(struct xdr_stream *, |
| 281 | struct nfs_entry *, int); | 283 | struct nfs_entry *, bool); |
| 282 | 284 | ||
| 283 | /* nfs4xdr.c */ | 285 | /* nfs4xdr.c */ |
| 284 | #if IS_ENABLED(CONFIG_NFS_V4) | 286 | #if IS_ENABLED(CONFIG_NFS_V4) |
| 285 | extern int nfs4_decode_dirent(struct xdr_stream *, | 287 | extern int nfs4_decode_dirent(struct xdr_stream *, |
| 286 | struct nfs_entry *, int); | 288 | struct nfs_entry *, bool); |
| 287 | #endif | 289 | #endif |
| 288 | #ifdef CONFIG_NFS_V4_1 | 290 | #ifdef CONFIG_NFS_V4_1 |
| 289 | extern const u32 nfs41_maxread_overhead; | 291 | extern const u32 nfs41_maxread_overhead; |
| @@ -939,7 +939,7 @@ static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr, · 938 unmodified lines | |||
| 939 | * }; | 939 | * }; |
| 940 | */ | 940 | */ |
| 941 | int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | 941 | int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, |
| 942 | int plus) | 942 | bool plus) |
| 943 | { | 943 | { |
| 944 | __be32 *p; | 944 | __be32 *p; |
| 945 | int error; | 945 | int error; |
| @@ -621,7 +621,7 @@ out: · 620 unmodified lines | |||
| 621 | */ | 621 | */ |
| 622 | static int | 622 | static int |
| 623 | nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | 623 | nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, |
| 624 | u64 cookie, struct page **pages, unsigned int count, int plus) | 624 | u64 cookie, struct page **pages, unsigned int count, bool plus) |
| 625 | { | 625 | { |
| 626 | struct inode *dir = d_inode(dentry); | 626 | struct inode *dir = d_inode(dentry); |
| 627 | __be32 *verf = NFS_I(dir)->cookieverf; | 627 | __be32 *verf = NFS_I(dir)->cookieverf; |
| @@ -1991,7 +1991,7 @@ out_status: · 1990 unmodified lines | |||
| 1991 | * }; | 1991 | * }; |
| 1992 | */ | 1992 | */ |
| 1993 | int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | 1993 | int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, |
| 1994 | int plus) | 1994 | bool plus) |
| 1995 | { | 1995 | { |
| 1996 | struct nfs_entry old = *entry; | 1996 | struct nfs_entry old = *entry; |
| 1997 | __be32 *p; | 1997 | __be32 *p; |
| @@ -146,7 +146,7 @@ static ssize_t _nfs42_proc_copy(struct file *src, · 145 unmodified lines | |||
| 146 | loff_t pos_src = args->src_pos; | 146 | loff_t pos_src = args->src_pos; |
| 147 | loff_t pos_dst = args->dst_pos; | 147 | loff_t pos_dst = args->dst_pos; |
| 148 | size_t count = args->count; | 148 | size_t count = args->count; |
| 149 | int status; | 149 | ssize_t status; |
| 150 | 150 | ||
| 151 | status = nfs4_set_rw_stateid(&args->src_stateid, src_lock->open_context, | 151 | status = nfs4_set_rw_stateid(&args->src_stateid, src_lock->open_context, |
| 152 | src_lock, FMODE_READ); | 152 | src_lock, FMODE_READ); |
| @@ -414,6 +414,7 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp, · 413 unmodified lines | |||
| 414 | if (clp != old) | 414 | if (clp != old) |
| 415 | clp->cl_preserve_clid = true; | 415 | clp->cl_preserve_clid = true; |
| 416 | nfs_put_client(clp); | 416 | nfs_put_client(clp); |
| 417 | clear_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags); | ||
| 417 | return old; | 418 | return old; |
| 418 | 419 | ||
| 419 | error: | 420 | error: |
| @@ -852,6 +853,8 @@ static int nfs4_set_client(struct nfs_server *server, · 432 unmodified lines | |||
| 852 | set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); | 853 | set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); |
| 853 | if (server->options & NFS_OPTION_MIGRATION) | 854 | if (server->options & NFS_OPTION_MIGRATION) |
| 854 | set_bit(NFS_CS_MIGRATION, &cl_init.init_flags); | 855 | set_bit(NFS_CS_MIGRATION, &cl_init.init_flags); |
| 856 | if (test_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status)) | ||
| 857 | set_bit(NFS_CS_TSM_POSSIBLE, &cl_init.init_flags); | ||
| 855 | 858 | ||
| 856 | /* Allocate or find a client reference we can use */ | 859 | /* Allocate or find a client reference we can use */ |
| 857 | clp = nfs_get_client(&cl_init); | 860 | clp = nfs_get_client(&cl_init); |
| @@ -1212,9 +1215,11 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname, · 354 unmodified lines | |||
| 1212 | return -EAFNOSUPPORT; | 1215 | return -EAFNOSUPPORT; |
| 1213 | 1216 | ||
| 1214 | nfs_server_remove_lists(server); | 1217 | nfs_server_remove_lists(server); |
| 1218 | set_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status); | ||
| 1215 | error = nfs4_set_client(server, hostname, sap, salen, buf, | 1219 | error = nfs4_set_client(server, hostname, sap, salen, buf, |
| 1216 | clp->cl_proto, clnt->cl_timeout, | 1220 | clp->cl_proto, clnt->cl_timeout, |
| 1217 | clp->cl_minorversion, net); | 1221 | clp->cl_minorversion, net); |
| 1222 | clear_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status); | ||
| 1218 | nfs_put_client(clp); | 1223 | nfs_put_client(clp); |
| 1219 | if (error != 0) { | 1224 | if (error != 0) { |
| 1220 | nfs_server_insert_lists(server); | 1225 | nfs_server_insert_lists(server); |
| @@ -364,7 +364,8 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *typ · 363 unmodified lines | |||
| 364 | ret = -EINVAL; | 364 | ret = -EINVAL; |
| 365 | } else { | 365 | } else { |
| 366 | ret = kstrtol(id_str, 10, &id_long); | 366 | ret = kstrtol(id_str, 10, &id_long); |
| 367 | *id = (__u32)id_long; | 367 | if (!ret) |
| 368 | *id = (__u32)id_long; | ||
| 368 | } | 369 | } |
| 369 | return ret; | 370 | return ret; |
| 370 | } | 371 | } |
| @@ -275,6 +275,7 @@ const u32 nfs4_fs_locations_bitmap[3] = { · 274 unmodified lines | |||
| 275 | static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry, | 275 | static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry, |
| 276 | struct nfs4_readdir_arg *readdir) | 276 | struct nfs4_readdir_arg *readdir) |
| 277 | { | 277 | { |
| 278 | unsigned int attrs = FATTR4_WORD0_FILEID | FATTR4_WORD0_TYPE; | ||
| 278 | __be32 *start, *p; | 279 | __be32 *start, *p; |
| 279 | 280 | ||
| 280 | if (cookie > 2) { | 281 | if (cookie > 2) { |
| @@ -305,8 +306,9 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent · 24 unmodified lines | |||
| 305 | memcpy(p, ".\0\0\0", 4); /* entry */ | 306 | memcpy(p, ".\0\0\0", 4); /* entry */ |
| 306 | p++; | 307 | p++; |
| 307 | *p++ = xdr_one; /* bitmap length */ | 308 | *p++ = xdr_one; /* bitmap length */ |
| 308 | *p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */ | 309 | *p++ = htonl(attrs); /* bitmap */ |
| 309 | *p++ = htonl(8); /* attribute buffer length */ | 310 | *p++ = htonl(12); /* attribute buffer length */ |
| 311 | *p++ = htonl(NF4DIR); | ||
| 310 | p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry))); | 312 | p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry))); |
| 311 | } | 313 | } |
| 312 | 314 | ||
| @@ -317,8 +319,9 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent · 4 unmodified lines | |||
| 317 | memcpy(p, "..\0\0", 4); /* entry */ | 319 | memcpy(p, "..\0\0", 4); /* entry */ |
| 318 | p++; | 320 | p++; |
| 319 | *p++ = xdr_one; /* bitmap length */ | 321 | *p++ = xdr_one; /* bitmap length */ |
| 320 | *p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */ | 322 | *p++ = htonl(attrs); /* bitmap */ |
| 321 | *p++ = htonl(8); /* attribute buffer length */ | 323 | *p++ = htonl(12); /* attribute buffer length */ |
| 324 | *p++ = htonl(NF4DIR); | ||
| 322 | p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry->d_parent))); | 325 | p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry->d_parent))); |
| 323 | 326 | ||
| 324 | readdir->pgbase = (char *)p - (char *)start; | 327 | readdir->pgbase = (char *)p - (char *)start; |
| @@ -1034,11 +1037,11 @@ struct nfs4_opendata { · 709 unmodified lines | |||
| 1034 | struct nfs4_state *state; | 1037 | struct nfs4_state *state; |
| 1035 | struct iattr attrs; | 1038 | struct iattr attrs; |
| 1036 | unsigned long timestamp; | 1039 | unsigned long timestamp; |
| 1037 | unsigned int rpc_done : 1; | 1040 | bool rpc_done; |
| 1038 | unsigned int file_created : 1; | 1041 | bool file_created; |
| 1039 | unsigned int is_recover : 1; | 1042 | bool is_recover; |
| 1043 | bool cancelled; | ||
| 1040 | int rpc_status; | 1044 | int rpc_status; |
| 1041 | int cancelled; | ||
| 1042 | }; | 1045 | }; |
| 1043 | 1046 | ||
| 1044 | static bool nfs4_clear_cap_atomic_open_v1(struct nfs_server *server, | 1047 | static bool nfs4_clear_cap_atomic_open_v1(struct nfs_server *server, |
| @@ -1962,7 +1965,7 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) · 917 unmodified lines | |||
| 1962 | nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid); | 1965 | nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid); |
| 1963 | nfs_confirm_seqid(&data->owner->so_seqid, 0); | 1966 | nfs_confirm_seqid(&data->owner->so_seqid, 0); |
| 1964 | renew_lease(data->o_res.server, data->timestamp); | 1967 | renew_lease(data->o_res.server, data->timestamp); |
| 1965 | data->rpc_done = 1; | 1968 | data->rpc_done = true; |
| 1966 | } | 1969 | } |
| 1967 | } | 1970 | } |
| 1968 | 1971 | ||
| @@ -1972,7 +1975,7 @@ static void nfs4_open_confirm_release(void *calldata) · 3 unmodified lines | |||
| 1972 | struct nfs4_state *state = NULL; | 1975 | struct nfs4_state *state = NULL; |
| 1973 | 1976 | ||
| 1974 | /* If this request hasn't been cancelled, do nothing */ | 1977 | /* If this request hasn't been cancelled, do nothing */ |
| 1975 | if (data->cancelled == 0) | 1978 | if (!data->cancelled) |
| 1976 | goto out_free; | 1979 | goto out_free; |
| 1977 | /* In case of error, no cleanup! */ | 1980 | /* In case of error, no cleanup! */ |
| 1978 | if (!data->rpc_done) | 1981 | if (!data->rpc_done) |
| @@ -2015,7 +2018,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) · 36 unmodified lines | |||
| 2015 | 2018 | ||
| 2016 | nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1); | 2019 | nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1); |
| 2017 | kref_get(&data->kref); | 2020 | kref_get(&data->kref); |
| 2018 | data->rpc_done = 0; | 2021 | data->rpc_done = false; |
| 2019 | data->rpc_status = 0; | 2022 | data->rpc_status = 0; |
| 2020 | data->timestamp = jiffies; | 2023 | data->timestamp = jiffies; |
| 2021 | if (data->is_recover) | 2024 | if (data->is_recover) |
| @@ -2025,7 +2028,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) · 3 unmodified lines | |||
| 2025 | return PTR_ERR(task); | 2028 | return PTR_ERR(task); |
| 2026 | status = rpc_wait_for_completion_task(task); | 2029 | status = rpc_wait_for_completion_task(task); |
| 2027 | if (status != 0) { | 2030 | if (status != 0) { |
| 2028 | data->cancelled = 1; | 2031 | data->cancelled = true; |
| 2029 | smp_wmb(); | 2032 | smp_wmb(); |
| 2030 | } else | 2033 | } else |
| 2031 | status = data->rpc_status; | 2034 | status = data->rpc_status; |
| @@ -2124,7 +2127,7 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata) · 92 unmodified lines | |||
| 2124 | if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)) | 2127 | if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)) |
| 2125 | nfs_confirm_seqid(&data->owner->so_seqid, 0); | 2128 | nfs_confirm_seqid(&data->owner->so_seqid, 0); |
| 2126 | } | 2129 | } |
| 2127 | data->rpc_done = 1; | 2130 | data->rpc_done = true; |
| 2128 | } | 2131 | } |
| 2129 | 2132 | ||
| 2130 | static void nfs4_open_release(void *calldata) | 2133 | static void nfs4_open_release(void *calldata) |
| @@ -2133,7 +2136,7 @@ static void nfs4_open_release(void *calldata) · 2 unmodified lines | |||
| 2133 | struct nfs4_state *state = NULL; | 2136 | struct nfs4_state *state = NULL; |
| 2134 | 2137 | ||
| 2135 | /* If this request hasn't been cancelled, do nothing */ | 2138 | /* If this request hasn't been cancelled, do nothing */ |
| 2136 | if (data->cancelled == 0) | 2139 | if (!data->cancelled) |
| 2137 | goto out_free; | 2140 | goto out_free; |
| 2138 | /* In case of error, no cleanup! */ | 2141 | /* In case of error, no cleanup! */ |
| 2139 | if (data->rpc_status != 0 || !data->rpc_done) | 2142 | if (data->rpc_status != 0 || !data->rpc_done) |
| @@ -2179,20 +2182,20 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) · 39 unmodified lines | |||
| 2179 | 2182 | ||
| 2180 | nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1); | 2183 | nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1); |
| 2181 | kref_get(&data->kref); | 2184 | kref_get(&data->kref); |
| 2182 | data->rpc_done = 0; | 2185 | data->rpc_done = false; |
| 2183 | data->rpc_status = 0; | 2186 | data->rpc_status = 0; |
| 2184 | data->cancelled = 0; | 2187 | data->cancelled = false; |
| 2185 | data->is_recover = 0; | 2188 | data->is_recover = false; |
| 2186 | if (isrecover) { | 2189 | if (isrecover) { |
| 2187 | nfs4_set_sequence_privileged(&o_arg->seq_args); | 2190 | nfs4_set_sequence_privileged(&o_arg->seq_args); |
| 2188 | data->is_recover = 1; | 2191 | data->is_recover = true; |
| 2189 | } | 2192 | } |
| 2190 | task = rpc_run_task(&task_setup_data); | 2193 | task = rpc_run_task(&task_setup_data); |
| 2191 | if (IS_ERR(task)) | 2194 | if (IS_ERR(task)) |
| 2192 | return PTR_ERR(task); | 2195 | return PTR_ERR(task); |
| 2193 | status = rpc_wait_for_completion_task(task); | 2196 | status = rpc_wait_for_completion_task(task); |
| 2194 | if (status != 0) { | 2197 | if (status != 0) { |
| 2195 | data->cancelled = 1; | 2198 | data->cancelled = true; |
| 2196 | smp_wmb(); | 2199 | smp_wmb(); |
| 2197 | } else | 2200 | } else |
| 2198 | status = data->rpc_status; | 2201 | status = data->rpc_status; |
| @@ -2287,9 +2290,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) · 88 unmodified lines | |||
| 2287 | 2290 | ||
| 2288 | if (o_arg->open_flags & O_CREAT) { | 2291 | if (o_arg->open_flags & O_CREAT) { |
| 2289 | if (o_arg->open_flags & O_EXCL) | 2292 | if (o_arg->open_flags & O_EXCL) |
| 2290 | data->file_created = 1; | 2293 | data->file_created = true; |
| 2291 | else if (o_res->cinfo.before != o_res->cinfo.after) | 2294 | else if (o_res->cinfo.before != o_res->cinfo.after) |
| 2292 | data->file_created = 1; | 2295 | data->file_created = true; |
| 2293 | if (data->file_created || dir->i_version != o_res->cinfo.after) | 2296 | if (data->file_created || dir->i_version != o_res->cinfo.after) |
| 2294 | update_changeattr(dir, &o_res->cinfo, | 2297 | update_changeattr(dir, &o_res->cinfo, |
| 2295 | o_res->f_attr->time_start); | 2298 | o_res->f_attr->time_start); |
| @@ -3803,6 +3806,54 @@ nfs4_proc_lookup_mountpoint(struct inode *dir, const struct qstr *name, · 1507 unmodified lines | |||
| 3803 | return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client; | 3806 | return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client; |
| 3804 | } | 3807 | } |
| 3805 | 3808 | ||
| 3809 | static int _nfs4_proc_lookupp(struct inode *inode, | ||
| 3810 | struct nfs_fh *fhandle, struct nfs_fattr *fattr, | ||
| 3811 | struct nfs4_label *label) | ||
| 3812 | { | ||
| 3813 | struct rpc_clnt *clnt = NFS_CLIENT(inode); | ||
| 3814 | struct nfs_server *server = NFS_SERVER(inode); | ||
| 3815 | int status; | ||
| 3816 | struct nfs4_lookupp_arg args = { | ||
| 3817 | .bitmask = server->attr_bitmask, | ||
| 3818 | .fh = NFS_FH(inode), | ||
| 3819 | }; | ||
| 3820 | struct nfs4_lookupp_res res = { | ||
| 3821 | .server = server, | ||
| 3822 | .fattr = fattr, | ||
| 3823 | .label = label, | ||
| 3824 | .fh = fhandle, | ||
| 3825 | }; | ||
| 3826 | struct rpc_message msg = { | ||
| 3827 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUPP], | ||
| 3828 | .rpc_argp = &args, | ||
| 3829 | .rpc_resp = &res, | ||
| 3830 | }; | ||
| 3831 | |||
| 3832 | args.bitmask = nfs4_bitmask(server, label); | ||
| 3833 | |||
| 3834 | nfs_fattr_init(fattr); | ||
| 3835 | |||
| 3836 | dprintk("NFS call lookupp ino=0x%lx\n", inode->i_ino); | ||
| 3837 | status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, | ||
| 3838 | &res.seq_res, 0); | ||
| 3839 | dprintk("NFS reply lookupp: %d\n", status); | ||
| 3840 | return status; | ||
| 3841 | } | ||
| 3842 | |||
| 3843 | static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle, | ||
| 3844 | struct nfs_fattr *fattr, struct nfs4_label *label) | ||
| 3845 | { | ||
| 3846 | struct nfs4_exception exception = { }; | ||
| 3847 | int err; | ||
| 3848 | do { | ||
| 3849 | err = _nfs4_proc_lookupp(inode, fhandle, fattr, label); | ||
| 3850 | trace_nfs4_lookupp(inode, err); | ||
| 3851 | err = nfs4_handle_exception(NFS_SERVER(inode), err, | ||
| 3852 | &exception); | ||
| 3853 | } while (exception.retry); | ||
| 3854 | return err; | ||
| 3855 | } | ||
| 3856 | |||
| 3806 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) | 3857 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) |
| 3807 | { | 3858 | { |
| 3808 | struct nfs_server *server = NFS_SERVER(inode); | 3859 | struct nfs_server *server = NFS_SERVER(inode); |
| @@ -4273,7 +4324,7 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, · 464 unmodified lines | |||
| 4273 | } | 4324 | } |
| 4274 | 4325 | ||
| 4275 | static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | 4326 | static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, |
| 4276 | u64 cookie, struct page **pages, unsigned int count, int plus) | 4327 | u64 cookie, struct page **pages, unsigned int count, bool plus) |
| 4277 | { | 4328 | { |
| 4278 | struct inode *dir = d_inode(dentry); | 4329 | struct inode *dir = d_inode(dentry); |
| 4279 | struct nfs4_readdir_arg args = { | 4330 | struct nfs4_readdir_arg args = { |
| @@ -4311,7 +4362,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, · 31 unmodified lines | |||
| 4311 | } | 4362 | } |
| 4312 | 4363 | ||
| 4313 | static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | 4364 | static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, |
| 4314 | u64 cookie, struct page **pages, unsigned int count, int plus) | 4365 | u64 cookie, struct page **pages, unsigned int count, bool plus) |
| 4315 | { | 4366 | { |
| 4316 | struct nfs4_exception exception = { }; | 4367 | struct nfs4_exception exception = { }; |
| 4317 | int err; | 4368 | int err; |
| @@ -6135,7 +6186,7 @@ static void nfs4_lock_release(void *calldata) · 1817 unmodified lines | |||
| 6135 | 6186 | ||
| 6136 | dprintk("%s: begin!\n", __func__); | 6187 | dprintk("%s: begin!\n", __func__); |
| 6137 | nfs_free_seqid(data->arg.open_seqid); | 6188 | nfs_free_seqid(data->arg.open_seqid); |
| 6138 | if (data->cancelled != 0) { | 6189 | if (data->cancelled) { |
| 6139 | struct rpc_task *task; | 6190 | struct rpc_task *task; |
| 6140 | task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, | 6191 | task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, |
| 6141 | data->arg.lock_seqid); | 6192 | data->arg.lock_seqid); |
| @@ -6218,7 +6269,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f · 76 unmodified lines | |||
| 6218 | nfs4_handle_setlk_error(data->server, data->lsp, | 6269 | nfs4_handle_setlk_error(data->server, data->lsp, |
| 6219 | data->arg.new_lock_owner, ret); | 6270 | data->arg.new_lock_owner, ret); |
| 6220 | } else | 6271 | } else |
| 6221 | data->cancelled = 1; | 6272 | data->cancelled = true; |
| 6222 | rpc_put_task(task); | 6273 | rpc_put_task(task); |
| 6223 | dprintk("%s: done, ret = %d!\n", __func__, ret); | 6274 | dprintk("%s: done, ret = %d!\n", __func__, ret); |
| 6224 | trace_nfs4_set_lock(fl, state, &data->res.stateid, cmd, ret); | 6275 | trace_nfs4_set_lock(fl, state, &data->res.stateid, cmd, ret); |
| @@ -7376,12 +7427,11 @@ static void nfs4_exchange_id_done(struct rpc_task *task, void *data) · 1151 unmodified lines | |||
| 7376 | if (status == 0) { | 7427 | if (status == 0) { |
| 7377 | clp->cl_clientid = cdata->res.clientid; | 7428 | clp->cl_clientid = cdata->res.clientid; |
| 7378 | clp->cl_exchange_flags = cdata->res.flags; | 7429 | clp->cl_exchange_flags = cdata->res.flags; |
| 7430 | clp->cl_seqid = cdata->res.seqid; | ||
| 7379 | /* Client ID is not confirmed */ | 7431 | /* Client ID is not confirmed */ |
| 7380 | if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R)) { | 7432 | if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R)) |
| 7381 | clear_bit(NFS4_SESSION_ESTABLISHED, | 7433 | clear_bit(NFS4_SESSION_ESTABLISHED, |
| 7382 | &clp->cl_session->session_state); | 7434 | &clp->cl_session->session_state); |
| 7383 | clp->cl_seqid = cdata->res.seqid; | ||
| 7384 | } | ||
| 7385 | 7435 | ||
| 7386 | kfree(clp->cl_serverowner); | 7436 | kfree(clp->cl_serverowner); |
| 7387 | clp->cl_serverowner = cdata->res.server_owner; | 7437 | clp->cl_serverowner = cdata->res.server_owner; |
| @@ -9313,6 +9363,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { · 1925 unmodified lines | |||
| 9313 | .getattr = nfs4_proc_getattr, | 9363 | .getattr = nfs4_proc_getattr, |
| 9314 | .setattr = nfs4_proc_setattr, | 9364 | .setattr = nfs4_proc_setattr, |
| 9315 | .lookup = nfs4_proc_lookup, | 9365 | .lookup = nfs4_proc_lookup, |
| 9366 | .lookupp = nfs4_proc_lookupp, | ||
| 9316 | .access = nfs4_proc_access, | 9367 | .access = nfs4_proc_access, |
| 9317 | .readlink = nfs4_proc_readlink, | 9368 | .readlink = nfs4_proc_readlink, |
| 9318 | .create = nfs4_proc_create, | 9369 | .create = nfs4_proc_create, |
| @@ -352,11 +352,17 @@ int nfs41_discover_server_trunking(struct nfs_client *clp, · 351 unmodified lines | |||
| 352 | if (clp != *result) | 352 | if (clp != *result) |
| 353 | return 0; | 353 | return 0; |
| 354 | 354 | ||
| 355 | /* Purge state if the client id was established in a prior instance */ | 355 | /* |
| 356 | if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R) | 356 | * Purge state if the client id was established in a prior |
| 357 | set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); | 357 | * instance and the client id could not have arrived on the |
| 358 | else | 358 | * server via Transparent State Migration. |
| 359 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | 359 | */ |
| 360 | if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R) { | ||
| 361 | if (!test_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags)) | ||
| 362 | set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); | ||
| 363 | else | ||
| 364 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
| 365 | } | ||
| 360 | nfs4_schedule_state_manager(clp); | 366 | nfs4_schedule_state_manager(clp); |
| 361 | status = nfs_wait_client_init_complete(clp); | 367 | status = nfs_wait_client_init_complete(clp); |
| 362 | if (status < 0) | 368 | if (status < 0) |
| @@ -891,6 +891,35 @@ DEFINE_NFS4_LOOKUP_EVENT(nfs4_remove); · 890 unmodified lines | |||
| 891 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_get_fs_locations); | 891 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_get_fs_locations); |
| 892 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_secinfo); | 892 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_secinfo); |
| 893 | 893 | ||
| 894 | TRACE_EVENT(nfs4_lookupp, | ||
| 895 | TP_PROTO( | ||
| 896 | const struct inode *inode, | ||
| 897 | int error | ||
| 898 | ), | ||
| 899 | |||
| 900 | TP_ARGS(inode, error), | ||
| 901 | |||
| 902 | TP_STRUCT__entry( | ||
| 903 | __field(dev_t, dev) | ||
| 904 | __field(u64, ino) | ||
| 905 | __field(int, error) | ||
| 906 | ), | ||
| 907 | |||
| 908 | TP_fast_assign( | ||
| 909 | __entry->dev = inode->i_sb->s_dev; | ||
| 910 | __entry->ino = NFS_FILEID(inode); | ||
| 911 | __entry->error = error; | ||
| 912 | ), | ||
| 913 | |||
| 914 | TP_printk( | ||
| 915 | "error=%d (%s) inode=%02x:%02x:%llu", | ||
| 916 | __entry->error, | ||
| 917 | show_nfsv4_errors(__entry->error), | ||
| 918 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
| 919 | (unsigned long long)__entry->ino | ||
| 920 | ) | ||
| 921 | ); | ||
| 922 | |||
| 894 | TRACE_EVENT(nfs4_rename, | 923 | TRACE_EVENT(nfs4_rename, |
| 895 | TP_PROTO( | 924 | TP_PROTO( |
| 896 | const struct inode *olddir, | 925 | const struct inode *olddir, |
| @@ -159,6 +159,8 @@ static int nfs4_stat_to_errno(int); · 158 unmodified lines | |||
| 159 | (op_decode_hdr_maxsz) | 159 | (op_decode_hdr_maxsz) |
| 160 | #define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) | 160 | #define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) |
| 161 | #define decode_lookup_maxsz (op_decode_hdr_maxsz) | 161 | #define decode_lookup_maxsz (op_decode_hdr_maxsz) |
| 162 | #define encode_lookupp_maxsz (op_encode_hdr_maxsz) | ||
| 163 | #define decode_lookupp_maxsz (op_decode_hdr_maxsz) | ||
| 162 | #define encode_share_access_maxsz \ | 164 | #define encode_share_access_maxsz \ |
| 163 | (2) | 165 | (2) |
| 164 | #define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) | 166 | #define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) |
| @@ -618,6 +620,18 @@ static int nfs4_stat_to_errno(int); · 453 unmodified lines | |||
| 618 | decode_lookup_maxsz + \ | 620 | decode_lookup_maxsz + \ |
| 619 | decode_getattr_maxsz + \ | 621 | decode_getattr_maxsz + \ |
| 620 | decode_getfh_maxsz) | 622 | decode_getfh_maxsz) |
| 623 | #define NFS4_enc_lookupp_sz (compound_encode_hdr_maxsz + \ | ||
| 624 | encode_sequence_maxsz + \ | ||
| 625 | encode_putfh_maxsz + \ | ||
| 626 | encode_lookupp_maxsz + \ | ||
| 627 | encode_getattr_maxsz + \ | ||
| 628 | encode_getfh_maxsz) | ||
| 629 | #define NFS4_dec_lookupp_sz (compound_decode_hdr_maxsz + \ | ||
| 630 | decode_sequence_maxsz + \ | ||
| 631 | decode_putfh_maxsz + \ | ||
| 632 | decode_lookupp_maxsz + \ | ||
| 633 | decode_getattr_maxsz + \ | ||
| 634 | decode_getfh_maxsz) | ||
| 621 | #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ | 635 | #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ |
| 622 | encode_sequence_maxsz + \ | 636 | encode_sequence_maxsz + \ |
| 623 | encode_putrootfh_maxsz + \ | 637 | encode_putrootfh_maxsz + \ |
| @@ -1368,6 +1382,11 @@ static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struc · 744 unmodified lines | |||
| 1368 | encode_string(xdr, name->len, name->name); | 1382 | encode_string(xdr, name->len, name->name); |
| 1369 | } | 1383 | } |
| 1370 | 1384 | ||
| 1385 | static void encode_lookupp(struct xdr_stream *xdr, struct compound_hdr *hdr) | ||
| 1386 | { | ||
| 1387 | encode_op_hdr(xdr, OP_LOOKUPP, decode_lookupp_maxsz, hdr); | ||
| 1388 | } | ||
| 1389 | |||
| 1371 | static void encode_share_access(struct xdr_stream *xdr, u32 share_access) | 1390 | static void encode_share_access(struct xdr_stream *xdr, u32 share_access) |
| 1372 | { | 1391 | { |
| 1373 | __be32 *p; | 1392 | __be32 *p; |
| @@ -2122,6 +2141,26 @@ static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr, · 748 unmodified lines | |||
| 2122 | encode_nops(&hdr); | 2141 | encode_nops(&hdr); |
| 2123 | } | 2142 | } |
| 2124 | 2143 | ||
| 2144 | /* | ||
| 2145 | * Encode LOOKUPP request | ||
| 2146 | */ | ||
| 2147 | static void nfs4_xdr_enc_lookupp(struct rpc_rqst *req, struct xdr_stream *xdr, | ||
| 2148 | const void *data) | ||
| 2149 | { | ||
| 2150 | const struct nfs4_lookupp_arg *args = data; | ||
| 2151 | struct compound_hdr hdr = { | ||
| 2152 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
| 2153 | }; | ||
| 2154 | |||
| 2155 | encode_compound_hdr(xdr, req, &hdr); | ||
| 2156 | encode_sequence(xdr, &args->seq_args, &hdr); | ||
| 2157 | encode_putfh(xdr, args->fh, &hdr); | ||
| 2158 | encode_lookupp(xdr, &hdr); | ||
| 2159 | encode_getfh(xdr, &hdr); | ||
| 2160 | encode_getfattr(xdr, args->bitmask, &hdr); | ||
| 2161 | encode_nops(&hdr); | ||
| 2162 | } | ||
| 2163 | |||
| 2125 | /* | 2164 | /* |
| 2126 | * Encode LOOKUP_ROOT request | 2165 | * Encode LOOKUP_ROOT request |
| 2127 | */ | 2166 | */ |
| @@ -5058,6 +5097,11 @@ static int decode_lookup(struct xdr_stream *xdr) · 2930 unmodified lines | |||
| 5058 | return decode_op_hdr(xdr, OP_LOOKUP); | 5097 | return decode_op_hdr(xdr, OP_LOOKUP); |
| 5059 | } | 5098 | } |
| 5060 | 5099 | ||
| 5100 | static int decode_lookupp(struct xdr_stream *xdr) | ||
| 5101 | { | ||
| 5102 | return decode_op_hdr(xdr, OP_LOOKUPP); | ||
| 5103 | } | ||
| 5104 | |||
| 5061 | /* This is too sick! */ | 5105 | /* This is too sick! */ |
| 5062 | static int decode_space_limit(struct xdr_stream *xdr, | 5106 | static int decode_space_limit(struct xdr_stream *xdr, |
| 5063 | unsigned long *pagemod_limit) | 5107 | unsigned long *pagemod_limit) |
| @@ -6237,6 +6281,36 @@ out: · 1173 unmodified lines | |||
| 6237 | return status; | 6281 | return status; |
| 6238 | } | 6282 | } |
| 6239 | 6283 | ||
| 6284 | /* | ||
| 6285 | * Decode LOOKUPP response | ||
| 6286 | */ | ||
| 6287 | static int nfs4_xdr_dec_lookupp(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | ||
| 6288 | void *data) | ||
| 6289 | { | ||
| 6290 | struct nfs4_lookupp_res *res = data; | ||
| 6291 | struct compound_hdr hdr; | ||
| 6292 | int status; | ||
| 6293 | |||
| 6294 | status = decode_compound_hdr(xdr, &hdr); | ||
| 6295 | if (status) | ||
| 6296 | goto out; | ||
| 6297 | status = decode_sequence(xdr, &res->seq_res, rqstp); | ||
| 6298 | if (status) | ||
| 6299 | goto out; | ||
| 6300 | status = decode_putfh(xdr); | ||
| 6301 | if (status) | ||
| 6302 | goto out; | ||
| 6303 | status = decode_lookupp(xdr); | ||
| 6304 | if (status) | ||
| 6305 | goto out; | ||
| 6306 | status = decode_getfh(xdr, res->fh); | ||
| 6307 | if (status) | ||
| 6308 | goto out; | ||
| 6309 | status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); | ||
| 6310 | out: | ||
| 6311 | return status; | ||
| 6312 | } | ||
| 6313 | |||
| 6240 | /* | 6314 | /* |
| 6241 | * Decode LOOKUP_ROOT response | 6315 | * Decode LOOKUP_ROOT response |
| 6242 | */ | 6316 | */ |
| @@ -7447,7 +7521,7 @@ out: · 1204 unmodified lines | |||
| 7447 | * on a directory already in our cache. | 7521 | * on a directory already in our cache. |
| 7448 | */ | 7522 | */ |
| 7449 | int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | 7523 | int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, |
| 7450 | int plus) | 7524 | bool plus) |
| 7451 | { | 7525 | { |
| 7452 | unsigned int savep; | 7526 | unsigned int savep; |
| 7453 | uint32_t bitmap[3] = {0}; | 7527 | uint32_t bitmap[3] = {0}; |
| @@ -7614,6 +7688,7 @@ const struct rpc_procinfo nfs4_procedures[] = { · 160 unmodified lines | |||
| 7614 | PROC(ACCESS, enc_access, dec_access), | 7688 | PROC(ACCESS, enc_access, dec_access), |
| 7615 | PROC(GETATTR, enc_getattr, dec_getattr), | 7689 | PROC(GETATTR, enc_getattr, dec_getattr), |
| 7616 | PROC(LOOKUP, enc_lookup, dec_lookup), | 7690 | PROC(LOOKUP, enc_lookup, dec_lookup), |
| 7691 | PROC(LOOKUPP, enc_lookupp, dec_lookupp), | ||
| 7617 | PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), | 7692 | PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), |
| 7618 | PROC(REMOVE, enc_remove, dec_remove), | 7693 | PROC(REMOVE, enc_remove, dec_remove), |
| 7619 | PROC(RENAME, enc_rename, dec_rename), | 7694 | PROC(RENAME, enc_rename, dec_rename), |
| @@ -50,8 +50,8 @@ void nfs_pgheader_init(struct nfs_pageio_descriptor *desc, · 49 unmodified lines | |||
| 50 | hdr->cred = hdr->req->wb_context->cred; | 50 | hdr->cred = hdr->req->wb_context->cred; |
| 51 | hdr->io_start = req_offset(hdr->req); | 51 | hdr->io_start = req_offset(hdr->req); |
| 52 | hdr->good_bytes = mirror->pg_count; | 52 | hdr->good_bytes = mirror->pg_count; |
| 53 | hdr->io_completion = desc->pg_io_completion; | ||
| 53 | hdr->dreq = desc->pg_dreq; | 54 | hdr->dreq = desc->pg_dreq; |
| 54 | hdr->layout_private = desc->pg_layout_private; | ||
| 55 | hdr->release = release; | 55 | hdr->release = release; |
| 56 | hdr->completion_ops = desc->pg_completion_ops; | 56 | hdr->completion_ops = desc->pg_completion_ops; |
| 57 | if (hdr->completion_ops->init_hdr) | 57 | if (hdr->completion_ops->init_hdr) |
| @@ -155,9 +155,12 @@ nfs_page_group_lock(struct nfs_page *req, bool nonblock) · 97 unmodified lines | |||
| 155 | if (!test_and_set_bit(PG_HEADLOCK, &head->wb_flags)) | 155 | if (!test_and_set_bit(PG_HEADLOCK, &head->wb_flags)) |
| 156 | return 0; | 156 | return 0; |
| 157 | 157 | ||
| 158 | if (!nonblock) | 158 | if (!nonblock) { |
| 159 | set_bit(PG_CONTENDED1, &head->wb_flags); | ||
| 160 | smp_mb__after_atomic(); | ||
| 159 | return wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK, | 161 | return wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK, |
| 160 | TASK_UNINTERRUPTIBLE); | 162 | TASK_UNINTERRUPTIBLE); |
| 163 | } | ||
| 161 | 164 | ||
| 162 | return -EAGAIN; | 165 | return -EAGAIN; |
| 163 | } | 166 | } |
| @@ -175,6 +178,10 @@ nfs_page_group_lock_wait(struct nfs_page *req) · 11 unmodified lines | |||
| 175 | 178 | ||
| 176 | WARN_ON_ONCE(head != head->wb_head); | 179 | WARN_ON_ONCE(head != head->wb_head); |
| 177 | 180 | ||
| 181 | if (!test_bit(PG_HEADLOCK, &head->wb_flags)) | ||
| 182 | return; | ||
| 183 | set_bit(PG_CONTENDED1, &head->wb_flags); | ||
| 184 | smp_mb__after_atomic(); | ||
| 178 | wait_on_bit(&head->wb_flags, PG_HEADLOCK, | 185 | wait_on_bit(&head->wb_flags, PG_HEADLOCK, |
| 179 | TASK_UNINTERRUPTIBLE); | 186 | TASK_UNINTERRUPTIBLE); |
| 180 | } | 187 | } |
| @@ -193,6 +200,8 @@ nfs_page_group_unlock(struct nfs_page *req) · 12 unmodified lines | |||
| 193 | smp_mb__before_atomic(); | 200 | smp_mb__before_atomic(); |
| 194 | clear_bit(PG_HEADLOCK, &head->wb_flags); | 201 | clear_bit(PG_HEADLOCK, &head->wb_flags); |
| 195 | smp_mb__after_atomic(); | 202 | smp_mb__after_atomic(); |
| 203 | if (!test_bit(PG_CONTENDED1, &head->wb_flags)) | ||
| 204 | return; | ||
| 196 | wake_up_bit(&head->wb_flags, PG_HEADLOCK); | 205 | wake_up_bit(&head->wb_flags, PG_HEADLOCK); |
| 197 | } | 206 | } |
| 198 | 207 | ||
| @@ -383,6 +392,8 @@ void nfs_unlock_request(struct nfs_page *req) · 184 unmodified lines | |||
| 383 | smp_mb__before_atomic(); | 392 | smp_mb__before_atomic(); |
| 384 | clear_bit(PG_BUSY, &req->wb_flags); | 393 | clear_bit(PG_BUSY, &req->wb_flags); |
| 385 | smp_mb__after_atomic(); | 394 | smp_mb__after_atomic(); |
| 395 | if (!test_bit(PG_CONTENDED2, &req->wb_flags)) | ||
| 396 | return; | ||
| 386 | wake_up_bit(&req->wb_flags, PG_BUSY); | 397 | wake_up_bit(&req->wb_flags, PG_BUSY); |
| 387 | } | 398 | } |
| 388 | 399 | ||
| @@ -465,6 +476,10 @@ void nfs_release_request(struct nfs_page *req) · 76 unmodified lines | |||
| 465 | int | 476 | int |
| 466 | nfs_wait_on_request(struct nfs_page *req) | 477 | nfs_wait_on_request(struct nfs_page *req) |
| 467 | { | 478 | { |
| 479 | if (!test_bit(PG_BUSY, &req->wb_flags)) | ||
| 480 | return 0; | ||
| 481 | set_bit(PG_CONTENDED2, &req->wb_flags); | ||
| 482 | smp_mb__after_atomic(); | ||
| 468 | return wait_on_bit_io(&req->wb_flags, PG_BUSY, | 483 | return wait_on_bit_io(&req->wb_flags, PG_BUSY, |
| 469 | TASK_UNINTERRUPTIBLE); | 484 | TASK_UNINTERRUPTIBLE); |
| 470 | } | 485 | } |
| @@ -710,8 +725,8 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, · 239 unmodified lines | |||
| 710 | desc->pg_ioflags = io_flags; | 725 | desc->pg_ioflags = io_flags; |
| 711 | desc->pg_error = 0; | 726 | desc->pg_error = 0; |
| 712 | desc->pg_lseg = NULL; | 727 | desc->pg_lseg = NULL; |
| 728 | desc->pg_io_completion = NULL; | ||
| 713 | desc->pg_dreq = NULL; | 729 | desc->pg_dreq = NULL; |
| 714 | desc->pg_layout_private = NULL; | ||
| 715 | desc->pg_bsize = bsize; | 730 | desc->pg_bsize = bsize; |
| 716 | 731 | ||
| 717 | desc->pg_mirror_count = 1; | 732 | desc->pg_mirror_count = 1; |
| @@ -779,6 +794,7 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, · 61 unmodified lines | |||
| 779 | gfp_t gfp_flags = GFP_KERNEL; | 794 | gfp_t gfp_flags = GFP_KERNEL; |
| 780 | 795 | ||
| 781 | pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count); | 796 | pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count); |
| 797 | pg_array->npages = pagecount; | ||
| 782 | 798 | ||
| 783 | if (pagecount <= ARRAY_SIZE(pg_array->page_array)) | 799 | if (pagecount <= ARRAY_SIZE(pg_array->page_array)) |
| 784 | pg_array->pagevec = pg_array->page_array; | 800 | pg_array->pagevec = pg_array->page_array; |
| @@ -1233,6 +1249,7 @@ int nfs_pageio_resend(struct nfs_pageio_descriptor *desc, · 448 unmodified lines | |||
| 1233 | { | 1249 | { |
| 1234 | LIST_HEAD(failed); | 1250 | LIST_HEAD(failed); |
| 1235 | 1251 | ||
| 1252 | desc->pg_io_completion = hdr->io_completion; | ||
| 1236 | desc->pg_dreq = hdr->dreq; | 1253 | desc->pg_dreq = hdr->dreq; |
| 1237 | while (!list_empty(&hdr->pages)) { | 1254 | while (!list_empty(&hdr->pages)) { |
| 1238 | struct nfs_page *req = nfs_list_entry(hdr->pages.next); | 1255 | struct nfs_page *req = nfs_list_entry(hdr->pages.next); |
| @@ -485,7 +485,7 @@ nfs_proc_rmdir(struct inode *dir, const struct qstr *name) · 484 unmodified lines | |||
| 485 | */ | 485 | */ |
| 486 | static int | 486 | static int |
| 487 | nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | 487 | nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, |
| 488 | u64 cookie, struct page **pages, unsigned int count, int plus) | 488 | u64 cookie, struct page **pages, unsigned int count, bool plus) |
| 489 | { | 489 | { |
| 490 | struct inode *dir = d_inode(dentry); | 490 | struct inode *dir = d_inode(dentry); |
| 491 | struct nfs_readdirargs arg = { | 491 | struct nfs_readdirargs arg = { |
| @@ -879,7 +879,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root) · 878 unmodified lines | |||
| 879 | if (nfss->options & NFS_OPTION_FSCACHE) { | 879 | if (nfss->options & NFS_OPTION_FSCACHE) { |
| 880 | seq_printf(m, "\n\tfsc:\t"); | 880 | seq_printf(m, "\n\tfsc:\t"); |
| 881 | for (i = 0; i < __NFSIOS_FSCACHEMAX; i++) | 881 | for (i = 0; i < __NFSIOS_FSCACHEMAX; i++) |
| 882 | seq_printf(m, "%Lu ", totals.bytes[i]); | 882 | seq_printf(m, "%Lu ", totals.fscache[i]); |
| 883 | } | 883 | } |
| 884 | #endif | 884 | #endif |
| 885 | seq_printf(m, "\n"); | 885 | seq_printf(m, "\n"); |
| @@ -2339,6 +2339,7 @@ void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info) · 1453 unmodified lines | |||
| 2339 | */ | 2339 | */ |
| 2340 | sb->s_flags |= MS_POSIXACL; | 2340 | sb->s_flags |= MS_POSIXACL; |
| 2341 | sb->s_time_gran = 1; | 2341 | sb->s_time_gran = 1; |
| 2342 | sb->s_export_op = &nfs_export_ops; | ||
| 2342 | } | 2343 | } |
| 2343 | 2344 | ||
| 2344 | nfs_initialise_sb(sb); | 2345 | nfs_initialise_sb(sb); |
| @@ -2360,6 +2361,7 @@ static void nfs_clone_super(struct super_block *sb, · 15 unmodified lines | |||
| 2360 | sb->s_xattr = old_sb->s_xattr; | 2361 | sb->s_xattr = old_sb->s_xattr; |
| 2361 | sb->s_op = old_sb->s_op; | 2362 | sb->s_op = old_sb->s_op; |
| 2362 | sb->s_time_gran = 1; | 2363 | sb->s_time_gran = 1; |
| 2364 | sb->s_export_op = old_sb->s_export_op; | ||
| 2363 | 2365 | ||
| 2364 | if (server->nfs_client->rpc_ops->version != 2) { | 2366 | if (server->nfs_client->rpc_ops->version != 2) { |
| 2365 | /* The VFS shouldn't apply the umask to mode bits. We will do | 2367 | /* The VFS shouldn't apply the umask to mode bits. We will do |
| @@ -288,6 +288,19 @@ static void nfs_async_rename_release(void *calldata) · 287 unmodified lines | |||
| 288 | if (d_really_is_positive(data->old_dentry)) | 288 | if (d_really_is_positive(data->old_dentry)) |
| 289 | nfs_mark_for_revalidate(d_inode(data->old_dentry)); | 289 | nfs_mark_for_revalidate(d_inode(data->old_dentry)); |
| 290 | 290 | ||
| 291 | /* The result of the rename is unknown. Play it safe by | ||
| 292 | * forcing a new lookup */ | ||
| 293 | if (data->cancelled) { | ||
| 294 | spin_lock(&data->old_dir->i_lock); | ||
| 295 | nfs_force_lookup_revalidate(data->old_dir); | ||
| 296 | spin_unlock(&data->old_dir->i_lock); | ||
| 297 | if (data->new_dir != data->old_dir) { | ||
| 298 | spin_lock(&data->new_dir->i_lock); | ||
| 299 | nfs_force_lookup_revalidate(data->new_dir); | ||
| 300 | spin_unlock(&data->new_dir->i_lock); | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 291 | dput(data->old_dentry); | 304 | dput(data->old_dentry); |
| 292 | dput(data->new_dentry); | 305 | dput(data->new_dentry); |
| 293 | iput(data->old_dir); | 306 | iput(data->old_dir); |
| @@ -40,6 +40,12 @@ · 39 unmodified lines | |||
| 40 | #define MIN_POOL_WRITE (32) | 40 | #define MIN_POOL_WRITE (32) |
| 41 | #define MIN_POOL_COMMIT (4) | 41 | #define MIN_POOL_COMMIT (4) |
| 42 | 42 | ||
| 43 | struct nfs_io_completion { | ||
| 44 | void (*complete)(void *data); | ||
| 45 | void *data; | ||
| 46 | struct kref refcount; | ||
| 47 | }; | ||
| 48 | |||
| 43 | /* | 49 | /* |
| 44 | * Local function declarations | 50 | * Local function declarations |
| 45 | */ | 51 | */ |
| @@ -108,6 +114,39 @@ static void nfs_writehdr_free(struct nfs_pgio_header *hdr) · 62 unmodified lines | |||
| 108 | mempool_free(hdr, nfs_wdata_mempool); | 114 | mempool_free(hdr, nfs_wdata_mempool); |
| 109 | } | 115 | } |
| 110 | 116 | ||
| 117 | static struct nfs_io_completion *nfs_io_completion_alloc(gfp_t gfp_flags) | ||
| 118 | { | ||
| 119 | return kmalloc(sizeof(struct nfs_io_completion), gfp_flags); | ||
| 120 | } | ||
| 121 | |||
| 122 | static void nfs_io_completion_init(struct nfs_io_completion *ioc, | ||
| 123 | void (*complete)(void *), void *data) | ||
| 124 | { | ||
| 125 | ioc->complete = complete; | ||
| 126 | ioc->data = data; | ||
| 127 | kref_init(&ioc->refcount); | ||
| 128 | } | ||
| 129 | |||
| 130 | static void nfs_io_completion_release(struct kref *kref) | ||
| 131 | { | ||
| 132 | struct nfs_io_completion *ioc = container_of(kref, | ||
| 133 | struct nfs_io_completion, refcount); | ||
| 134 | ioc->complete(ioc->data); | ||
| 135 | kfree(ioc); | ||
| 136 | } | ||
| 137 | |||
| 138 | static void nfs_io_completion_get(struct nfs_io_completion *ioc) | ||
| 139 | { | ||
| 140 | if (ioc != NULL) | ||
| 141 | kref_get(&ioc->refcount); | ||
| 142 | } | ||
| 143 | |||
| 144 | static void nfs_io_completion_put(struct nfs_io_completion *ioc) | ||
| 145 | { | ||
| 146 | if (ioc != NULL) | ||
| 147 | kref_put(&ioc->refcount, nfs_io_completion_release); | ||
| 148 | } | ||
| 149 | |||
| 111 | static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) | 150 | static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) |
| 112 | { | 151 | { |
| 113 | ctx->error = error; | 152 | ctx->error = error; |
| @@ -681,18 +720,29 @@ static int nfs_writepages_callback(struct page *page, struct writeback_control * · 567 unmodified lines | |||
| 681 | return ret; | 720 | return ret; |
| 682 | } | 721 | } |
| 683 | 722 | ||
| 723 | static void nfs_io_completion_commit(void *inode) | ||
| 724 | { | ||
| 725 | nfs_commit_inode(inode, 0); | ||
| 726 | } | ||
| 727 | |||
| 684 | int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | 728 | int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) |
| 685 | { | 729 | { |
| 686 | struct inode *inode = mapping->host; | 730 | struct inode *inode = mapping->host; |
| 687 | struct nfs_pageio_descriptor pgio; | 731 | struct nfs_pageio_descriptor pgio; |
| 732 | struct nfs_io_completion *ioc = nfs_io_completion_alloc(GFP_NOFS); | ||
| 688 | int err; | 733 | int err; |
| 689 | 734 | ||
| 690 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); | 735 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); |
| 691 | 736 | ||
| 737 | if (ioc) | ||
| 738 | nfs_io_completion_init(ioc, nfs_io_completion_commit, inode); | ||
| 739 | |||
| 692 | nfs_pageio_init_write(&pgio, inode, wb_priority(wbc), false, | 740 | nfs_pageio_init_write(&pgio, inode, wb_priority(wbc), false, |
| 693 | &nfs_async_write_completion_ops); | 741 | &nfs_async_write_completion_ops); |
| 742 | pgio.pg_io_completion = ioc; | ||
| 694 | err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); | 743 | err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); |
| 695 | nfs_pageio_complete(&pgio); | 744 | nfs_pageio_complete(&pgio); |
| 745 | nfs_io_completion_put(ioc); | ||
| 696 | 746 | ||
| 697 | if (err < 0) | 747 | if (err < 0) |
| 698 | goto out_err; | 748 | goto out_err; |
| @@ -940,6 +990,11 @@ int nfs_write_need_commit(struct nfs_pgio_header *hdr) · 241 unmodified lines | |||
| 940 | return hdr->verf.committed != NFS_FILE_SYNC; | 990 | return hdr->verf.committed != NFS_FILE_SYNC; |
| 941 | } | 991 | } |
| 942 | 992 | ||
| 993 | static void nfs_async_write_init(struct nfs_pgio_header *hdr) | ||
| 994 | { | ||
| 995 | nfs_io_completion_get(hdr->io_completion); | ||
| 996 | } | ||
| 997 | |||
| 943 | static void nfs_write_completion(struct nfs_pgio_header *hdr) | 998 | static void nfs_write_completion(struct nfs_pgio_header *hdr) |
| 944 | { | 999 | { |
| 945 | struct nfs_commit_info cinfo; | 1000 | struct nfs_commit_info cinfo; |
| @@ -973,6 +1028,7 @@ next: · 27 unmodified lines | |||
| 973 | nfs_release_request(req); | 1028 | nfs_release_request(req); |
| 974 | } | 1029 | } |
| 975 | out: | 1030 | out: |
| 1031 | nfs_io_completion_put(hdr->io_completion); | ||
| 976 | hdr->release(hdr); | 1032 | hdr->release(hdr); |
| 977 | } | 1033 | } |
| 978 | 1034 | ||
| @@ -1378,6 +1434,7 @@ static void nfs_async_write_reschedule_io(struct nfs_pgio_header *hdr) · 399 unmodified lines | |||
| 1378 | } | 1434 | } |
| 1379 | 1435 | ||
| 1380 | static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = { | 1436 | static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = { |
| 1437 | .init_hdr = nfs_async_write_init, | ||
| 1381 | .error_cleanup = nfs_async_write_error, | 1438 | .error_cleanup = nfs_async_write_error, |
| 1382 | .completion = nfs_write_completion, | 1439 | .completion = nfs_write_completion, |
| 1383 | .reschedule_io = nfs_async_write_reschedule_io, | 1440 | .reschedule_io = nfs_async_write_reschedule_io, |
| @@ -1884,7 +1941,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) · 500 unmodified lines | |||
| 1884 | /* Don't commit yet if this is a non-blocking flush and there | 1941 | /* Don't commit yet if this is a non-blocking flush and there |
| 1885 | * are a lot of outstanding writes for this mapping. | 1942 | * are a lot of outstanding writes for this mapping. |
| 1886 | */ | 1943 | */ |
| 1887 | if (nfsi->commit_info.ncommit <= (nfsi->nrequests >> 1)) | 1944 | if (mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK)) |
| 1888 | goto out_mark_dirty; | 1945 | goto out_mark_dirty; |
| 1889 | 1946 | ||
| 1890 | /* don't wait for the COMMIT response */ | 1947 | /* don't wait for the COMMIT response */ |
| @@ -479,6 +479,7 @@ enum { · 478 unmodified lines | |||
| 479 | NFSPROC4_CLNT_ACCESS, | 479 | NFSPROC4_CLNT_ACCESS, |
| 480 | NFSPROC4_CLNT_GETATTR, | 480 | NFSPROC4_CLNT_GETATTR, |
| 481 | NFSPROC4_CLNT_LOOKUP, | 481 | NFSPROC4_CLNT_LOOKUP, |
| 482 | NFSPROC4_CLNT_LOOKUPP, | ||
| 482 | NFSPROC4_CLNT_LOOKUP_ROOT, | 483 | NFSPROC4_CLNT_LOOKUP_ROOT, |
| 483 | NFSPROC4_CLNT_REMOVE, | 484 | NFSPROC4_CLNT_REMOVE, |
| 484 | NFSPROC4_CLNT_RENAME, | 485 | NFSPROC4_CLNT_RENAME, |
| @@ -332,6 +332,7 @@ extern void nfs_zap_caches(struct inode *); · 331 unmodified lines | |||
| 332 | extern void nfs_invalidate_atime(struct inode *); | 332 | extern void nfs_invalidate_atime(struct inode *); |
| 333 | extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, | 333 | extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, |
| 334 | struct nfs_fattr *, struct nfs4_label *); | 334 | struct nfs_fattr *, struct nfs4_label *); |
| 335 | struct inode *nfs_ilookup(struct super_block *sb, struct nfs_fattr *, struct nfs_fh *); | ||
| 335 | extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); | 336 | extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); |
| 336 | extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); | 337 | extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); |
| 337 | extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); | 338 | extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); |
| @@ -42,6 +42,7 @@ struct nfs_client { · 41 unmodified lines | |||
| 42 | #define NFS_CS_MIGRATION 2 /* - transparent state migr */ | 42 | #define NFS_CS_MIGRATION 2 /* - transparent state migr */ |
| 43 | #define NFS_CS_INFINITE_SLOTS 3 /* - don't limit TCP slots */ | 43 | #define NFS_CS_INFINITE_SLOTS 3 /* - don't limit TCP slots */ |
| 44 | #define NFS_CS_NO_RETRANS_TIMEOUT 4 /* - Disable retransmit timeouts */ | 44 | #define NFS_CS_NO_RETRANS_TIMEOUT 4 /* - Disable retransmit timeouts */ |
| 45 | #define NFS_CS_TSM_POSSIBLE 5 /* - Maybe state migration */ | ||
| 45 | struct sockaddr_storage cl_addr; /* server identifier */ | 46 | struct sockaddr_storage cl_addr; /* server identifier */ |
| 46 | size_t cl_addrlen; | 47 | size_t cl_addrlen; |
| 47 | char * cl_hostname; /* hostname of server */ | 48 | char * cl_hostname; /* hostname of server */ |
| @@ -210,6 +211,7 @@ struct nfs_server { · 162 unmodified lines | |||
| 210 | unsigned long mig_status; | 211 | unsigned long mig_status; |
| 211 | #define NFS_MIG_IN_TRANSITION (1) | 212 | #define NFS_MIG_IN_TRANSITION (1) |
| 212 | #define NFS_MIG_FAILED (2) | 213 | #define NFS_MIG_FAILED (2) |
| 214 | #define NFS_MIG_TSM_POSSIBLE (3) | ||
| 213 | 215 | ||
| 214 | void (*destroy)(struct nfs_server *); | 216 | void (*destroy)(struct nfs_server *); |
| 215 | 217 | ||
| @@ -33,6 +33,8 @@ enum { · 32 unmodified lines | |||
| 33 | PG_UPTODATE, /* page group sync bit in read path */ | 33 | PG_UPTODATE, /* page group sync bit in read path */ |
| 34 | PG_WB_END, /* page group sync bit in write path */ | 34 | PG_WB_END, /* page group sync bit in write path */ |
| 35 | PG_REMOVE, /* page group sync bit in write path */ | 35 | PG_REMOVE, /* page group sync bit in write path */ |
| 36 | PG_CONTENDED1, /* Is someone waiting for a lock? */ | ||
| 37 | PG_CONTENDED2, /* Is someone waiting for a lock? */ | ||
| 36 | }; | 38 | }; |
| 37 | 39 | ||
| 38 | struct nfs_inode; | 40 | struct nfs_inode; |
| @@ -93,8 +95,8 @@ struct nfs_pageio_descriptor { · 54 unmodified lines | |||
| 93 | const struct rpc_call_ops *pg_rpc_callops; | 95 | const struct rpc_call_ops *pg_rpc_callops; |
| 94 | const struct nfs_pgio_completion_ops *pg_completion_ops; | 96 | const struct nfs_pgio_completion_ops *pg_completion_ops; |
| 95 | struct pnfs_layout_segment *pg_lseg; | 97 | struct pnfs_layout_segment *pg_lseg; |
| 98 | struct nfs_io_completion *pg_io_completion; | ||
| 96 | struct nfs_direct_req *pg_dreq; | 99 | struct nfs_direct_req *pg_dreq; |
| 97 | void *pg_layout_private; | ||
| 98 | unsigned int pg_bsize; /* default bsize for mirrors */ | 100 | unsigned int pg_bsize; /* default bsize for mirrors */ |
| 99 | 101 | ||
| 100 | u32 pg_mirror_count; | 102 | u32 pg_mirror_count; |
| @@ -878,7 +878,7 @@ struct nfs3_readdirargs { · 877 unmodified lines | |||
| 878 | struct nfs_fh * fh; | 878 | struct nfs_fh * fh; |
| 879 | __u64 cookie; | 879 | __u64 cookie; |
| 880 | __be32 verf[2]; | 880 | __be32 verf[2]; |
| 881 | int plus; | 881 | bool plus; |
| 882 | unsigned int count; | 882 | unsigned int count; |
| 883 | struct page ** pages; | 883 | struct page ** pages; |
| 884 | }; | 884 | }; |
| @@ -909,7 +909,7 @@ struct nfs3_linkres { · 24 unmodified lines | |||
| 909 | struct nfs3_readdirres { | 909 | struct nfs3_readdirres { |
| 910 | struct nfs_fattr * dir_attr; | 910 | struct nfs_fattr * dir_attr; |
| 911 | __be32 * verf; | 911 | __be32 * verf; |
| 912 | int plus; | 912 | bool plus; |
| 913 | }; | 913 | }; |
| 914 | 914 | ||
| 915 | struct nfs3_getaclres { | 915 | struct nfs3_getaclres { |
| @@ -1012,7 +1012,6 @@ struct nfs4_link_res { · 96 unmodified lines | |||
| 1012 | struct nfs_fattr * dir_attr; | 1012 | struct nfs_fattr * dir_attr; |
| 1013 | }; | 1013 | }; |
| 1014 | 1014 | ||
| 1015 | |||
| 1016 | struct nfs4_lookup_arg { | 1015 | struct nfs4_lookup_arg { |
| 1017 | struct nfs4_sequence_args seq_args; | 1016 | struct nfs4_sequence_args seq_args; |
| 1018 | const struct nfs_fh * dir_fh; | 1017 | const struct nfs_fh * dir_fh; |
| @@ -1028,6 +1027,20 @@ struct nfs4_lookup_res { · 9 unmodified lines | |||
| 1028 | struct nfs4_label *label; | 1027 | struct nfs4_label *label; |
| 1029 | }; | 1028 | }; |
| 1030 | 1029 | ||
| 1030 | struct nfs4_lookupp_arg { | ||
| 1031 | struct nfs4_sequence_args seq_args; | ||
| 1032 | const struct nfs_fh *fh; | ||
| 1033 | const u32 *bitmask; | ||
| 1034 | }; | ||
| 1035 | |||
| 1036 | struct nfs4_lookupp_res { | ||
| 1037 | struct nfs4_sequence_res seq_res; | ||
| 1038 | const struct nfs_server *server; | ||
| 1039 | struct nfs_fattr *fattr; | ||
| 1040 | struct nfs_fh *fh; | ||
| 1041 | struct nfs4_label *label; | ||
| 1042 | }; | ||
| 1043 | |||
| 1031 | struct nfs4_lookup_root_arg { | 1044 | struct nfs4_lookup_root_arg { |
| 1032 | struct nfs4_sequence_args seq_args; | 1045 | struct nfs4_sequence_args seq_args; |
| 1033 | const u32 * bitmask; | 1046 | const u32 * bitmask; |
| @@ -1053,7 +1066,7 @@ struct nfs4_readdir_arg { · 19 unmodified lines | |||
| 1053 | struct page ** pages; /* zero-copy data */ | 1066 | struct page ** pages; /* zero-copy data */ |
| 1054 | unsigned int pgbase; /* zero-copy data */ | 1067 | unsigned int pgbase; /* zero-copy data */ |
| 1055 | const u32 * bitmask; | 1068 | const u32 * bitmask; |
| 1056 | int plus; | 1069 | bool plus; |
| 1057 | }; | 1070 | }; |
| 1058 | 1071 | ||
| 1059 | struct nfs4_readdir_res { | 1072 | struct nfs4_readdir_res { |
| @@ -1422,6 +1435,7 @@ enum { · 362 unmodified lines | |||
| 1422 | NFS_IOHDR_STAT, | 1435 | NFS_IOHDR_STAT, |
| 1423 | }; | 1436 | }; |
| 1424 | 1437 | ||
| 1438 | struct nfs_io_completion; | ||
| 1425 | struct nfs_pgio_header { | 1439 | struct nfs_pgio_header { |
| 1426 | struct inode *inode; | 1440 | struct inode *inode; |
| 1427 | struct rpc_cred *cred; | 1441 | struct rpc_cred *cred; |
| @@ -1435,8 +1449,8 @@ struct nfs_pgio_header { · 7 unmodified lines | |||
| 1435 | void (*release) (struct nfs_pgio_header *hdr); | 1449 | void (*release) (struct nfs_pgio_header *hdr); |
| 1436 | const struct nfs_pgio_completion_ops *completion_ops; | 1450 | const struct nfs_pgio_completion_ops *completion_ops; |
| 1437 | const struct nfs_rw_ops *rw_ops; | 1451 | const struct nfs_rw_ops *rw_ops; |
| 1452 | struct nfs_io_completion *io_completion; | ||
| 1438 | struct nfs_direct_req *dreq; | 1453 | struct nfs_direct_req *dreq; |
| 1439 | void *layout_private; | ||
| 1440 | spinlock_t lock; | 1454 | spinlock_t lock; |
| 1441 | /* fields protected by lock */ | 1455 | /* fields protected by lock */ |
| 1442 | int pnfs_error; | 1456 | int pnfs_error; |
| @@ -1533,6 +1547,7 @@ struct nfs_renamedata { · 90 unmodified lines | |||
| 1533 | struct nfs_fattr new_fattr; | 1547 | struct nfs_fattr new_fattr; |
| 1534 | void (*complete)(struct rpc_task *, struct nfs_renamedata *); | 1548 | void (*complete)(struct rpc_task *, struct nfs_renamedata *); |
| 1535 | long timeout; | 1549 | long timeout; |
| 1550 | bool cancelled; | ||
| 1536 | }; | 1551 | }; |
| 1537 | 1552 | ||
| 1538 | struct nfs_access_entry; | 1553 | struct nfs_access_entry; |
| @@ -1567,6 +1582,8 @@ struct nfs_rpc_ops { · 28 unmodified lines | |||
| 1567 | int (*lookup) (struct inode *, const struct qstr *, | 1582 | int (*lookup) (struct inode *, const struct qstr *, |
| 1568 | struct nfs_fh *, struct nfs_fattr *, | 1583 | struct nfs_fh *, struct nfs_fattr *, |
| 1569 | struct nfs4_label *); | 1584 | struct nfs4_label *); |
| 1585 | int (*lookupp) (struct inode *, struct nfs_fh *, | ||
| 1586 | struct nfs_fattr *, struct nfs4_label *); | ||
| 1570 | int (*access) (struct inode *, struct nfs_access_entry *); | 1587 | int (*access) (struct inode *, struct nfs_access_entry *); |
| 1571 | int (*readlink)(struct inode *, struct page *, unsigned int, | 1588 | int (*readlink)(struct inode *, struct page *, unsigned int, |
| 1572 | unsigned int); | 1589 | unsigned int); |
| @@ -1585,7 +1602,7 @@ struct nfs_rpc_ops { · 12 unmodified lines | |||
| 1585 | int (*mkdir) (struct inode *, struct dentry *, struct iattr *); | 1602 | int (*mkdir) (struct inode *, struct dentry *, struct iattr *); |
| 1586 | int (*rmdir) (struct inode *, const struct qstr *); | 1603 | int (*rmdir) (struct inode *, const struct qstr *); |
| 1587 | int (*readdir) (struct dentry *, struct rpc_cred *, | 1604 | int (*readdir) (struct dentry *, struct rpc_cred *, |
| 1588 | u64, struct page **, unsigned int, int); | 1605 | u64, struct page **, unsigned int, bool); |
| 1589 | int (*mknod) (struct inode *, struct dentry *, struct iattr *, | 1606 | int (*mknod) (struct inode *, struct dentry *, struct iattr *, |
| 1590 | dev_t); | 1607 | dev_t); |
| 1591 | int (*statfs) (struct nfs_server *, struct nfs_fh *, | 1608 | int (*statfs) (struct nfs_server *, struct nfs_fh *, |
| @@ -1595,7 +1612,7 @@ struct nfs_rpc_ops { · 3 unmodified lines | |||
| 1595 | int (*pathconf) (struct nfs_server *, struct nfs_fh *, | 1612 | int (*pathconf) (struct nfs_server *, struct nfs_fh *, |
| 1596 | struct nfs_pathconf *); | 1613 | struct nfs_pathconf *); |
| 1597 | int (*set_capabilities)(struct nfs_server *, struct nfs_fh *); | 1614 | int (*set_capabilities)(struct nfs_server *, struct nfs_fh *); |
| 1598 | int (*decode_dirent)(struct xdr_stream *, struct nfs_entry *, int); | 1615 | int (*decode_dirent)(struct xdr_stream *, struct nfs_entry *, bool); |
| 1599 | int (*pgio_rpc_prepare)(struct rpc_task *, | 1616 | int (*pgio_rpc_prepare)(struct rpc_task *, |
| 1600 | struct nfs_pgio_header *); | 1617 | struct nfs_pgio_header *); |
| 1601 | void (*read_setup)(struct nfs_pgio_header *, struct rpc_message *); | 1618 | void (*read_setup)(struct nfs_pgio_header *, struct rpc_message *); |
| @@ -34,6 +34,7 @@ · 33 unmodified lines | |||
| 34 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 34 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
| 35 | */ | 35 | */ |
| 36 | 36 | ||
| 37 | #include <crypto/algapi.h> | ||
| 37 | #include <crypto/hash.h> | 38 | #include <crypto/hash.h> |
| 38 | #include <crypto/skcipher.h> | 39 | #include <crypto/skcipher.h> |
| 39 | #include <linux/err.h> | 40 | #include <linux/err.h> |
| @@ -927,7 +928,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, · 887 unmodified lines | |||
| 927 | if (ret) | 928 | if (ret) |
| 928 | goto out_err; | 929 | goto out_err; |
| 929 | 930 | ||
| 930 | if (memcmp(pkt_hmac, our_hmac, kctx->gk5e->cksumlength) != 0) { | 931 | if (crypto_memneq(pkt_hmac, our_hmac, kctx->gk5e->cksumlength) != 0) { |
| 931 | ret = GSS_S_BAD_SIG; | 932 | ret = GSS_S_BAD_SIG; |
| 932 | goto out_err; | 933 | goto out_err; |
| 933 | } | 934 | } |
| @@ -1047,13 +1047,15 @@ out: · 1046 unmodified lines | |||
| 1047 | return ret; | 1047 | return ret; |
| 1048 | } | 1048 | } |
| 1049 | 1049 | ||
| 1050 | static struct rpc_rqst *xprt_dynamic_alloc_slot(struct rpc_xprt *xprt, gfp_t gfp_flags) | 1050 | static struct rpc_rqst *xprt_dynamic_alloc_slot(struct rpc_xprt *xprt) |
| 1051 | { | 1051 | { |
| 1052 | struct rpc_rqst *req = ERR_PTR(-EAGAIN); | 1052 | struct rpc_rqst *req = ERR_PTR(-EAGAIN); |
| 1053 | 1053 | ||
| 1054 | if (!atomic_add_unless(&xprt->num_reqs, 1, xprt->max_reqs)) | 1054 | if (!atomic_add_unless(&xprt->num_reqs, 1, xprt->max_reqs)) |
| 1055 | goto out; | 1055 | goto out; |
| 1056 | req = kzalloc(sizeof(struct rpc_rqst), gfp_flags); | 1056 | spin_unlock(&xprt->reserve_lock); |
| 1057 | req = kzalloc(sizeof(struct rpc_rqst), GFP_NOFS); | ||
| 1058 | spin_lock(&xprt->reserve_lock); | ||
| 1057 | if (req != NULL) | 1059 | if (req != NULL) |
| 1058 | goto out; | 1060 | goto out; |
| 1059 | atomic_dec(&xprt->num_reqs); | 1061 | atomic_dec(&xprt->num_reqs); |
| @@ -1081,7 +1083,7 @@ void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) · 21 unmodified lines | |||
| 1081 | list_del(&req->rq_list); | 1083 | list_del(&req->rq_list); |
| 1082 | goto out_init_req; | 1084 | goto out_init_req; |
| 1083 | } | 1085 | } |
| 1084 | req = xprt_dynamic_alloc_slot(xprt, GFP_NOWAIT|__GFP_NOWARN); | 1086 | req = xprt_dynamic_alloc_slot(xprt); |
| 1085 | if (!IS_ERR(req)) | 1087 | if (!IS_ERR(req)) |
| 1086 | goto out_init_req; | 1088 | goto out_init_req; |
| 1087 | switch (PTR_ERR(req)) { | 1089 | switch (PTR_ERR(req)) { |
| @@ -91,7 +91,7 @@ __fmr_unmap(struct rpcrdma_mw *mw) · 90 unmodified lines | |||
| 91 | 91 | ||
| 92 | list_add(&mw->fmr.fm_mr->list, &l); | 92 | list_add(&mw->fmr.fm_mr->list, &l); |
| 93 | rc = ib_unmap_fmr(&l); | 93 | rc = ib_unmap_fmr(&l); |
| 94 | list_del_init(&mw->fmr.fm_mr->list); | 94 | list_del(&mw->fmr.fm_mr->list); |
| 95 | return rc; | 95 | return rc; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| @@ -213,13 +213,11 @@ fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, · 115 unmodified lines | |||
| 213 | offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len)) | 213 | offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len)) |
| 214 | break; | 214 | break; |
| 215 | } | 215 | } |
| 216 | mw->mw_nents = i; | ||
| 217 | mw->mw_dir = rpcrdma_data_dir(writing); | 216 | mw->mw_dir = rpcrdma_data_dir(writing); |
| 218 | if (i == 0) | ||
| 219 | goto out_dmamap_err; | ||
| 220 | 217 | ||
| 221 | if (!ib_dma_map_sg(r_xprt->rx_ia.ri_device, | 218 | mw->mw_nents = ib_dma_map_sg(r_xprt->rx_ia.ri_device, |
| 222 | mw->mw_sg, mw->mw_nents, mw->mw_dir)) | 219 | mw->mw_sg, i, mw->mw_dir); |
| 220 | if (!mw->mw_nents) | ||
| 223 | goto out_dmamap_err; | 221 | goto out_dmamap_err; |
| 224 | 222 | ||
| 225 | for (i = 0, dma_pages = mw->fmr.fm_physaddrs; i < mw->mw_nents; i++) | 223 | for (i = 0, dma_pages = mw->fmr.fm_physaddrs; i < mw->mw_nents; i++) |
| @@ -237,16 +235,18 @@ fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, · 11 unmodified lines | |||
| 237 | return mw->mw_nents; | 235 | return mw->mw_nents; |
| 238 | 236 | ||
| 239 | out_dmamap_err: | 237 | out_dmamap_err: |
| 240 | pr_err("rpcrdma: failed to dma map sg %p sg_nents %u\n", | 238 | pr_err("rpcrdma: failed to DMA map sg %p sg_nents %d\n", |
| 241 | mw->mw_sg, mw->mw_nents); | 239 | mw->mw_sg, i); |
| 242 | rpcrdma_defer_mr_recovery(mw); | 240 | rpcrdma_put_mw(r_xprt, mw); |
| 243 | return -EIO; | 241 | return -EIO; |
| 244 | 242 | ||
| 245 | out_maperr: | 243 | out_maperr: |
| 246 | pr_err("rpcrdma: ib_map_phys_fmr %u@0x%llx+%i (%d) status %i\n", | 244 | pr_err("rpcrdma: ib_map_phys_fmr %u@0x%llx+%i (%d) status %i\n", |
| 247 | len, (unsigned long long)dma_pages[0], | 245 | len, (unsigned long long)dma_pages[0], |
| 248 | pageoff, mw->mw_nents, rc); | 246 | pageoff, mw->mw_nents, rc); |
| 249 | rpcrdma_defer_mr_recovery(mw); | 247 | ib_dma_unmap_sg(r_xprt->rx_ia.ri_device, |
| 248 | mw->mw_sg, mw->mw_nents, mw->mw_dir); | ||
| 249 | rpcrdma_put_mw(r_xprt, mw); | ||
| 250 | return -EIO; | 250 | return -EIO; |
| 251 | } | 251 | } |
| 252 | 252 | ||
| @@ -255,24 +255,26 @@ out_maperr: · 2 unmodified lines | |||
| 255 | * Sleeps until it is safe for the host CPU to access the | 255 | * Sleeps until it is safe for the host CPU to access the |
| 256 | * previously mapped memory regions. | 256 | * previously mapped memory regions. |
| 257 | * | 257 | * |
| 258 | * Caller ensures that req->rl_registered is not empty. | 258 | * Caller ensures that @mws is not empty before the call. This |
| 259 | * function empties the list. | ||
| 259 | */ | 260 | */ |
| 260 | static void | 261 | static void |
| 261 | fmr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) | 262 | fmr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct list_head *mws) |
| 262 | { | 263 | { |
| 263 | struct rpcrdma_mw *mw, *tmp; | 264 | struct rpcrdma_mw *mw; |
| 264 | LIST_HEAD(unmap_list); | 265 | LIST_HEAD(unmap_list); |
| 265 | int rc; | 266 | int rc; |
| 266 | 267 | ||
| 267 | dprintk("RPC: %s: req %p\n", __func__, req); | ||
| 268 | |||
| 269 | /* ORDER: Invalidate all of the req's MRs first | 268 | /* ORDER: Invalidate all of the req's MRs first |
| 270 | * | 269 | * |
| 271 | * ib_unmap_fmr() is slow, so use a single call instead | 270 | * ib_unmap_fmr() is slow, so use a single call instead |
| 272 | * of one call per mapped FMR. | 271 | * of one call per mapped FMR. |
| 273 | */ | 272 | */ |
| 274 | list_for_each_entry(mw, &req->rl_registered, mw_list) | 273 | list_for_each_entry(mw, mws, mw_list) { |
| 274 | dprintk("RPC: %s: unmapping fmr %p\n", | ||
| 275 | __func__, &mw->fmr); | ||
| 275 | list_add_tail(&mw->fmr.fm_mr->list, &unmap_list); | 276 | list_add_tail(&mw->fmr.fm_mr->list, &unmap_list); |
| 277 | } | ||
| 276 | r_xprt->rx_stats.local_inv_needed++; | 278 | r_xprt->rx_stats.local_inv_needed++; |
| 277 | rc = ib_unmap_fmr(&unmap_list); | 279 | rc = ib_unmap_fmr(&unmap_list); |
| 278 | if (rc) | 280 | if (rc) |
| @@ -281,9 +283,11 @@ fmr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) · 2 unmodified lines | |||
| 281 | /* ORDER: Now DMA unmap all of the req's MRs, and return | 283 | /* ORDER: Now DMA unmap all of the req's MRs, and return |
| 282 | * them to the free MW list. | 284 | * them to the free MW list. |
| 283 | */ | 285 | */ |
| 284 | list_for_each_entry_safe(mw, tmp, &req->rl_registered, mw_list) { | 286 | while (!list_empty(mws)) { |
| 285 | list_del_init(&mw->mw_list); | 287 | mw = rpcrdma_pop_mw(mws); |
| 286 | list_del_init(&mw->fmr.fm_mr->list); | 288 | dprintk("RPC: %s: DMA unmapping fmr %p\n", |
| 289 | __func__, &mw->fmr); | ||
| 290 | list_del(&mw->fmr.fm_mr->list); | ||
| 287 | ib_dma_unmap_sg(r_xprt->rx_ia.ri_device, | 291 | ib_dma_unmap_sg(r_xprt->rx_ia.ri_device, |
| 288 | mw->mw_sg, mw->mw_nents, mw->mw_dir); | 292 | mw->mw_sg, mw->mw_nents, mw->mw_dir); |
| 289 | rpcrdma_put_mw(r_xprt, mw); | 293 | rpcrdma_put_mw(r_xprt, mw); |
| @@ -294,8 +298,9 @@ fmr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) · 4 unmodified lines | |||
| 294 | out_reset: | 298 | out_reset: |
| 295 | pr_err("rpcrdma: ib_unmap_fmr failed (%i)\n", rc); | 299 | pr_err("rpcrdma: ib_unmap_fmr failed (%i)\n", rc); |
| 296 | 300 | ||
| 297 | list_for_each_entry_safe(mw, tmp, &req->rl_registered, mw_list) { | 301 | while (!list_empty(mws)) { |
| 298 | list_del_init(&mw->fmr.fm_mr->list); | 302 | mw = rpcrdma_pop_mw(mws); |
| 303 | list_del(&mw->fmr.fm_mr->list); | ||
| 299 | fmr_op_recover_mr(mw); | 304 | fmr_op_recover_mr(mw); |
| 300 | } | 305 | } |
| 301 | } | 306 | } |
| @@ -277,7 +277,7 @@ __frwr_sendcompletion_flush(struct ib_wc *wc, const char *wr) · 276 unmodified lines | |||
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | /** | 279 | /** |
| 280 | * frwr_wc_fastreg - Invoked by RDMA provider for each polled FastReg WC | 280 | * frwr_wc_fastreg - Invoked by RDMA provider for a flushed FastReg WC |
| 281 | * @cq: completion queue (ignored) | 281 | * @cq: completion queue (ignored) |
| 282 | * @wc: completed WR | 282 | * @wc: completed WR |
| 283 | * | 283 | * |
| @@ -298,7 +298,7 @@ frwr_wc_fastreg(struct ib_cq *cq, struct ib_wc *wc) · 14 unmodified lines | |||
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | /** | 300 | /** |
| 301 | * frwr_wc_localinv - Invoked by RDMA provider for each polled LocalInv WC | 301 | * frwr_wc_localinv - Invoked by RDMA provider for a flushed LocalInv WC |
| 302 | * @cq: completion queue (ignored) | 302 | * @cq: completion queue (ignored) |
| 303 | * @wc: completed WR | 303 | * @wc: completed WR |
| 304 | * | 304 | * |
| @@ -319,7 +319,7 @@ frwr_wc_localinv(struct ib_cq *cq, struct ib_wc *wc) · 14 unmodified lines | |||
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | /** | 321 | /** |
| 322 | * frwr_wc_localinv - Invoked by RDMA provider for each polled LocalInv WC | 322 | * frwr_wc_localinv_wake - Invoked by RDMA provider for a signaled LocalInv WC |
| 323 | * @cq: completion queue (ignored) | 323 | * @cq: completion queue (ignored) |
| 324 | * @wc: completed WR | 324 | * @wc: completed WR |
| 325 | * | 325 | * |
| @@ -355,7 +355,7 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, · 29 unmodified lines | |||
| 355 | struct ib_mr *mr; | 355 | struct ib_mr *mr; |
| 356 | struct ib_reg_wr *reg_wr; | 356 | struct ib_reg_wr *reg_wr; |
| 357 | struct ib_send_wr *bad_wr; | 357 | struct ib_send_wr *bad_wr; |
| 358 | int rc, i, n, dma_nents; | 358 | int rc, i, n; |
| 359 | u8 key; | 359 | u8 key; |
| 360 | 360 | ||
| 361 | mw = NULL; | 361 | mw = NULL; |
| @@ -391,14 +391,10 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, · 29 unmodified lines | |||
| 391 | offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len)) | 391 | offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len)) |
| 392 | break; | 392 | break; |
| 393 | } | 393 | } |
| 394 | mw->mw_nents = i; | ||
| 395 | mw->mw_dir = rpcrdma_data_dir(writing); | 394 | mw->mw_dir = rpcrdma_data_dir(writing); |
| 396 | if (i == 0) | ||
| 397 | goto out_dmamap_err; | ||
| 398 | 395 | ||
| 399 | dma_nents = ib_dma_map_sg(ia->ri_device, | 396 | mw->mw_nents = ib_dma_map_sg(ia->ri_device, mw->mw_sg, i, mw->mw_dir); |
| 400 | mw->mw_sg, mw->mw_nents, mw->mw_dir); | 397 | if (!mw->mw_nents) |
| 401 | if (!dma_nents) | ||
| 402 | goto out_dmamap_err; | 398 | goto out_dmamap_err; |
| 403 | 399 | ||
| 404 | n = ib_map_mr_sg(mr, mw->mw_sg, mw->mw_nents, NULL, PAGE_SIZE); | 400 | n = ib_map_mr_sg(mr, mw->mw_sg, mw->mw_nents, NULL, PAGE_SIZE); |
| @@ -436,13 +432,14 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, · 31 unmodified lines | |||
| 436 | return mw->mw_nents; | 432 | return mw->mw_nents; |
| 437 | 433 | ||
| 438 | out_dmamap_err: | 434 | out_dmamap_err: |
| 439 | pr_err("rpcrdma: failed to dma map sg %p sg_nents %u\n", | 435 | pr_err("rpcrdma: failed to DMA map sg %p sg_nents %d\n", |
| 440 | mw->mw_sg, mw->mw_nents); | 436 | mw->mw_sg, i); |
| 441 | rpcrdma_defer_mr_recovery(mw); | 437 | frmr->fr_state = FRMR_IS_INVALID; |
| 438 | rpcrdma_put_mw(r_xprt, mw); | ||
| 442 | return -EIO; | 439 | return -EIO; |
| 443 | 440 | ||
| 444 | out_mapmr_err: | 441 | out_mapmr_err: |
| 445 | pr_err("rpcrdma: failed to map mr %p (%u/%u)\n", | 442 | pr_err("rpcrdma: failed to map mr %p (%d/%d)\n", |
| 446 | frmr->fr_mr, n, mw->mw_nents); | 443 | frmr->fr_mr, n, mw->mw_nents); |
| 447 | rpcrdma_defer_mr_recovery(mw); | 444 | rpcrdma_defer_mr_recovery(mw); |
| 448 | return -EIO; | 445 | return -EIO; |
| @@ -458,21 +455,19 @@ out_senderr: · 9 unmodified lines | |||
| 458 | * Sleeps until it is safe for the host CPU to access the | 455 | * Sleeps until it is safe for the host CPU to access the |
| 459 | * previously mapped memory regions. | 456 | * previously mapped memory regions. |
| 460 | * | 457 | * |
| 461 | * Caller ensures that req->rl_registered is not empty. | 458 | * Caller ensures that @mws is not empty before the call. This |
| 459 | * function empties the list. | ||
| 462 | */ | 460 | */ |
| 463 | static void | 461 | static void |
| 464 | frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) | 462 | frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct list_head *mws) |
| 465 | { | 463 | { |
| 466 | struct ib_send_wr *first, **prev, *last, *bad_wr; | 464 | struct ib_send_wr *first, **prev, *last, *bad_wr; |
| 467 | struct rpcrdma_rep *rep = req->rl_reply; | ||
| 468 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | 465 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; |
| 469 | struct rpcrdma_frmr *f; | 466 | struct rpcrdma_frmr *f; |
| 470 | struct rpcrdma_mw *mw; | 467 | struct rpcrdma_mw *mw; |
| 471 | int count, rc; | 468 | int count, rc; |
| 472 | 469 | ||
| 473 | dprintk("RPC: %s: req %p\n", __func__, req); | 470 | /* ORDER: Invalidate all of the MRs first |
| 474 | |||
| 475 | /* ORDER: Invalidate all of the req's MRs first | ||
| 476 | * | 471 | * |
| 477 | * Chain the LOCAL_INV Work Requests and post them with | 472 | * Chain the LOCAL_INV Work Requests and post them with |
| 478 | * a single ib_post_send() call. | 473 | * a single ib_post_send() call. |
| @@ -480,11 +475,10 @@ frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) · 1 unmodified line | |||
| 480 | f = NULL; | 475 | f = NULL; |
| 481 | count = 0; | 476 | count = 0; |
| 482 | prev = &first; | 477 | prev = &first; |
| 483 | list_for_each_entry(mw, &req->rl_registered, mw_list) { | 478 | list_for_each_entry(mw, mws, mw_list) { |
| 484 | mw->frmr.fr_state = FRMR_IS_INVALID; | 479 | mw->frmr.fr_state = FRMR_IS_INVALID; |
| 485 | 480 | ||
| 486 | if ((rep->rr_wc_flags & IB_WC_WITH_INVALIDATE) && | 481 | if (mw->mw_flags & RPCRDMA_MW_F_RI) |
| 487 | (mw->mw_handle == rep->rr_inv_rkey)) | ||
| 488 | continue; | 482 | continue; |
| 489 | 483 | ||
| 490 | f = &mw->frmr; | 484 | f = &mw->frmr; |
| @@ -524,18 +518,19 @@ frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) · 33 unmodified lines | |||
| 524 | * unless ri_id->qp is a valid pointer. | 518 | * unless ri_id->qp is a valid pointer. |
| 525 | */ | 519 | */ |
| 526 | r_xprt->rx_stats.local_inv_needed++; | 520 | r_xprt->rx_stats.local_inv_needed++; |
| 521 | bad_wr = NULL; | ||
| 527 | rc = ib_post_send(ia->ri_id->qp, first, &bad_wr); | 522 | rc = ib_post_send(ia->ri_id->qp, first, &bad_wr); |
| 523 | if (bad_wr != first) | ||
| 524 | wait_for_completion(&f->fr_linv_done); | ||
| 528 | if (rc) | 525 | if (rc) |
| 529 | goto reset_mrs; | 526 | goto reset_mrs; |
| 530 | 527 | ||
| 531 | wait_for_completion(&f->fr_linv_done); | 528 | /* ORDER: Now DMA unmap all of the MRs, and return |
| 532 | |||
| 533 | /* ORDER: Now DMA unmap all of the req's MRs, and return | ||
| 534 | * them to the free MW list. | 529 | * them to the free MW list. |
| 535 | */ | 530 | */ |
| 536 | unmap: | 531 | unmap: |
| 537 | while (!list_empty(&req->rl_registered)) { | 532 | while (!list_empty(mws)) { |
| 538 | mw = rpcrdma_pop_mw(&req->rl_registered); | 533 | mw = rpcrdma_pop_mw(mws); |
| 539 | dprintk("RPC: %s: DMA unmapping frmr %p\n", | 534 | dprintk("RPC: %s: DMA unmapping frmr %p\n", |
| 540 | __func__, &mw->frmr); | 535 | __func__, &mw->frmr); |
| 541 | ib_dma_unmap_sg(ia->ri_device, | 536 | ib_dma_unmap_sg(ia->ri_device, |
| @@ -546,17 +541,19 @@ unmap: · 4 unmodified lines | |||
| 546 | 541 | ||
| 547 | reset_mrs: | 542 | reset_mrs: |
| 548 | pr_err("rpcrdma: FRMR invalidate ib_post_send returned %i\n", rc); | 543 | pr_err("rpcrdma: FRMR invalidate ib_post_send returned %i\n", rc); |
| 549 | rdma_disconnect(ia->ri_id); | ||
| 550 | 544 | ||
| 551 | /* Find and reset the MRs in the LOCAL_INV WRs that did not | 545 | /* Find and reset the MRs in the LOCAL_INV WRs that did not |
| 552 | * get posted. This is synchronous, and slow. | 546 | * get posted. |
| 553 | */ | 547 | */ |
| 554 | list_for_each_entry(mw, &req->rl_registered, mw_list) { | 548 | rpcrdma_init_cqcount(&r_xprt->rx_ep, -count); |
| 555 | f = &mw->frmr; | 549 | while (bad_wr) { |
| 556 | if (mw->mw_handle == bad_wr->ex.invalidate_rkey) { | 550 | f = container_of(bad_wr, struct rpcrdma_frmr, |
| 557 | __frwr_reset_mr(ia, mw); | 551 | fr_invwr); |
| 558 | bad_wr = bad_wr->next; | 552 | mw = container_of(f, struct rpcrdma_mw, frmr); |
| 559 | } | 553 | |
| 554 | __frwr_reset_mr(ia, mw); | ||
| 555 | |||
| 556 | bad_wr = bad_wr->next; | ||
| 560 | } | 557 | } |
| 561 | goto unmap; | 558 | goto unmap; |
| 562 | } | 559 | } |
| @@ -141,7 +141,7 @@ static bool rpcrdma_args_inline(struct rpcrdma_xprt *r_xprt, · 140 unmodified lines | |||
| 141 | 141 | ||
| 142 | if (xdr->page_len) { | 142 | if (xdr->page_len) { |
| 143 | remaining = xdr->page_len; | 143 | remaining = xdr->page_len; |
| 144 | offset = xdr->page_base & ~PAGE_MASK; | 144 | offset = offset_in_page(xdr->page_base); |
| 145 | count = 0; | 145 | count = 0; |
| 146 | while (remaining) { | 146 | while (remaining) { |
| 147 | remaining -= min_t(unsigned int, | 147 | remaining -= min_t(unsigned int, |
| @@ -222,7 +222,7 @@ rpcrdma_convert_iovs(struct rpcrdma_xprt *r_xprt, struct xdr_buf *xdrbuf, · 74 unmodified lines | |||
| 222 | 222 | ||
| 223 | len = xdrbuf->page_len; | 223 | len = xdrbuf->page_len; |
| 224 | ppages = xdrbuf->pages + (xdrbuf->page_base >> PAGE_SHIFT); | 224 | ppages = xdrbuf->pages + (xdrbuf->page_base >> PAGE_SHIFT); |
| 225 | page_base = xdrbuf->page_base & ~PAGE_MASK; | 225 | page_base = offset_in_page(xdrbuf->page_base); |
| 226 | p = 0; | 226 | p = 0; |
| 227 | while (len && n < RPCRDMA_MAX_SEGS) { | 227 | while (len && n < RPCRDMA_MAX_SEGS) { |
| 228 | if (!ppages[p]) { | 228 | if (!ppages[p]) { |
| @@ -540,7 +540,7 @@ rpcrdma_prepare_msg_sges(struct rpcrdma_ia *ia, struct rpcrdma_req *req, · 311 unmodified lines | |||
| 540 | goto out; | 540 | goto out; |
| 541 | 541 | ||
| 542 | page = virt_to_page(xdr->tail[0].iov_base); | 542 | page = virt_to_page(xdr->tail[0].iov_base); |
| 543 | page_base = (unsigned long)xdr->tail[0].iov_base & ~PAGE_MASK; | 543 | page_base = offset_in_page(xdr->tail[0].iov_base); |
| 544 | 544 | ||
| 545 | /* If the content in the page list is an odd length, | 545 | /* If the content in the page list is an odd length, |
| 546 | * xdr_write_pages() has added a pad at the beginning | 546 | * xdr_write_pages() has added a pad at the beginning |
| @@ -557,7 +557,7 @@ rpcrdma_prepare_msg_sges(struct rpcrdma_ia *ia, struct rpcrdma_req *req, · 10 unmodified lines | |||
| 557 | */ | 557 | */ |
| 558 | if (xdr->page_len) { | 558 | if (xdr->page_len) { |
| 559 | ppages = xdr->pages + (xdr->page_base >> PAGE_SHIFT); | 559 | ppages = xdr->pages + (xdr->page_base >> PAGE_SHIFT); |
| 560 | page_base = xdr->page_base & ~PAGE_MASK; | 560 | page_base = offset_in_page(xdr->page_base); |
| 561 | remaining = xdr->page_len; | 561 | remaining = xdr->page_len; |
| 562 | while (remaining) { | 562 | while (remaining) { |
| 563 | sge_no++; | 563 | sge_no++; |
| @@ -587,7 +587,7 @@ rpcrdma_prepare_msg_sges(struct rpcrdma_ia *ia, struct rpcrdma_req *req, · 23 unmodified lines | |||
| 587 | */ | 587 | */ |
| 588 | if (xdr->tail[0].iov_len) { | 588 | if (xdr->tail[0].iov_len) { |
| 589 | page = virt_to_page(xdr->tail[0].iov_base); | 589 | page = virt_to_page(xdr->tail[0].iov_base); |
| 590 | page_base = (unsigned long)xdr->tail[0].iov_base & ~PAGE_MASK; | 590 | page_base = offset_in_page(xdr->tail[0].iov_base); |
| 591 | len = xdr->tail[0].iov_len; | 591 | len = xdr->tail[0].iov_len; |
| 592 | 592 | ||
| 593 | map_tail: | 593 | map_tail: |
| @@ -734,6 +734,9 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) · 140 unmodified lines | |||
| 734 | rpclen = 0; | 734 | rpclen = 0; |
| 735 | } | 735 | } |
| 736 | 736 | ||
| 737 | req->rl_xid = rqst->rq_xid; | ||
| 738 | rpcrdma_insert_req(&r_xprt->rx_buf, req); | ||
| 739 | |||
| 737 | /* This implementation supports the following combinations | 740 | /* This implementation supports the following combinations |
| 738 | * of chunk lists in one RPC-over-RDMA Call message: | 741 | * of chunk lists in one RPC-over-RDMA Call message: |
| 739 | * | 742 | * |
| @@ -875,9 +878,9 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad) · 135 unmodified lines | |||
| 875 | srcp += curlen; | 878 | srcp += curlen; |
| 876 | copy_len -= curlen; | 879 | copy_len -= curlen; |
| 877 | 880 | ||
| 878 | page_base = rqst->rq_rcv_buf.page_base; | 881 | ppages = rqst->rq_rcv_buf.pages + |
| 879 | ppages = rqst->rq_rcv_buf.pages + (page_base >> PAGE_SHIFT); | 882 | (rqst->rq_rcv_buf.page_base >> PAGE_SHIFT); |
| 880 | page_base &= ~PAGE_MASK; | 883 | page_base = offset_in_page(rqst->rq_rcv_buf.page_base); |
| 881 | fixup_copy_count = 0; | 884 | fixup_copy_count = 0; |
| 882 | if (copy_len && rqst->rq_rcv_buf.page_len) { | 885 | if (copy_len && rqst->rq_rcv_buf.page_len) { |
| 883 | int pagelist_len; | 886 | int pagelist_len; |
| @@ -928,6 +931,24 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad) · 44 unmodified lines | |||
| 928 | return fixup_copy_count; | 931 | return fixup_copy_count; |
| 929 | } | 932 | } |
| 930 | 933 | ||
| 934 | /* Caller must guarantee @rep remains stable during this call. | ||
| 935 | */ | ||
| 936 | static void | ||
| 937 | rpcrdma_mark_remote_invalidation(struct list_head *mws, | ||
| 938 | struct rpcrdma_rep *rep) | ||
| 939 | { | ||
| 940 | struct rpcrdma_mw *mw; | ||
| 941 | |||
| 942 | if (!(rep->rr_wc_flags & IB_WC_WITH_INVALIDATE)) | ||
| 943 | return; | ||
| 944 | |||
| 945 | list_for_each_entry(mw, mws, mw_list) | ||
| 946 | if (mw->mw_handle == rep->rr_inv_rkey) { | ||
| 947 | mw->mw_flags = RPCRDMA_MW_F_RI; | ||
| 948 | break; /* only one invalidated MR per RPC */ | ||
| 949 | } | ||
| 950 | } | ||
| 951 | |||
| 931 | #if defined(CONFIG_SUNRPC_BACKCHANNEL) | 952 | #if defined(CONFIG_SUNRPC_BACKCHANNEL) |
| 932 | /* By convention, backchannel calls arrive via rdma_msg type | 953 | /* By convention, backchannel calls arrive via rdma_msg type |
| 933 | * messages, and never populate the chunk lists. This makes | 954 | * messages, and never populate the chunk lists. This makes |
| @@ -969,14 +990,16 @@ rpcrdma_reply_handler(struct work_struct *work) · 35 unmodified lines | |||
| 969 | { | 990 | { |
| 970 | struct rpcrdma_rep *rep = | 991 | struct rpcrdma_rep *rep = |
| 971 | container_of(work, struct rpcrdma_rep, rr_work); | 992 | container_of(work, struct rpcrdma_rep, rr_work); |
| 993 | struct rpcrdma_xprt *r_xprt = rep->rr_rxprt; | ||
| 994 | struct rpcrdma_buffer *buf = &r_xprt->rx_buf; | ||
| 995 | struct rpc_xprt *xprt = &r_xprt->rx_xprt; | ||
| 972 | struct rpcrdma_msg *headerp; | 996 | struct rpcrdma_msg *headerp; |
| 973 | struct rpcrdma_req *req; | 997 | struct rpcrdma_req *req; |
| 974 | struct rpc_rqst *rqst; | 998 | struct rpc_rqst *rqst; |
| 975 | struct rpcrdma_xprt *r_xprt = rep->rr_rxprt; | ||
| 976 | struct rpc_xprt *xprt = &r_xprt->rx_xprt; | ||
| 977 | __be32 *iptr; | 999 | __be32 *iptr; |
| 978 | int rdmalen, status, rmerr; | 1000 | int rdmalen, status, rmerr; |
| 979 | unsigned long cwnd; | 1001 | unsigned long cwnd; |
| 1002 | struct list_head mws; | ||
| 980 | 1003 | ||
| 981 | dprintk("RPC: %s: incoming rep %p\n", __func__, rep); | 1004 | dprintk("RPC: %s: incoming rep %p\n", __func__, rep); |
| 982 | 1005 | ||
| @@ -994,27 +1017,45 @@ rpcrdma_reply_handler(struct work_struct *work) · 11 unmodified lines | |||
| 994 | /* Match incoming rpcrdma_rep to an rpcrdma_req to | 1017 | /* Match incoming rpcrdma_rep to an rpcrdma_req to |
| 995 | * get context for handling any incoming chunks. | 1018 | * get context for handling any incoming chunks. |
| 996 | */ | 1019 | */ |
| 997 | spin_lock_bh(&xprt->transport_lock); | 1020 | spin_lock(&buf->rb_lock); |
| 998 | rqst = xprt_lookup_rqst(xprt, headerp->rm_xid); | 1021 | req = rpcrdma_lookup_req_locked(&r_xprt->rx_buf, |
| 999 | if (!rqst) | 1022 | headerp->rm_xid); |
| 1023 | if (!req) | ||
| 1000 | goto out_nomatch; | 1024 | goto out_nomatch; |
| 1001 | |||
| 1002 | req = rpcr_to_rdmar(rqst); | ||
| 1003 | if (req->rl_reply) | 1025 | if (req->rl_reply) |
| 1004 | goto out_duplicate; | 1026 | goto out_duplicate; |
| 1005 | 1027 | ||
| 1006 | /* Sanity checking has passed. We are now committed | 1028 | list_replace_init(&req->rl_registered, &mws); |
| 1007 | * to complete this transaction. | 1029 | rpcrdma_mark_remote_invalidation(&mws, rep); |
| 1030 | |||
| 1031 | /* Avoid races with signals and duplicate replies | ||
| 1032 | * by marking this req as matched. | ||
| 1008 | */ | 1033 | */ |
| 1009 | list_del_init(&rqst->rq_list); | 1034 | req->rl_reply = rep; |
| 1010 | spin_unlock_bh(&xprt->transport_lock); | 1035 | spin_unlock(&buf->rb_lock); |
| 1036 | |||
| 1011 | dprintk("RPC: %s: reply %p completes request %p (xid 0x%08x)\n", | 1037 | dprintk("RPC: %s: reply %p completes request %p (xid 0x%08x)\n", |
| 1012 | __func__, rep, req, be32_to_cpu(headerp->rm_xid)); | 1038 | __func__, rep, req, be32_to_cpu(headerp->rm_xid)); |
| 1013 | 1039 | ||
| 1014 | /* from here on, the reply is no longer an orphan */ | 1040 | /* Invalidate and unmap the data payloads before waking the |
| 1015 | req->rl_reply = rep; | 1041 | * waiting application. This guarantees the memory regions |
| 1016 | xprt->reestablish_timeout = 0; | 1042 | * are properly fenced from the server before the application |
| 1043 | * accesses the data. It also ensures proper send flow control: | ||
| 1044 | * waking the next RPC waits until this RPC has relinquished | ||
| 1045 | * all its Send Queue entries. | ||
| 1046 | */ | ||
| 1047 | if (!list_empty(&mws)) | ||
| 1048 | r_xprt->rx_ia.ri_ops->ro_unmap_sync(r_xprt, &mws); | ||
| 1017 | 1049 | ||
| 1050 | /* Perform XID lookup, reconstruction of the RPC reply, and | ||
| 1051 | * RPC completion while holding the transport lock to ensure | ||
| 1052 | * the rep, rqst, and rq_task pointers remain stable. | ||
| 1053 | */ | ||
| 1054 | spin_lock_bh(&xprt->transport_lock); | ||
| 1055 | rqst = xprt_lookup_rqst(xprt, headerp->rm_xid); | ||
| 1056 | if (!rqst) | ||
| 1057 | goto out_norqst; | ||
| 1058 | xprt->reestablish_timeout = 0; | ||
| 1018 | if (headerp->rm_vers != rpcrdma_version) | 1059 | if (headerp->rm_vers != rpcrdma_version) |
| 1019 | goto out_badversion; | 1060 | goto out_badversion; |
| 1020 | 1061 | ||
| @@ -1024,12 +1065,9 @@ rpcrdma_reply_handler(struct work_struct *work) · 3 unmodified lines | |||
| 1024 | case rdma_msg: | 1065 | case rdma_msg: |
| 1025 | /* never expect read chunks */ | 1066 | /* never expect read chunks */ |
| 1026 | /* never expect reply chunks (two ways to check) */ | 1067 | /* never expect reply chunks (two ways to check) */ |
| 1027 | /* never expect write chunks without having offered RDMA */ | ||
| 1028 | if (headerp->rm_body.rm_chunks[0] != xdr_zero || | 1068 | if (headerp->rm_body.rm_chunks[0] != xdr_zero || |
| 1029 | (headerp->rm_body.rm_chunks[1] == xdr_zero && | 1069 | (headerp->rm_body.rm_chunks[1] == xdr_zero && |
| 1030 | headerp->rm_body.rm_chunks[2] != xdr_zero) || | 1070 | headerp->rm_body.rm_chunks[2] != xdr_zero)) |
| 1031 | (headerp->rm_body.rm_chunks[1] != xdr_zero && | ||
| 1032 | list_empty(&req->rl_registered))) | ||
| 1033 | goto badheader; | 1071 | goto badheader; |
| 1034 | if (headerp->rm_body.rm_chunks[1] != xdr_zero) { | 1072 | if (headerp->rm_body.rm_chunks[1] != xdr_zero) { |
| 1035 | /* count any expected write chunks in read reply */ | 1073 | /* count any expected write chunks in read reply */ |
| @@ -1066,8 +1104,7 @@ rpcrdma_reply_handler(struct work_struct *work) · 30 unmodified lines | |||
| 1066 | /* never expect read or write chunks, always reply chunks */ | 1104 | /* never expect read or write chunks, always reply chunks */ |
| 1067 | if (headerp->rm_body.rm_chunks[0] != xdr_zero || | 1105 | if (headerp->rm_body.rm_chunks[0] != xdr_zero || |
| 1068 | headerp->rm_body.rm_chunks[1] != xdr_zero || | 1106 | headerp->rm_body.rm_chunks[1] != xdr_zero || |
| 1069 | headerp->rm_body.rm_chunks[2] != xdr_one || | 1107 | headerp->rm_body.rm_chunks[2] != xdr_one) |
| 1070 | list_empty(&req->rl_registered)) | ||
| 1071 | goto badheader; | 1108 | goto badheader; |
| 1072 | iptr = (__be32 *)((unsigned char *)headerp + | 1109 | iptr = (__be32 *)((unsigned char *)headerp + |
| 1073 | RPCRDMA_HDRLEN_MIN); | 1110 | RPCRDMA_HDRLEN_MIN); |
| @@ -1093,17 +1130,6 @@ badheader: · 19 unmodified lines | |||
| 1093 | } | 1130 | } |
| 1094 | 1131 | ||
| 1095 | out: | 1132 | out: |
| 1096 | /* Invalidate and flush the data payloads before waking the | ||
| 1097 | * waiting application. This guarantees the memory region is | ||
| 1098 | * properly fenced from the server before the application | ||
| 1099 | * accesses the data. It also ensures proper send flow | ||
| 1100 | * control: waking the next RPC waits until this RPC has | ||
| 1101 | * relinquished all its Send Queue entries. | ||
| 1102 | */ | ||
| 1103 | if (!list_empty(&req->rl_registered)) | ||
| 1104 | r_xprt->rx_ia.ri_ops->ro_unmap_sync(r_xprt, req); | ||
| 1105 | |||
| 1106 | spin_lock_bh(&xprt->transport_lock); | ||
| 1107 | cwnd = xprt->cwnd; | 1133 | cwnd = xprt->cwnd; |
| 1108 | xprt->cwnd = atomic_read(&r_xprt->rx_buf.rb_credits) << RPC_CWNDSHIFT; | 1134 | xprt->cwnd = atomic_read(&r_xprt->rx_buf.rb_credits) << RPC_CWNDSHIFT; |
| 1109 | if (xprt->cwnd > cwnd) | 1135 | if (xprt->cwnd > cwnd) |
| @@ -1112,7 +1138,7 @@ out: · 2 unmodified lines | |||
| 1112 | xprt_complete_rqst(rqst->rq_task, status); | 1138 | xprt_complete_rqst(rqst->rq_task, status); |
| 1113 | spin_unlock_bh(&xprt->transport_lock); | 1139 | spin_unlock_bh(&xprt->transport_lock); |
| 1114 | dprintk("RPC: %s: xprt_complete_rqst(0x%p, 0x%p, %d)\n", | 1140 | dprintk("RPC: %s: xprt_complete_rqst(0x%p, 0x%p, %d)\n", |
| 1115 | __func__, xprt, rqst, status); | 1141 | __func__, xprt, rqst, status); |
| 1116 | return; | 1142 | return; |
| 1117 | 1143 | ||
| 1118 | out_badstatus: | 1144 | out_badstatus: |
| @@ -1161,26 +1187,37 @@ out_rdmaerr: · 42 unmodified lines | |||
| 1161 | r_xprt->rx_stats.bad_reply_count++; | 1187 | r_xprt->rx_stats.bad_reply_count++; |
| 1162 | goto out; | 1188 | goto out; |
| 1163 | 1189 | ||
| 1164 | /* If no pending RPC transaction was matched, post a replacement | 1190 | /* The req was still available, but by the time the transport_lock |
| 1165 | * receive buffer before returning. | 1191 | * was acquired, the rqst and task had been released. Thus the RPC |
| 1192 | * has already been terminated. | ||
| 1166 | */ | 1193 | */ |
| 1194 | out_norqst: | ||
| 1195 | spin_unlock_bh(&xprt->transport_lock); | ||
| 1196 | rpcrdma_buffer_put(req); | ||
| 1197 | dprintk("RPC: %s: race, no rqst left for req %p\n", | ||
| 1198 | __func__, req); | ||
| 1199 | return; | ||
| 1200 | |||
| 1167 | out_shortreply: | 1201 | out_shortreply: |
| 1168 | dprintk("RPC: %s: short/invalid reply\n", __func__); | 1202 | dprintk("RPC: %s: short/invalid reply\n", __func__); |
| 1169 | goto repost; | 1203 | goto repost; |
| 1170 | 1204 | ||
| 1171 | out_nomatch: | 1205 | out_nomatch: |
| 1172 | spin_unlock_bh(&xprt->transport_lock); | 1206 | spin_unlock(&buf->rb_lock); |
| 1173 | dprintk("RPC: %s: no match for incoming xid 0x%08x len %d\n", | 1207 | dprintk("RPC: %s: no match for incoming xid 0x%08x len %d\n", |
| 1174 | __func__, be32_to_cpu(headerp->rm_xid), | 1208 | __func__, be32_to_cpu(headerp->rm_xid), |
| 1175 | rep->rr_len); | 1209 | rep->rr_len); |
| 1176 | goto repost; | 1210 | goto repost; |
| 1177 | 1211 | ||
| 1178 | out_duplicate: | 1212 | out_duplicate: |
| 1179 | spin_unlock_bh(&xprt->transport_lock); | 1213 | spin_unlock(&buf->rb_lock); |
| 1180 | dprintk("RPC: %s: " | 1214 | dprintk("RPC: %s: " |
| 1181 | "duplicate reply %p to RPC request %p: xid 0x%08x\n", | 1215 | "duplicate reply %p to RPC request %p: xid 0x%08x\n", |
| 1182 | __func__, rep, req, be32_to_cpu(headerp->rm_xid)); | 1216 | __func__, rep, req, be32_to_cpu(headerp->rm_xid)); |
| 1183 | 1217 | ||
| 1218 | /* If no pending RPC transaction was matched, post a replacement | ||
| 1219 | * receive buffer before returning. | ||
| 1220 | */ | ||
| 1184 | repost: | 1221 | repost: |
| 1185 | r_xprt->rx_stats.bad_reply_count++; | 1222 | r_xprt->rx_stats.bad_reply_count++; |
| 1186 | if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, rep)) | 1223 | if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, rep)) |
| @@ -684,7 +684,8 @@ xprt_rdma_free(struct rpc_task *task) · 683 unmodified lines | |||
| 684 | 684 | ||
| 685 | dprintk("RPC: %s: called on 0x%p\n", __func__, req->rl_reply); | 685 | dprintk("RPC: %s: called on 0x%p\n", __func__, req->rl_reply); |
| 686 | 686 | ||
| 687 | if (unlikely(!list_empty(&req->rl_registered))) | 687 | rpcrdma_remove_req(&r_xprt->rx_buf, req); |
| 688 | if (!list_empty(&req->rl_registered)) | ||
| 688 | ia->ri_ops->ro_unmap_safe(r_xprt, req, !RPC_IS_ASYNC(task)); | 689 | ia->ri_ops->ro_unmap_safe(r_xprt, req, !RPC_IS_ASYNC(task)); |
| 689 | rpcrdma_unmap_sges(ia, req); | 690 | rpcrdma_unmap_sges(ia, req); |
| 690 | rpcrdma_buffer_put(req); | 691 | rpcrdma_buffer_put(req); |
| @@ -243,8 +243,6 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) · 242 unmodified lines | |||
| 243 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) | 243 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) |
| 244 | struct sockaddr *sap = (struct sockaddr *)&ep->rep_remote_addr; | 244 | struct sockaddr *sap = (struct sockaddr *)&ep->rep_remote_addr; |
| 245 | #endif | 245 | #endif |
| 246 | struct ib_qp_attr *attr = &ia->ri_qp_attr; | ||
| 247 | struct ib_qp_init_attr *iattr = &ia->ri_qp_init_attr; | ||
| 248 | int connstate = 0; | 246 | int connstate = 0; |
| 249 | 247 | ||
| 250 | switch (event->event) { | 248 | switch (event->event) { |
| @@ -267,7 +265,8 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) · 16 unmodified lines | |||
| 267 | break; | 265 | break; |
| 268 | case RDMA_CM_EVENT_DEVICE_REMOVAL: | 266 | case RDMA_CM_EVENT_DEVICE_REMOVAL: |
| 269 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) | 267 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) |
| 270 | pr_info("rpcrdma: removing device for %pIS:%u\n", | 268 | pr_info("rpcrdma: removing device %s for %pIS:%u\n", |
| 269 | ia->ri_device->name, | ||
| 271 | sap, rpc_get_port(sap)); | 270 | sap, rpc_get_port(sap)); |
| 272 | #endif | 271 | #endif |
| 273 | set_bit(RPCRDMA_IAF_REMOVING, &ia->ri_flags); | 272 | set_bit(RPCRDMA_IAF_REMOVING, &ia->ri_flags); |
| @@ -282,13 +281,6 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) · 8 unmodified lines | |||
| 282 | return 1; | 281 | return 1; |
| 283 | case RDMA_CM_EVENT_ESTABLISHED: | 282 | case RDMA_CM_EVENT_ESTABLISHED: |
| 284 | connstate = 1; | 283 | connstate = 1; |
| 285 | ib_query_qp(ia->ri_id->qp, attr, | ||
| 286 | IB_QP_MAX_QP_RD_ATOMIC | IB_QP_MAX_DEST_RD_ATOMIC, | ||
| 287 | iattr); | ||
| 288 | dprintk("RPC: %s: %d responder resources" | ||
| 289 | " (%d initiator)\n", | ||
| 290 | __func__, attr->max_dest_rd_atomic, | ||
| 291 | attr->max_rd_atomic); | ||
| 292 | rpcrdma_update_connect_private(xprt, &event->param.conn); | 284 | rpcrdma_update_connect_private(xprt, &event->param.conn); |
| 293 | goto connected; | 285 | goto connected; |
| 294 | case RDMA_CM_EVENT_CONNECT_ERROR: | 286 | case RDMA_CM_EVENT_CONNECT_ERROR: |
| @@ -298,11 +290,9 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) · 3 unmodified lines | |||
| 298 | connstate = -ENETDOWN; | 290 | connstate = -ENETDOWN; |
| 299 | goto connected; | 291 | goto connected; |
| 300 | case RDMA_CM_EVENT_REJECTED: | 292 | case RDMA_CM_EVENT_REJECTED: |
| 301 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) | 293 | dprintk("rpcrdma: connection to %pIS:%u rejected: %s\n", |
| 302 | pr_info("rpcrdma: connection to %pIS:%u on %s rejected: %s\n", | 294 | sap, rpc_get_port(sap), |
| 303 | sap, rpc_get_port(sap), ia->ri_device->name, | ||
| 304 | rdma_reject_msg(id, event->status)); | 295 | rdma_reject_msg(id, event->status)); |
| 305 | #endif | ||
| 306 | connstate = -ECONNREFUSED; | 296 | connstate = -ECONNREFUSED; |
| 307 | if (event->status == IB_CM_REJ_STALE_CONN) | 297 | if (event->status == IB_CM_REJ_STALE_CONN) |
| 308 | connstate = -EAGAIN; | 298 | connstate = -EAGAIN; |
| @@ -310,37 +300,19 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) · 1 unmodified line | |||
| 310 | case RDMA_CM_EVENT_DISCONNECTED: | 300 | case RDMA_CM_EVENT_DISCONNECTED: |
| 311 | connstate = -ECONNABORTED; | 301 | connstate = -ECONNABORTED; |
| 312 | connected: | 302 | connected: |
| 313 | dprintk("RPC: %s: %sconnected\n", | ||
| 314 | __func__, connstate > 0 ? "" : "dis"); | ||
| 315 | atomic_set(&xprt->rx_buf.rb_credits, 1); | 303 | atomic_set(&xprt->rx_buf.rb_credits, 1); |
| 316 | ep->rep_connected = connstate; | 304 | ep->rep_connected = connstate; |
| 317 | rpcrdma_conn_func(ep); | 305 | rpcrdma_conn_func(ep); |
| 318 | wake_up_all(&ep->rep_connect_wait); | 306 | wake_up_all(&ep->rep_connect_wait); |
| 319 | /*FALLTHROUGH*/ | 307 | /*FALLTHROUGH*/ |
| 320 | default: | 308 | default: |
| 321 | dprintk("RPC: %s: %pIS:%u (ep 0x%p): %s\n", | 309 | dprintk("RPC: %s: %pIS:%u on %s/%s (ep 0x%p): %s\n", |
| 322 | __func__, sap, rpc_get_port(sap), ep, | 310 | __func__, sap, rpc_get_port(sap), |
| 323 | rdma_event_msg(event->event)); | 311 | ia->ri_device->name, ia->ri_ops->ro_displayname, |
| 312 | ep, rdma_event_msg(event->event)); | ||
| 324 | break; | 313 | break; |
| 325 | } | 314 | } |
| 326 | 315 | ||
| 327 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) | ||
| 328 | if (connstate == 1) { | ||
| 329 | int ird = attr->max_dest_rd_atomic; | ||
| 330 | int tird = ep->rep_remote_cma.responder_resources; | ||
| 331 | |||
| 332 | pr_info("rpcrdma: connection to %pIS:%u on %s, memreg '%s', %d credits, %d responders%s\n", | ||
| 333 | sap, rpc_get_port(sap), | ||
| 334 | ia->ri_device->name, | ||
| 335 | ia->ri_ops->ro_displayname, | ||
| 336 | xprt->rx_buf.rb_max_requests, | ||
| 337 | ird, ird < 4 && ird < tird / 2 ? " (low!)" : ""); | ||
| 338 | } else if (connstate < 0) { | ||
| 339 | pr_info("rpcrdma: connection to %pIS:%u closed (%d)\n", | ||
| 340 | sap, rpc_get_port(sap), connstate); | ||
| 341 | } | ||
| 342 | #endif | ||
| 343 | |||
| 344 | return 0; | 316 | return 0; |
| 345 | } | 317 | } |
| 346 | 318 | ||
| @@ -971,7 +943,6 @@ rpcrdma_create_req(struct rpcrdma_xprt *r_xprt) · 624 unmodified lines | |||
| 971 | if (req == NULL) | 943 | if (req == NULL) |
| 972 | return ERR_PTR(-ENOMEM); | 944 | return ERR_PTR(-ENOMEM); |
| 973 | 945 | ||
| 974 | INIT_LIST_HEAD(&req->rl_free); | ||
| 975 | spin_lock(&buffer->rb_reqslock); | 946 | spin_lock(&buffer->rb_reqslock); |
| 976 | list_add(&req->rl_all, &buffer->rb_allreqs); | 947 | list_add(&req->rl_all, &buffer->rb_allreqs); |
| 977 | spin_unlock(&buffer->rb_reqslock); | 948 | spin_unlock(&buffer->rb_reqslock); |
| @@ -1033,6 +1004,7 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt) · 55 unmodified lines | |||
| 1033 | spin_lock_init(&buf->rb_recovery_lock); | 1004 | spin_lock_init(&buf->rb_recovery_lock); |
| 1034 | INIT_LIST_HEAD(&buf->rb_mws); | 1005 | INIT_LIST_HEAD(&buf->rb_mws); |
| 1035 | INIT_LIST_HEAD(&buf->rb_all); | 1006 | INIT_LIST_HEAD(&buf->rb_all); |
| 1007 | INIT_LIST_HEAD(&buf->rb_pending); | ||
| 1036 | INIT_LIST_HEAD(&buf->rb_stale_mrs); | 1008 | INIT_LIST_HEAD(&buf->rb_stale_mrs); |
| 1037 | INIT_DELAYED_WORK(&buf->rb_refresh_worker, | 1009 | INIT_DELAYED_WORK(&buf->rb_refresh_worker, |
| 1038 | rpcrdma_mr_refresh_worker); | 1010 | rpcrdma_mr_refresh_worker); |
| @@ -1055,7 +1027,7 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt) · 16 unmodified lines | |||
| 1055 | goto out; | 1027 | goto out; |
| 1056 | } | 1028 | } |
| 1057 | req->rl_backchannel = false; | 1029 | req->rl_backchannel = false; |
| 1058 | list_add(&req->rl_free, &buf->rb_send_bufs); | 1030 | list_add(&req->rl_list, &buf->rb_send_bufs); |
| 1059 | } | 1031 | } |
| 1060 | 1032 | ||
| 1061 | INIT_LIST_HEAD(&buf->rb_recv_bufs); | 1033 | INIT_LIST_HEAD(&buf->rb_recv_bufs); |
| @@ -1084,8 +1056,8 @@ rpcrdma_buffer_get_req_locked(struct rpcrdma_buffer *buf) · 22 unmodified lines | |||
| 1084 | struct rpcrdma_req *req; | 1056 | struct rpcrdma_req *req; |
| 1085 | 1057 | ||
| 1086 | req = list_first_entry(&buf->rb_send_bufs, | 1058 | req = list_first_entry(&buf->rb_send_bufs, |
| 1087 | struct rpcrdma_req, rl_free); | 1059 | struct rpcrdma_req, rl_list); |
| 1088 | list_del(&req->rl_free); | 1060 | list_del_init(&req->rl_list); |
| 1089 | return req; | 1061 | return req; |
| 1090 | } | 1062 | } |
| 1091 | 1063 | ||
| @@ -1187,6 +1159,7 @@ rpcrdma_get_mw(struct rpcrdma_xprt *r_xprt) · 95 unmodified lines | |||
| 1187 | 1159 | ||
| 1188 | if (!mw) | 1160 | if (!mw) |
| 1189 | goto out_nomws; | 1161 | goto out_nomws; |
| 1162 | mw->mw_flags = 0; | ||
| 1190 | return mw; | 1163 | return mw; |
| 1191 | 1164 | ||
| 1192 | out_nomws: | 1165 | out_nomws: |
| @@ -1267,7 +1240,7 @@ rpcrdma_buffer_put(struct rpcrdma_req *req) · 74 unmodified lines | |||
| 1267 | 1240 | ||
| 1268 | spin_lock(&buffers->rb_lock); | 1241 | spin_lock(&buffers->rb_lock); |
| 1269 | buffers->rb_send_count--; | 1242 | buffers->rb_send_count--; |
| 1270 | list_add_tail(&req->rl_free, &buffers->rb_send_bufs); | 1243 | list_add_tail(&req->rl_list, &buffers->rb_send_bufs); |
| 1271 | if (rep) { | 1244 | if (rep) { |
| 1272 | buffers->rb_recv_count--; | 1245 | buffers->rb_recv_count--; |
| 1273 | list_add_tail(&rep->rr_list, &buffers->rb_recv_bufs); | 1246 | list_add_tail(&rep->rr_list, &buffers->rb_recv_bufs); |
| @@ -271,6 +271,7 @@ struct rpcrdma_mw { · 270 unmodified lines | |||
| 271 | struct scatterlist *mw_sg; | 271 | struct scatterlist *mw_sg; |
| 272 | int mw_nents; | 272 | int mw_nents; |
| 273 | enum dma_data_direction mw_dir; | 273 | enum dma_data_direction mw_dir; |
| 274 | unsigned long mw_flags; | ||
| 274 | union { | 275 | union { |
| 275 | struct rpcrdma_fmr fmr; | 276 | struct rpcrdma_fmr fmr; |
| 276 | struct rpcrdma_frmr frmr; | 277 | struct rpcrdma_frmr frmr; |
| @@ -282,6 +283,11 @@ struct rpcrdma_mw { · 5 unmodified lines | |||
| 282 | struct list_head mw_all; | 283 | struct list_head mw_all; |
| 283 | }; | 284 | }; |
| 284 | 285 | ||
| 286 | /* mw_flags */ | ||
| 287 | enum { | ||
| 288 | RPCRDMA_MW_F_RI = 1, | ||
| 289 | }; | ||
| 290 | |||
| 285 | /* | 291 | /* |
| 286 | * struct rpcrdma_req -- structure central to the request/reply sequence. | 292 | * struct rpcrdma_req -- structure central to the request/reply sequence. |
| 287 | * | 293 | * |
| @@ -334,7 +340,8 @@ enum { · 46 unmodified lines | |||
| 334 | 340 | ||
| 335 | struct rpcrdma_buffer; | 341 | struct rpcrdma_buffer; |
| 336 | struct rpcrdma_req { | 342 | struct rpcrdma_req { |
| 337 | struct list_head rl_free; | 343 | struct list_head rl_list; |
| 344 | __be32 rl_xid; | ||
| 338 | unsigned int rl_mapped_sges; | 345 | unsigned int rl_mapped_sges; |
| 339 | unsigned int rl_connect_cookie; | 346 | unsigned int rl_connect_cookie; |
| 340 | struct rpcrdma_buffer *rl_buffer; | 347 | struct rpcrdma_buffer *rl_buffer; |
| @@ -396,6 +403,7 @@ struct rpcrdma_buffer { · 55 unmodified lines | |||
| 396 | int rb_send_count, rb_recv_count; | 403 | int rb_send_count, rb_recv_count; |
| 397 | struct list_head rb_send_bufs; | 404 | struct list_head rb_send_bufs; |
| 398 | struct list_head rb_recv_bufs; | 405 | struct list_head rb_recv_bufs; |
| 406 | struct list_head rb_pending; | ||
| 399 | u32 rb_max_requests; | 407 | u32 rb_max_requests; |
| 400 | atomic_t rb_credits; /* most recent credit grant */ | 408 | atomic_t rb_credits; /* most recent credit grant */ |
| 401 | 409 | ||
| @@ -461,7 +469,7 @@ struct rpcrdma_memreg_ops { · 59 unmodified lines | |||
| 461 | struct rpcrdma_mr_seg *, int, bool, | 469 | struct rpcrdma_mr_seg *, int, bool, |
| 462 | struct rpcrdma_mw **); | 470 | struct rpcrdma_mw **); |
| 463 | void (*ro_unmap_sync)(struct rpcrdma_xprt *, | 471 | void (*ro_unmap_sync)(struct rpcrdma_xprt *, |
| 464 | struct rpcrdma_req *); | 472 | struct list_head *); |
| 465 | void (*ro_unmap_safe)(struct rpcrdma_xprt *, | 473 | void (*ro_unmap_safe)(struct rpcrdma_xprt *, |
| 466 | struct rpcrdma_req *, bool); | 474 | struct rpcrdma_req *, bool); |
| 467 | void (*ro_recover_mr)(struct rpcrdma_mw *); | 475 | void (*ro_recover_mr)(struct rpcrdma_mw *); |
| @@ -544,6 +552,34 @@ void rpcrdma_destroy_req(struct rpcrdma_req *); · 76 unmodified lines | |||
| 544 | int rpcrdma_buffer_create(struct rpcrdma_xprt *); | 552 | int rpcrdma_buffer_create(struct rpcrdma_xprt *); |
| 545 | void rpcrdma_buffer_destroy(struct rpcrdma_buffer *); | 553 | void rpcrdma_buffer_destroy(struct rpcrdma_buffer *); |
| 546 | 554 | ||
| 555 | static inline void | ||
| 556 | rpcrdma_insert_req(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req) | ||
| 557 | { | ||
| 558 | spin_lock(&buffers->rb_lock); | ||
| 559 | if (list_empty(&req->rl_list)) | ||
| 560 | list_add_tail(&req->rl_list, &buffers->rb_pending); | ||
| 561 | spin_unlock(&buffers->rb_lock); | ||
| 562 | } | ||
| 563 | |||
| 564 | static inline struct rpcrdma_req * | ||
| 565 | rpcrdma_lookup_req_locked(struct rpcrdma_buffer *buffers, __be32 xid) | ||
| 566 | { | ||
| 567 | struct rpcrdma_req *pos; | ||
| 568 | |||
| 569 | list_for_each_entry(pos, &buffers->rb_pending, rl_list) | ||
| 570 | if (pos->rl_xid == xid) | ||
| 571 | return pos; | ||
| 572 | return NULL; | ||
| 573 | } | ||
| 574 | |||
| 575 | static inline void | ||
| 576 | rpcrdma_remove_req(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req) | ||
| 577 | { | ||
| 578 | spin_lock(&buffers->rb_lock); | ||
| 579 | list_del(&req->rl_list); | ||
| 580 | spin_unlock(&buffers->rb_lock); | ||
| 581 | } | ||
| 582 | |||
| 547 | struct rpcrdma_mw *rpcrdma_get_mw(struct rpcrdma_xprt *); | 583 | struct rpcrdma_mw *rpcrdma_get_mw(struct rpcrdma_xprt *); |
| 548 | void rpcrdma_put_mw(struct rpcrdma_xprt *, struct rpcrdma_mw *); | 584 | void rpcrdma_put_mw(struct rpcrdma_xprt *, struct rpcrdma_mw *); |
| 549 | struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *); | 585 | struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *); |