0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <linux/nfs_fs.h>
0032 #include <linux/vmalloc.h>
0033 #include <linux/module.h>
0034
0035 #include "../internal.h"
0036 #include "../nfs4session.h"
0037 #include "filelayout.h"
0038
0039 #define NFSDBG_FACILITY NFSDBG_PNFS_LD
0040
0041 static unsigned int dataserver_timeo = NFS4_DEF_DS_TIMEO;
0042 static unsigned int dataserver_retrans = NFS4_DEF_DS_RETRANS;
0043
0044 void
0045 nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
0046 {
0047 struct nfs4_pnfs_ds *ds;
0048 int i;
0049
0050 nfs4_print_deviceid(&dsaddr->id_node.deviceid);
0051
0052 for (i = 0; i < dsaddr->ds_num; i++) {
0053 ds = dsaddr->ds_list[i];
0054 if (ds != NULL)
0055 nfs4_pnfs_ds_put(ds);
0056 }
0057 kfree(dsaddr->stripe_indices);
0058 kfree_rcu(dsaddr, id_node.rcu);
0059 }
0060
0061
0062 struct nfs4_file_layout_dsaddr *
0063 nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
0064 gfp_t gfp_flags)
0065 {
0066 int i;
0067 u32 cnt, num;
0068 u8 *indexp;
0069 __be32 *p;
0070 u8 *stripe_indices;
0071 u8 max_stripe_index;
0072 struct nfs4_file_layout_dsaddr *dsaddr = NULL;
0073 struct xdr_stream stream;
0074 struct xdr_buf buf;
0075 struct page *scratch;
0076 struct list_head dsaddrs;
0077 struct nfs4_pnfs_ds_addr *da;
0078
0079
0080 scratch = alloc_page(gfp_flags);
0081 if (!scratch)
0082 goto out_err;
0083
0084 xdr_init_decode_pages(&stream, &buf, pdev->pages, pdev->pglen);
0085 xdr_set_scratch_page(&stream, scratch);
0086
0087
0088 p = xdr_inline_decode(&stream, 4);
0089 if (unlikely(!p))
0090 goto out_err_free_scratch;
0091
0092 cnt = be32_to_cpup(p);
0093 dprintk("%s stripe count %d\n", __func__, cnt);
0094 if (cnt > NFS4_PNFS_MAX_STRIPE_CNT) {
0095 printk(KERN_WARNING "NFS: %s: stripe count %d greater than "
0096 "supported maximum %d\n", __func__,
0097 cnt, NFS4_PNFS_MAX_STRIPE_CNT);
0098 goto out_err_free_scratch;
0099 }
0100
0101
0102 stripe_indices = kcalloc(cnt, sizeof(u8), gfp_flags);
0103 if (!stripe_indices)
0104 goto out_err_free_scratch;
0105
0106 p = xdr_inline_decode(&stream, cnt << 2);
0107 if (unlikely(!p))
0108 goto out_err_free_stripe_indices;
0109
0110 indexp = &stripe_indices[0];
0111 max_stripe_index = 0;
0112 for (i = 0; i < cnt; i++) {
0113 *indexp = be32_to_cpup(p++);
0114 max_stripe_index = max(max_stripe_index, *indexp);
0115 indexp++;
0116 }
0117
0118
0119 p = xdr_inline_decode(&stream, 4);
0120 if (unlikely(!p))
0121 goto out_err_free_stripe_indices;
0122
0123 num = be32_to_cpup(p);
0124 dprintk("%s ds_num %u\n", __func__, num);
0125 if (num > NFS4_PNFS_MAX_MULTI_CNT) {
0126 printk(KERN_WARNING "NFS: %s: multipath count %d greater than "
0127 "supported maximum %d\n", __func__,
0128 num, NFS4_PNFS_MAX_MULTI_CNT);
0129 goto out_err_free_stripe_indices;
0130 }
0131
0132
0133 if (max_stripe_index >= num) {
0134 printk(KERN_WARNING "NFS: %s: stripe index %u >= num ds %u\n",
0135 __func__, max_stripe_index, num);
0136 goto out_err_free_stripe_indices;
0137 }
0138
0139 dsaddr = kzalloc(struct_size(dsaddr, ds_list, num), gfp_flags);
0140 if (!dsaddr)
0141 goto out_err_free_stripe_indices;
0142
0143 dsaddr->stripe_count = cnt;
0144 dsaddr->stripe_indices = stripe_indices;
0145 stripe_indices = NULL;
0146 dsaddr->ds_num = num;
0147 nfs4_init_deviceid_node(&dsaddr->id_node, server, &pdev->dev_id);
0148
0149 INIT_LIST_HEAD(&dsaddrs);
0150
0151 for (i = 0; i < dsaddr->ds_num; i++) {
0152 int j;
0153 u32 mp_count;
0154
0155 p = xdr_inline_decode(&stream, 4);
0156 if (unlikely(!p))
0157 goto out_err_free_deviceid;
0158
0159 mp_count = be32_to_cpup(p);
0160 for (j = 0; j < mp_count; j++) {
0161 da = nfs4_decode_mp_ds_addr(server->nfs_client->cl_net,
0162 &stream, gfp_flags);
0163 if (da)
0164 list_add_tail(&da->da_node, &dsaddrs);
0165 }
0166 if (list_empty(&dsaddrs)) {
0167 dprintk("%s: no suitable DS addresses found\n",
0168 __func__);
0169 goto out_err_free_deviceid;
0170 }
0171
0172 dsaddr->ds_list[i] = nfs4_pnfs_ds_add(&dsaddrs, gfp_flags);
0173 if (!dsaddr->ds_list[i])
0174 goto out_err_drain_dsaddrs;
0175
0176
0177 while (!list_empty(&dsaddrs)) {
0178 da = list_first_entry(&dsaddrs,
0179 struct nfs4_pnfs_ds_addr,
0180 da_node);
0181 list_del_init(&da->da_node);
0182 kfree(da->da_remotestr);
0183 kfree(da);
0184 }
0185 }
0186
0187 __free_page(scratch);
0188 return dsaddr;
0189
0190 out_err_drain_dsaddrs:
0191 while (!list_empty(&dsaddrs)) {
0192 da = list_first_entry(&dsaddrs, struct nfs4_pnfs_ds_addr,
0193 da_node);
0194 list_del_init(&da->da_node);
0195 kfree(da->da_remotestr);
0196 kfree(da);
0197 }
0198 out_err_free_deviceid:
0199 nfs4_fl_free_deviceid(dsaddr);
0200
0201 goto out_err_free_scratch;
0202 out_err_free_stripe_indices:
0203 kfree(stripe_indices);
0204 out_err_free_scratch:
0205 __free_page(scratch);
0206 out_err:
0207 dprintk("%s ERROR: returning NULL\n", __func__);
0208 return NULL;
0209 }
0210
0211 void
0212 nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
0213 {
0214 nfs4_put_deviceid_node(&dsaddr->id_node);
0215 }
0216
0217
0218
0219
0220
0221 u32
0222 nfs4_fl_calc_j_index(struct pnfs_layout_segment *lseg, loff_t offset)
0223 {
0224 struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
0225 u64 tmp;
0226
0227 tmp = offset - flseg->pattern_offset;
0228 do_div(tmp, flseg->stripe_unit);
0229 tmp += flseg->first_stripe_index;
0230 return do_div(tmp, flseg->dsaddr->stripe_count);
0231 }
0232
0233 u32
0234 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j)
0235 {
0236 return FILELAYOUT_LSEG(lseg)->dsaddr->stripe_indices[j];
0237 }
0238
0239 struct nfs_fh *
0240 nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j)
0241 {
0242 struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
0243 u32 i;
0244
0245 if (flseg->stripe_type == STRIPE_SPARSE) {
0246 if (flseg->num_fh == 1)
0247 i = 0;
0248 else if (flseg->num_fh == 0)
0249
0250 return NULL;
0251 else
0252 i = nfs4_fl_calc_ds_index(lseg, j);
0253 } else
0254 i = j;
0255 return flseg->fh_array[i];
0256 }
0257
0258
0259 struct nfs4_pnfs_ds *
0260 nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
0261 {
0262 struct nfs4_file_layout_dsaddr *dsaddr = FILELAYOUT_LSEG(lseg)->dsaddr;
0263 struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx];
0264 struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
0265 struct nfs4_pnfs_ds *ret = ds;
0266 struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode);
0267 int status;
0268
0269 if (ds == NULL) {
0270 printk(KERN_ERR "NFS: %s: No data server for offset index %d\n",
0271 __func__, ds_idx);
0272 pnfs_generic_mark_devid_invalid(devid);
0273 goto out;
0274 }
0275 smp_rmb();
0276 if (ds->ds_clp)
0277 goto out_test_devid;
0278
0279 status = nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo,
0280 dataserver_retrans, 4,
0281 s->nfs_client->cl_minorversion);
0282 if (status) {
0283 nfs4_mark_deviceid_unavailable(devid);
0284 ret = NULL;
0285 goto out;
0286 }
0287
0288 out_test_devid:
0289 if (ret->ds_clp == NULL ||
0290 filelayout_test_devid_unavailable(devid))
0291 ret = NULL;
0292 out:
0293 return ret;
0294 }
0295
0296 module_param(dataserver_retrans, uint, 0644);
0297 MODULE_PARM_DESC(dataserver_retrans, "The number of times the NFSv4.1 client "
0298 "retries a request before it attempts further "
0299 " recovery action.");
0300 module_param(dataserver_timeo, uint, 0644);
0301 MODULE_PARM_DESC(dataserver_timeo, "The time (in tenths of a second) the "
0302 "NFSv4.1 client waits for a response from a "
0303 " data server before it retries an NFS request.");