Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 1 | /* |
| 2 | * Device operations for the pnfs nfs4 file layout driver. |
| 3 | * |
| 4 | * Copyright (c) 2002 |
| 5 | * The Regents of the University of Michigan |
| 6 | * All Rights Reserved |
| 7 | * |
| 8 | * Dean Hildebrand <dhildebz@umich.edu> |
| 9 | * Garth Goodson <Garth.Goodson@netapp.com> |
| 10 | * |
| 11 | * Permission is granted to use, copy, create derivative works, and |
| 12 | * redistribute this software and such derivative works for any purpose, |
| 13 | * so long as the name of the University of Michigan is not used in |
| 14 | * any advertising or publicity pertaining to the use or distribution |
| 15 | * of this software without specific, written prior authorization. If |
| 16 | * the above copyright notice or any other identification of the |
| 17 | * University of Michigan is included in any copy of any portion of |
| 18 | * this software, then the disclaimer below must also be included. |
| 19 | * |
| 20 | * This software is provided as is, without representation or warranty |
| 21 | * of any kind either express or implied, including without limitation |
| 22 | * the implied warranties of merchantability, fitness for a particular |
| 23 | * purpose, or noninfringement. The Regents of the University of |
| 24 | * Michigan shall not be liable for any damages, including special, |
| 25 | * indirect, incidental, or consequential damages, with respect to any |
| 26 | * claim arising out of or in connection with the use of the software, |
| 27 | * even if it has been or is hereafter advised of the possibility of |
| 28 | * such damages. |
| 29 | */ |
| 30 | |
| 31 | #include <linux/nfs_fs.h> |
| 32 | #include <linux/vmalloc.h> |
Andy Adamson | 98fc685 | 2012-04-27 17:53:45 -0400 | [diff] [blame] | 33 | #include <linux/module.h> |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 34 | |
Tom Haynes | b596872 | 2014-05-12 14:35:52 -0700 | [diff] [blame] | 35 | #include "../internal.h" |
| 36 | #include "../nfs4session.h" |
| 37 | #include "filelayout.h" |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 38 | |
| 39 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD |
| 40 | |
Andy Adamson | 98fc685 | 2012-04-27 17:53:45 -0400 | [diff] [blame] | 41 | static unsigned int dataserver_timeo = NFS4_DEF_DS_TIMEO; |
| 42 | static unsigned int dataserver_retrans = NFS4_DEF_DS_RETRANS; |
| 43 | |
Benny Halevy | 1775bc3 | 2011-05-20 13:47:33 +0200 | [diff] [blame] | 44 | void |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 45 | nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) |
| 46 | { |
| 47 | struct nfs4_pnfs_ds *ds; |
| 48 | int i; |
| 49 | |
Benny Halevy | a1eaecb | 2011-05-19 22:14:47 -0400 | [diff] [blame] | 50 | nfs4_print_deviceid(&dsaddr->id_node.deviceid); |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 51 | |
| 52 | for (i = 0; i < dsaddr->ds_num; i++) { |
| 53 | ds = dsaddr->ds_list[i]; |
Peng Tao | 875ae06 | 2014-05-29 21:06:57 +0800 | [diff] [blame] | 54 | if (ds != NULL) |
| 55 | nfs4_pnfs_ds_put(ds); |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 56 | } |
| 57 | kfree(dsaddr->stripe_indices); |
Trond Myklebust | 84a80f6 | 2015-03-09 15:23:35 -0400 | [diff] [blame] | 58 | kfree_rcu(dsaddr, id_node.rcu); |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 59 | } |
| 60 | |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 61 | /* Decode opaque device data and return the result */ |
Christoph Hellwig | 661373b | 2014-09-02 21:27:57 -0700 | [diff] [blame] | 62 | struct nfs4_file_layout_dsaddr * |
| 63 | nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, |
| 64 | gfp_t gfp_flags) |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 65 | { |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 66 | int i; |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 67 | u32 cnt, num; |
| 68 | u8 *indexp; |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 69 | __be32 *p; |
| 70 | u8 *stripe_indices; |
| 71 | u8 max_stripe_index; |
| 72 | struct nfs4_file_layout_dsaddr *dsaddr = NULL; |
| 73 | struct xdr_stream stream; |
Benny Halevy | f7da7a1 | 2011-05-19 14:16:47 -0400 | [diff] [blame] | 74 | struct xdr_buf buf; |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 75 | struct page *scratch; |
Weston Andros Adamson | 14f9a60 | 2011-05-31 18:48:57 -0400 | [diff] [blame] | 76 | struct list_head dsaddrs; |
| 77 | struct nfs4_pnfs_ds_addr *da; |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 78 | |
| 79 | /* set up xdr stream */ |
Trond Myklebust | a75b9df | 2011-05-11 18:00:51 -0400 | [diff] [blame] | 80 | scratch = alloc_page(gfp_flags); |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 81 | if (!scratch) |
| 82 | goto out_err; |
| 83 | |
Benny Halevy | f7da7a1 | 2011-05-19 14:16:47 -0400 | [diff] [blame] | 84 | xdr_init_decode_pages(&stream, &buf, pdev->pages, pdev->pglen); |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 85 | xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 86 | |
| 87 | /* Get the stripe count (number of stripe index) */ |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 88 | p = xdr_inline_decode(&stream, 4); |
| 89 | if (unlikely(!p)) |
| 90 | goto out_err_free_scratch; |
| 91 | |
| 92 | cnt = be32_to_cpup(p); |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 93 | dprintk("%s stripe count %d\n", __func__, cnt); |
| 94 | if (cnt > NFS4_PNFS_MAX_STRIPE_CNT) { |
Weston Andros Adamson | a030889 | 2012-01-26 13:32:23 -0500 | [diff] [blame] | 95 | printk(KERN_WARNING "NFS: %s: stripe count %d greater than " |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 96 | "supported maximum %d\n", __func__, |
| 97 | cnt, NFS4_PNFS_MAX_STRIPE_CNT); |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 98 | goto out_err_free_scratch; |
| 99 | } |
| 100 | |
| 101 | /* read stripe indices */ |
Trond Myklebust | a75b9df | 2011-05-11 18:00:51 -0400 | [diff] [blame] | 102 | stripe_indices = kcalloc(cnt, sizeof(u8), gfp_flags); |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 103 | if (!stripe_indices) |
| 104 | goto out_err_free_scratch; |
| 105 | |
| 106 | p = xdr_inline_decode(&stream, cnt << 2); |
| 107 | if (unlikely(!p)) |
| 108 | goto out_err_free_stripe_indices; |
| 109 | |
| 110 | indexp = &stripe_indices[0]; |
| 111 | max_stripe_index = 0; |
| 112 | for (i = 0; i < cnt; i++) { |
| 113 | *indexp = be32_to_cpup(p++); |
| 114 | max_stripe_index = max(max_stripe_index, *indexp); |
| 115 | indexp++; |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 116 | } |
| 117 | |
| 118 | /* Check the multipath list count */ |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 119 | p = xdr_inline_decode(&stream, 4); |
| 120 | if (unlikely(!p)) |
| 121 | goto out_err_free_stripe_indices; |
| 122 | |
| 123 | num = be32_to_cpup(p); |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 124 | dprintk("%s ds_num %u\n", __func__, num); |
| 125 | if (num > NFS4_PNFS_MAX_MULTI_CNT) { |
Weston Andros Adamson | a030889 | 2012-01-26 13:32:23 -0500 | [diff] [blame] | 126 | printk(KERN_WARNING "NFS: %s: multipath count %d greater than " |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 127 | "supported maximum %d\n", __func__, |
| 128 | num, NFS4_PNFS_MAX_MULTI_CNT); |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 129 | goto out_err_free_stripe_indices; |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 130 | } |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 131 | |
| 132 | /* validate stripe indices are all < num */ |
| 133 | if (max_stripe_index >= num) { |
Weston Andros Adamson | a030889 | 2012-01-26 13:32:23 -0500 | [diff] [blame] | 134 | printk(KERN_WARNING "NFS: %s: stripe index %u >= num ds %u\n", |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 135 | __func__, max_stripe_index, num); |
| 136 | goto out_err_free_stripe_indices; |
| 137 | } |
| 138 | |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 139 | dsaddr = kzalloc(sizeof(*dsaddr) + |
| 140 | (sizeof(struct nfs4_pnfs_ds *) * (num - 1)), |
Trond Myklebust | a75b9df | 2011-05-11 18:00:51 -0400 | [diff] [blame] | 141 | gfp_flags); |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 142 | if (!dsaddr) |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 143 | goto out_err_free_stripe_indices; |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 144 | |
| 145 | dsaddr->stripe_count = cnt; |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 146 | dsaddr->stripe_indices = stripe_indices; |
| 147 | stripe_indices = NULL; |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 148 | dsaddr->ds_num = num; |
Christoph Hellwig | 661373b | 2014-09-02 21:27:57 -0700 | [diff] [blame] | 149 | nfs4_init_deviceid_node(&dsaddr->id_node, server, &pdev->dev_id); |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 150 | |
Weston Andros Adamson | 14f9a60 | 2011-05-31 18:48:57 -0400 | [diff] [blame] | 151 | INIT_LIST_HEAD(&dsaddrs); |
| 152 | |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 153 | for (i = 0; i < dsaddr->ds_num; i++) { |
| 154 | int j; |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 155 | u32 mp_count; |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 156 | |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 157 | p = xdr_inline_decode(&stream, 4); |
| 158 | if (unlikely(!p)) |
| 159 | goto out_err_free_deviceid; |
| 160 | |
| 161 | mp_count = be32_to_cpup(p); /* multipath count */ |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 162 | for (j = 0; j < mp_count; j++) { |
Peng Tao | 6b7f3cf | 2014-05-29 21:06:59 +0800 | [diff] [blame] | 163 | da = nfs4_decode_mp_ds_addr(server->nfs_client->cl_net, |
| 164 | &stream, gfp_flags); |
Weston Andros Adamson | 14f9a60 | 2011-05-31 18:48:57 -0400 | [diff] [blame] | 165 | if (da) |
| 166 | list_add_tail(&da->da_node, &dsaddrs); |
| 167 | } |
| 168 | if (list_empty(&dsaddrs)) { |
| 169 | dprintk("%s: no suitable DS addresses found\n", |
| 170 | __func__); |
| 171 | goto out_err_free_deviceid; |
| 172 | } |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 173 | |
Weston Andros Adamson | 14f9a60 | 2011-05-31 18:48:57 -0400 | [diff] [blame] | 174 | dsaddr->ds_list[i] = nfs4_pnfs_ds_add(&dsaddrs, gfp_flags); |
| 175 | if (!dsaddr->ds_list[i]) |
| 176 | goto out_err_drain_dsaddrs; |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 177 | |
Weston Andros Adamson | 14f9a60 | 2011-05-31 18:48:57 -0400 | [diff] [blame] | 178 | /* If DS was already in cache, free ds addrs */ |
| 179 | while (!list_empty(&dsaddrs)) { |
| 180 | da = list_first_entry(&dsaddrs, |
| 181 | struct nfs4_pnfs_ds_addr, |
| 182 | da_node); |
| 183 | list_del_init(&da->da_node); |
| 184 | kfree(da->da_remotestr); |
| 185 | kfree(da); |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 186 | } |
| 187 | } |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 188 | |
| 189 | __free_page(scratch); |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 190 | return dsaddr; |
| 191 | |
Weston Andros Adamson | 14f9a60 | 2011-05-31 18:48:57 -0400 | [diff] [blame] | 192 | out_err_drain_dsaddrs: |
| 193 | while (!list_empty(&dsaddrs)) { |
| 194 | da = list_first_entry(&dsaddrs, struct nfs4_pnfs_ds_addr, |
| 195 | da_node); |
| 196 | list_del_init(&da->da_node); |
| 197 | kfree(da->da_remotestr); |
| 198 | kfree(da); |
| 199 | } |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 200 | out_err_free_deviceid: |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 201 | nfs4_fl_free_deviceid(dsaddr); |
Weston Andros Adamson | 35124a0 | 2011-03-24 16:48:21 -0400 | [diff] [blame] | 202 | /* stripe_indicies was part of dsaddr */ |
| 203 | goto out_err_free_scratch; |
| 204 | out_err_free_stripe_indices: |
| 205 | kfree(stripe_indices); |
| 206 | out_err_free_scratch: |
| 207 | __free_page(scratch); |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 208 | out_err: |
| 209 | dprintk("%s ERROR: returning NULL\n", __func__); |
| 210 | return NULL; |
| 211 | } |
| 212 | |
Christoph Hellwig | ea8eecd | 2011-03-01 01:34:21 +0000 | [diff] [blame] | 213 | void |
| 214 | nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 215 | { |
Benny Halevy | 1775bc3 | 2011-05-20 13:47:33 +0200 | [diff] [blame] | 216 | nfs4_put_deviceid_node(&dsaddr->id_node); |
Andy Adamson | 16b374c | 2010-10-20 00:18:04 -0400 | [diff] [blame] | 217 | } |
Fred Isaman | cfe7f41 | 2011-03-01 01:34:18 +0000 | [diff] [blame] | 218 | |
| 219 | /* |
| 220 | * Want res = (offset - layout->pattern_offset)/ layout->stripe_unit |
| 221 | * Then: ((res + fsi) % dsaddr->stripe_count) |
| 222 | */ |
| 223 | u32 |
| 224 | nfs4_fl_calc_j_index(struct pnfs_layout_segment *lseg, loff_t offset) |
| 225 | { |
| 226 | struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg); |
| 227 | u64 tmp; |
| 228 | |
| 229 | tmp = offset - flseg->pattern_offset; |
| 230 | do_div(tmp, flseg->stripe_unit); |
| 231 | tmp += flseg->first_stripe_index; |
| 232 | return do_div(tmp, flseg->dsaddr->stripe_count); |
| 233 | } |
| 234 | |
| 235 | u32 |
| 236 | nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j) |
| 237 | { |
| 238 | return FILELAYOUT_LSEG(lseg)->dsaddr->stripe_indices[j]; |
| 239 | } |
| 240 | |
| 241 | struct nfs_fh * |
| 242 | nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j) |
| 243 | { |
| 244 | struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg); |
| 245 | u32 i; |
| 246 | |
| 247 | if (flseg->stripe_type == STRIPE_SPARSE) { |
| 248 | if (flseg->num_fh == 1) |
| 249 | i = 0; |
| 250 | else if (flseg->num_fh == 0) |
| 251 | /* Use the MDS OPEN fh set in nfs_read_rpcsetup */ |
| 252 | return NULL; |
| 253 | else |
| 254 | i = nfs4_fl_calc_ds_index(lseg, j); |
| 255 | } else |
| 256 | i = j; |
| 257 | return flseg->fh_array[i]; |
| 258 | } |
| 259 | |
Peng Tao | 7405f9e | 2014-05-29 21:06:58 +0800 | [diff] [blame] | 260 | /* Upon return, either ds is connected, or ds is NULL */ |
Fred Isaman | cfe7f41 | 2011-03-01 01:34:18 +0000 | [diff] [blame] | 261 | struct nfs4_pnfs_ds * |
| 262 | nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx) |
| 263 | { |
| 264 | struct nfs4_file_layout_dsaddr *dsaddr = FILELAYOUT_LSEG(lseg)->dsaddr; |
| 265 | struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx]; |
Andy Adamson | 554d458 | 2012-04-27 17:53:42 -0400 | [diff] [blame] | 266 | struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); |
Trond Myklebust | 52b26a3 | 2013-09-26 14:08:36 -0400 | [diff] [blame] | 267 | struct nfs4_pnfs_ds *ret = ds; |
Peng Tao | 7405f9e | 2014-05-29 21:06:58 +0800 | [diff] [blame] | 268 | struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode); |
Fred Isaman | cfe7f41 | 2011-03-01 01:34:18 +0000 | [diff] [blame] | 269 | |
| 270 | if (ds == NULL) { |
Weston Andros Adamson | a030889 | 2012-01-26 13:32:23 -0500 | [diff] [blame] | 271 | printk(KERN_ERR "NFS: %s: No data server for offset index %d\n", |
Fred Isaman | cfe7f41 | 2011-03-01 01:34:18 +0000 | [diff] [blame] | 272 | __func__, ds_idx); |
Tom Haynes | f54bcf2 | 2014-12-11 15:34:59 -0500 | [diff] [blame] | 273 | pnfs_generic_mark_devid_invalid(devid); |
Trond Myklebust | 52b26a3 | 2013-09-26 14:08:36 -0400 | [diff] [blame] | 274 | goto out; |
Fred Isaman | cfe7f41 | 2011-03-01 01:34:18 +0000 | [diff] [blame] | 275 | } |
Trond Myklebust | acd65e5 | 2013-09-26 14:32:56 -0400 | [diff] [blame] | 276 | smp_rmb(); |
Andy Adamson | c23266d | 2013-05-08 16:21:18 -0400 | [diff] [blame] | 277 | if (ds->ds_clp) |
Trond Myklebust | 52b26a3 | 2013-09-26 14:08:36 -0400 | [diff] [blame] | 278 | goto out_test_devid; |
Fred Isaman | cfe7f41 | 2011-03-01 01:34:18 +0000 | [diff] [blame] | 279 | |
Peng Tao | 7405f9e | 2014-05-29 21:06:58 +0800 | [diff] [blame] | 280 | nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo, |
Peng Tao | 30626f9 | 2014-05-30 18:15:58 +0800 | [diff] [blame] | 281 | dataserver_retrans, 4, |
| 282 | s->nfs_client->cl_minorversion, |
Peng Tao | 064172f | 2014-05-29 21:07:00 +0800 | [diff] [blame] | 283 | s->nfs_client->cl_rpcclient->cl_auth->au_flavor); |
Fred Isaman | cfe7f41 | 2011-03-01 01:34:18 +0000 | [diff] [blame] | 284 | |
Trond Myklebust | 52b26a3 | 2013-09-26 14:08:36 -0400 | [diff] [blame] | 285 | out_test_devid: |
| 286 | if (filelayout_test_devid_unavailable(devid)) |
| 287 | ret = NULL; |
| 288 | out: |
| 289 | return ret; |
Fred Isaman | cfe7f41 | 2011-03-01 01:34:18 +0000 | [diff] [blame] | 290 | } |
Andy Adamson | 98fc685 | 2012-04-27 17:53:45 -0400 | [diff] [blame] | 291 | |
| 292 | module_param(dataserver_retrans, uint, 0644); |
| 293 | MODULE_PARM_DESC(dataserver_retrans, "The number of times the NFSv4.1 client " |
| 294 | "retries a request before it attempts further " |
| 295 | " recovery action."); |
| 296 | module_param(dataserver_timeo, uint, 0644); |
| 297 | MODULE_PARM_DESC(dataserver_timeo, "The time (in tenths of a second) the " |
| 298 | "NFSv4.1 client waits for a response from a " |
| 299 | " data server before it retries an NFS request."); |