18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Module for pnfs flexfile layout driver. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2014, Primary Data, Inc. All rights reserved. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Tao Peng <bergwolf@primarydata.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/nfs_fs.h> 118c2ecf20Sopenharmony_ci#include <linux/nfs_mount.h> 128c2ecf20Sopenharmony_ci#include <linux/nfs_page.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/sched/mm.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/sunrpc/metrics.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include "flexfilelayout.h" 198c2ecf20Sopenharmony_ci#include "../nfs4session.h" 208c2ecf20Sopenharmony_ci#include "../nfs4idmap.h" 218c2ecf20Sopenharmony_ci#include "../internal.h" 228c2ecf20Sopenharmony_ci#include "../delegation.h" 238c2ecf20Sopenharmony_ci#include "../nfs4trace.h" 248c2ecf20Sopenharmony_ci#include "../iostat.h" 258c2ecf20Sopenharmony_ci#include "../nfs.h" 268c2ecf20Sopenharmony_ci#include "../nfs42.h" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define NFSDBG_FACILITY NFSDBG_PNFS_LD 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define FF_LAYOUT_POLL_RETRY_MAX (15*HZ) 318c2ecf20Sopenharmony_ci#define FF_LAYOUTRETURN_MAXERR 20 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic unsigned short io_maxretrans; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic const struct pnfs_commit_ops ff_layout_commit_ops; 368c2ecf20Sopenharmony_cistatic void ff_layout_read_record_layoutstats_done(struct rpc_task *task, 378c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr); 388c2ecf20Sopenharmony_cistatic int ff_layout_mirror_prepare_stats(struct pnfs_layout_hdr *lo, 398c2ecf20Sopenharmony_ci struct nfs42_layoutstat_devinfo *devinfo, 408c2ecf20Sopenharmony_ci int dev_limit); 418c2ecf20Sopenharmony_cistatic void ff_layout_encode_ff_layoutupdate(struct xdr_stream *xdr, 428c2ecf20Sopenharmony_ci const struct nfs42_layoutstat_devinfo *devinfo, 438c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic struct pnfs_layout_hdr * 468c2ecf20Sopenharmony_ciff_layout_alloc_layout_hdr(struct inode *inode, gfp_t gfp_flags) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci struct nfs4_flexfile_layout *ffl; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci ffl = kzalloc(sizeof(*ffl), gfp_flags); 518c2ecf20Sopenharmony_ci if (ffl) { 528c2ecf20Sopenharmony_ci pnfs_init_ds_commit_info(&ffl->commit_info); 538c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ffl->error_list); 548c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ffl->mirrors); 558c2ecf20Sopenharmony_ci ffl->last_report_time = ktime_get(); 568c2ecf20Sopenharmony_ci ffl->commit_info.ops = &ff_layout_commit_ops; 578c2ecf20Sopenharmony_ci return &ffl->generic_hdr; 588c2ecf20Sopenharmony_ci } else 598c2ecf20Sopenharmony_ci return NULL; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic void 638c2ecf20Sopenharmony_ciff_layout_free_layout_hdr(struct pnfs_layout_hdr *lo) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci struct nfs4_flexfile_layout *ffl = FF_LAYOUT_FROM_HDR(lo); 668c2ecf20Sopenharmony_ci struct nfs4_ff_layout_ds_err *err, *n; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci list_for_each_entry_safe(err, n, &ffl->error_list, list) { 698c2ecf20Sopenharmony_ci list_del(&err->list); 708c2ecf20Sopenharmony_ci kfree(err); 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci kfree_rcu(ffl, generic_hdr.plh_rcu); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic int decode_pnfs_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci __be32 *p; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, NFS4_STATEID_SIZE); 808c2ecf20Sopenharmony_ci if (unlikely(p == NULL)) 818c2ecf20Sopenharmony_ci return -ENOBUFS; 828c2ecf20Sopenharmony_ci stateid->type = NFS4_PNFS_DS_STATEID_TYPE; 838c2ecf20Sopenharmony_ci memcpy(stateid->data, p, NFS4_STATEID_SIZE); 848c2ecf20Sopenharmony_ci dprintk("%s: stateid id= [%x%x%x%x]\n", __func__, 858c2ecf20Sopenharmony_ci p[0], p[1], p[2], p[3]); 868c2ecf20Sopenharmony_ci return 0; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic int decode_deviceid(struct xdr_stream *xdr, struct nfs4_deviceid *devid) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci __be32 *p; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, NFS4_DEVICEID4_SIZE); 948c2ecf20Sopenharmony_ci if (unlikely(!p)) 958c2ecf20Sopenharmony_ci return -ENOBUFS; 968c2ecf20Sopenharmony_ci memcpy(devid, p, NFS4_DEVICEID4_SIZE); 978c2ecf20Sopenharmony_ci nfs4_print_deviceid(devid); 988c2ecf20Sopenharmony_ci return 0; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic int decode_nfs_fh(struct xdr_stream *xdr, struct nfs_fh *fh) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci __be32 *p; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 4); 1068c2ecf20Sopenharmony_ci if (unlikely(!p)) 1078c2ecf20Sopenharmony_ci return -ENOBUFS; 1088c2ecf20Sopenharmony_ci fh->size = be32_to_cpup(p++); 1098c2ecf20Sopenharmony_ci if (fh->size > NFS_MAXFHSIZE) { 1108c2ecf20Sopenharmony_ci printk(KERN_ERR "NFS flexfiles: Too big fh received %d\n", 1118c2ecf20Sopenharmony_ci fh->size); 1128c2ecf20Sopenharmony_ci return -EOVERFLOW; 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci /* fh.data */ 1158c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, fh->size); 1168c2ecf20Sopenharmony_ci if (unlikely(!p)) 1178c2ecf20Sopenharmony_ci return -ENOBUFS; 1188c2ecf20Sopenharmony_ci memcpy(&fh->data, p, fh->size); 1198c2ecf20Sopenharmony_ci dprintk("%s: fh len %d\n", __func__, fh->size); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci return 0; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci/* 1258c2ecf20Sopenharmony_ci * Currently only stringified uids and gids are accepted. 1268c2ecf20Sopenharmony_ci * I.e., kerberos is not supported to the DSes, so no pricipals. 1278c2ecf20Sopenharmony_ci * 1288c2ecf20Sopenharmony_ci * That means that one common function will suffice, but when 1298c2ecf20Sopenharmony_ci * principals are added, this should be split to accomodate 1308c2ecf20Sopenharmony_ci * calls to both nfs_map_name_to_uid() and nfs_map_group_to_gid(). 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_cistatic int 1338c2ecf20Sopenharmony_cidecode_name(struct xdr_stream *xdr, u32 *id) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci __be32 *p; 1368c2ecf20Sopenharmony_ci int len; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci /* opaque_length(4)*/ 1398c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, 4); 1408c2ecf20Sopenharmony_ci if (unlikely(!p)) 1418c2ecf20Sopenharmony_ci return -ENOBUFS; 1428c2ecf20Sopenharmony_ci len = be32_to_cpup(p++); 1438c2ecf20Sopenharmony_ci if (len < 0) 1448c2ecf20Sopenharmony_ci return -EINVAL; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci dprintk("%s: len %u\n", __func__, len); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci /* opaque body */ 1498c2ecf20Sopenharmony_ci p = xdr_inline_decode(xdr, len); 1508c2ecf20Sopenharmony_ci if (unlikely(!p)) 1518c2ecf20Sopenharmony_ci return -ENOBUFS; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci if (!nfs_map_string_to_numeric((char *)p, len, id)) 1548c2ecf20Sopenharmony_ci return -EINVAL; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci return 0; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic bool ff_mirror_match_fh(const struct nfs4_ff_layout_mirror *m1, 1608c2ecf20Sopenharmony_ci const struct nfs4_ff_layout_mirror *m2) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci int i, j; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci if (m1->fh_versions_cnt != m2->fh_versions_cnt) 1658c2ecf20Sopenharmony_ci return false; 1668c2ecf20Sopenharmony_ci for (i = 0; i < m1->fh_versions_cnt; i++) { 1678c2ecf20Sopenharmony_ci bool found_fh = false; 1688c2ecf20Sopenharmony_ci for (j = 0; j < m2->fh_versions_cnt; j++) { 1698c2ecf20Sopenharmony_ci if (nfs_compare_fh(&m1->fh_versions[i], 1708c2ecf20Sopenharmony_ci &m2->fh_versions[j]) == 0) { 1718c2ecf20Sopenharmony_ci found_fh = true; 1728c2ecf20Sopenharmony_ci break; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci if (!found_fh) 1768c2ecf20Sopenharmony_ci return false; 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci return true; 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic struct nfs4_ff_layout_mirror * 1828c2ecf20Sopenharmony_ciff_layout_add_mirror(struct pnfs_layout_hdr *lo, 1838c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci struct nfs4_flexfile_layout *ff_layout = FF_LAYOUT_FROM_HDR(lo); 1868c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *pos; 1878c2ecf20Sopenharmony_ci struct inode *inode = lo->plh_inode; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci spin_lock(&inode->i_lock); 1908c2ecf20Sopenharmony_ci list_for_each_entry(pos, &ff_layout->mirrors, mirrors) { 1918c2ecf20Sopenharmony_ci if (memcmp(&mirror->devid, &pos->devid, sizeof(pos->devid)) != 0) 1928c2ecf20Sopenharmony_ci continue; 1938c2ecf20Sopenharmony_ci if (!ff_mirror_match_fh(mirror, pos)) 1948c2ecf20Sopenharmony_ci continue; 1958c2ecf20Sopenharmony_ci if (refcount_inc_not_zero(&pos->ref)) { 1968c2ecf20Sopenharmony_ci spin_unlock(&inode->i_lock); 1978c2ecf20Sopenharmony_ci return pos; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci list_add(&mirror->mirrors, &ff_layout->mirrors); 2018c2ecf20Sopenharmony_ci mirror->layout = lo; 2028c2ecf20Sopenharmony_ci spin_unlock(&inode->i_lock); 2038c2ecf20Sopenharmony_ci return mirror; 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic void 2078c2ecf20Sopenharmony_ciff_layout_remove_mirror(struct nfs4_ff_layout_mirror *mirror) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci struct inode *inode; 2108c2ecf20Sopenharmony_ci if (mirror->layout == NULL) 2118c2ecf20Sopenharmony_ci return; 2128c2ecf20Sopenharmony_ci inode = mirror->layout->plh_inode; 2138c2ecf20Sopenharmony_ci spin_lock(&inode->i_lock); 2148c2ecf20Sopenharmony_ci list_del(&mirror->mirrors); 2158c2ecf20Sopenharmony_ci spin_unlock(&inode->i_lock); 2168c2ecf20Sopenharmony_ci mirror->layout = NULL; 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic struct nfs4_ff_layout_mirror *ff_layout_alloc_mirror(gfp_t gfp_flags) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci mirror = kzalloc(sizeof(*mirror), gfp_flags); 2248c2ecf20Sopenharmony_ci if (mirror != NULL) { 2258c2ecf20Sopenharmony_ci spin_lock_init(&mirror->lock); 2268c2ecf20Sopenharmony_ci refcount_set(&mirror->ref, 1); 2278c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&mirror->mirrors); 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci return mirror; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic void ff_layout_free_mirror(struct nfs4_ff_layout_mirror *mirror) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci const struct cred *cred; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci ff_layout_remove_mirror(mirror); 2378c2ecf20Sopenharmony_ci kfree(mirror->fh_versions); 2388c2ecf20Sopenharmony_ci cred = rcu_access_pointer(mirror->ro_cred); 2398c2ecf20Sopenharmony_ci put_cred(cred); 2408c2ecf20Sopenharmony_ci cred = rcu_access_pointer(mirror->rw_cred); 2418c2ecf20Sopenharmony_ci put_cred(cred); 2428c2ecf20Sopenharmony_ci nfs4_ff_layout_put_deviceid(mirror->mirror_ds); 2438c2ecf20Sopenharmony_ci kfree(mirror); 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic void ff_layout_put_mirror(struct nfs4_ff_layout_mirror *mirror) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci if (mirror != NULL && refcount_dec_and_test(&mirror->ref)) 2498c2ecf20Sopenharmony_ci ff_layout_free_mirror(mirror); 2508c2ecf20Sopenharmony_ci} 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_cistatic void ff_layout_free_mirror_array(struct nfs4_ff_layout_segment *fls) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci u32 i; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci for (i = 0; i < fls->mirror_array_cnt; i++) 2578c2ecf20Sopenharmony_ci ff_layout_put_mirror(fls->mirror_array[i]); 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic void _ff_layout_free_lseg(struct nfs4_ff_layout_segment *fls) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci if (fls) { 2638c2ecf20Sopenharmony_ci ff_layout_free_mirror_array(fls); 2648c2ecf20Sopenharmony_ci kfree(fls); 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci} 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cistatic bool 2698c2ecf20Sopenharmony_ciff_lseg_match_mirrors(struct pnfs_layout_segment *l1, 2708c2ecf20Sopenharmony_ci struct pnfs_layout_segment *l2) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci const struct nfs4_ff_layout_segment *fl1 = FF_LAYOUT_LSEG(l1); 2738c2ecf20Sopenharmony_ci const struct nfs4_ff_layout_segment *fl2 = FF_LAYOUT_LSEG(l1); 2748c2ecf20Sopenharmony_ci u32 i; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci if (fl1->mirror_array_cnt != fl2->mirror_array_cnt) 2778c2ecf20Sopenharmony_ci return false; 2788c2ecf20Sopenharmony_ci for (i = 0; i < fl1->mirror_array_cnt; i++) { 2798c2ecf20Sopenharmony_ci if (fl1->mirror_array[i] != fl2->mirror_array[i]) 2808c2ecf20Sopenharmony_ci return false; 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci return true; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic bool 2868c2ecf20Sopenharmony_ciff_lseg_range_is_after(const struct pnfs_layout_range *l1, 2878c2ecf20Sopenharmony_ci const struct pnfs_layout_range *l2) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci u64 end1, end2; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci if (l1->iomode != l2->iomode) 2928c2ecf20Sopenharmony_ci return l1->iomode != IOMODE_READ; 2938c2ecf20Sopenharmony_ci end1 = pnfs_calc_offset_end(l1->offset, l1->length); 2948c2ecf20Sopenharmony_ci end2 = pnfs_calc_offset_end(l2->offset, l2->length); 2958c2ecf20Sopenharmony_ci if (end1 < l2->offset) 2968c2ecf20Sopenharmony_ci return false; 2978c2ecf20Sopenharmony_ci if (end2 < l1->offset) 2988c2ecf20Sopenharmony_ci return true; 2998c2ecf20Sopenharmony_ci return l2->offset <= l1->offset; 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic bool 3038c2ecf20Sopenharmony_ciff_lseg_merge(struct pnfs_layout_segment *new, 3048c2ecf20Sopenharmony_ci struct pnfs_layout_segment *old) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci u64 new_end, old_end; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci if (test_bit(NFS_LSEG_LAYOUTRETURN, &old->pls_flags)) 3098c2ecf20Sopenharmony_ci return false; 3108c2ecf20Sopenharmony_ci if (new->pls_range.iomode != old->pls_range.iomode) 3118c2ecf20Sopenharmony_ci return false; 3128c2ecf20Sopenharmony_ci old_end = pnfs_calc_offset_end(old->pls_range.offset, 3138c2ecf20Sopenharmony_ci old->pls_range.length); 3148c2ecf20Sopenharmony_ci if (old_end < new->pls_range.offset) 3158c2ecf20Sopenharmony_ci return false; 3168c2ecf20Sopenharmony_ci new_end = pnfs_calc_offset_end(new->pls_range.offset, 3178c2ecf20Sopenharmony_ci new->pls_range.length); 3188c2ecf20Sopenharmony_ci if (new_end < old->pls_range.offset) 3198c2ecf20Sopenharmony_ci return false; 3208c2ecf20Sopenharmony_ci if (!ff_lseg_match_mirrors(new, old)) 3218c2ecf20Sopenharmony_ci return false; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci /* Mergeable: copy info from 'old' to 'new' */ 3248c2ecf20Sopenharmony_ci if (new_end < old_end) 3258c2ecf20Sopenharmony_ci new_end = old_end; 3268c2ecf20Sopenharmony_ci if (new->pls_range.offset < old->pls_range.offset) 3278c2ecf20Sopenharmony_ci new->pls_range.offset = old->pls_range.offset; 3288c2ecf20Sopenharmony_ci new->pls_range.length = pnfs_calc_offset_length(new->pls_range.offset, 3298c2ecf20Sopenharmony_ci new_end); 3308c2ecf20Sopenharmony_ci if (test_bit(NFS_LSEG_ROC, &old->pls_flags)) 3318c2ecf20Sopenharmony_ci set_bit(NFS_LSEG_ROC, &new->pls_flags); 3328c2ecf20Sopenharmony_ci return true; 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic void 3368c2ecf20Sopenharmony_ciff_layout_add_lseg(struct pnfs_layout_hdr *lo, 3378c2ecf20Sopenharmony_ci struct pnfs_layout_segment *lseg, 3388c2ecf20Sopenharmony_ci struct list_head *free_me) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci pnfs_generic_layout_insert_lseg(lo, lseg, 3418c2ecf20Sopenharmony_ci ff_lseg_range_is_after, 3428c2ecf20Sopenharmony_ci ff_lseg_merge, 3438c2ecf20Sopenharmony_ci free_me); 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic void ff_layout_sort_mirrors(struct nfs4_ff_layout_segment *fls) 3478c2ecf20Sopenharmony_ci{ 3488c2ecf20Sopenharmony_ci int i, j; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci for (i = 0; i < fls->mirror_array_cnt - 1; i++) { 3518c2ecf20Sopenharmony_ci for (j = i + 1; j < fls->mirror_array_cnt; j++) 3528c2ecf20Sopenharmony_ci if (fls->mirror_array[i]->efficiency < 3538c2ecf20Sopenharmony_ci fls->mirror_array[j]->efficiency) 3548c2ecf20Sopenharmony_ci swap(fls->mirror_array[i], 3558c2ecf20Sopenharmony_ci fls->mirror_array[j]); 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic struct pnfs_layout_segment * 3608c2ecf20Sopenharmony_ciff_layout_alloc_lseg(struct pnfs_layout_hdr *lh, 3618c2ecf20Sopenharmony_ci struct nfs4_layoutget_res *lgr, 3628c2ecf20Sopenharmony_ci gfp_t gfp_flags) 3638c2ecf20Sopenharmony_ci{ 3648c2ecf20Sopenharmony_ci struct pnfs_layout_segment *ret; 3658c2ecf20Sopenharmony_ci struct nfs4_ff_layout_segment *fls = NULL; 3668c2ecf20Sopenharmony_ci struct xdr_stream stream; 3678c2ecf20Sopenharmony_ci struct xdr_buf buf; 3688c2ecf20Sopenharmony_ci struct page *scratch; 3698c2ecf20Sopenharmony_ci u64 stripe_unit; 3708c2ecf20Sopenharmony_ci u32 mirror_array_cnt; 3718c2ecf20Sopenharmony_ci __be32 *p; 3728c2ecf20Sopenharmony_ci int i, rc; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci dprintk("--> %s\n", __func__); 3758c2ecf20Sopenharmony_ci scratch = alloc_page(gfp_flags); 3768c2ecf20Sopenharmony_ci if (!scratch) 3778c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci xdr_init_decode_pages(&stream, &buf, lgr->layoutp->pages, 3808c2ecf20Sopenharmony_ci lgr->layoutp->len); 3818c2ecf20Sopenharmony_ci xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* stripe unit and mirror_array_cnt */ 3848c2ecf20Sopenharmony_ci rc = -EIO; 3858c2ecf20Sopenharmony_ci p = xdr_inline_decode(&stream, 8 + 4); 3868c2ecf20Sopenharmony_ci if (!p) 3878c2ecf20Sopenharmony_ci goto out_err_free; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci p = xdr_decode_hyper(p, &stripe_unit); 3908c2ecf20Sopenharmony_ci mirror_array_cnt = be32_to_cpup(p++); 3918c2ecf20Sopenharmony_ci dprintk("%s: stripe_unit=%llu mirror_array_cnt=%u\n", __func__, 3928c2ecf20Sopenharmony_ci stripe_unit, mirror_array_cnt); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci if (mirror_array_cnt > NFS4_FLEXFILE_LAYOUT_MAX_MIRROR_CNT || 3958c2ecf20Sopenharmony_ci mirror_array_cnt == 0) 3968c2ecf20Sopenharmony_ci goto out_err_free; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci rc = -ENOMEM; 3998c2ecf20Sopenharmony_ci fls = kzalloc(struct_size(fls, mirror_array, mirror_array_cnt), 4008c2ecf20Sopenharmony_ci gfp_flags); 4018c2ecf20Sopenharmony_ci if (!fls) 4028c2ecf20Sopenharmony_ci goto out_err_free; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci fls->mirror_array_cnt = mirror_array_cnt; 4058c2ecf20Sopenharmony_ci fls->stripe_unit = stripe_unit; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci for (i = 0; i < fls->mirror_array_cnt; i++) { 4088c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror; 4098c2ecf20Sopenharmony_ci struct cred *kcred; 4108c2ecf20Sopenharmony_ci const struct cred __rcu *cred; 4118c2ecf20Sopenharmony_ci kuid_t uid; 4128c2ecf20Sopenharmony_ci kgid_t gid; 4138c2ecf20Sopenharmony_ci u32 ds_count, fh_count, id; 4148c2ecf20Sopenharmony_ci int j; 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci rc = -EIO; 4178c2ecf20Sopenharmony_ci p = xdr_inline_decode(&stream, 4); 4188c2ecf20Sopenharmony_ci if (!p) 4198c2ecf20Sopenharmony_ci goto out_err_free; 4208c2ecf20Sopenharmony_ci ds_count = be32_to_cpup(p); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci /* FIXME: allow for striping? */ 4238c2ecf20Sopenharmony_ci if (ds_count != 1) 4248c2ecf20Sopenharmony_ci goto out_err_free; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci fls->mirror_array[i] = ff_layout_alloc_mirror(gfp_flags); 4278c2ecf20Sopenharmony_ci if (fls->mirror_array[i] == NULL) { 4288c2ecf20Sopenharmony_ci rc = -ENOMEM; 4298c2ecf20Sopenharmony_ci goto out_err_free; 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci fls->mirror_array[i]->ds_count = ds_count; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci /* deviceid */ 4358c2ecf20Sopenharmony_ci rc = decode_deviceid(&stream, &fls->mirror_array[i]->devid); 4368c2ecf20Sopenharmony_ci if (rc) 4378c2ecf20Sopenharmony_ci goto out_err_free; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* efficiency */ 4408c2ecf20Sopenharmony_ci rc = -EIO; 4418c2ecf20Sopenharmony_ci p = xdr_inline_decode(&stream, 4); 4428c2ecf20Sopenharmony_ci if (!p) 4438c2ecf20Sopenharmony_ci goto out_err_free; 4448c2ecf20Sopenharmony_ci fls->mirror_array[i]->efficiency = be32_to_cpup(p); 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci /* stateid */ 4478c2ecf20Sopenharmony_ci rc = decode_pnfs_stateid(&stream, &fls->mirror_array[i]->stateid); 4488c2ecf20Sopenharmony_ci if (rc) 4498c2ecf20Sopenharmony_ci goto out_err_free; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci /* fh */ 4528c2ecf20Sopenharmony_ci rc = -EIO; 4538c2ecf20Sopenharmony_ci p = xdr_inline_decode(&stream, 4); 4548c2ecf20Sopenharmony_ci if (!p) 4558c2ecf20Sopenharmony_ci goto out_err_free; 4568c2ecf20Sopenharmony_ci fh_count = be32_to_cpup(p); 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci fls->mirror_array[i]->fh_versions = 4598c2ecf20Sopenharmony_ci kcalloc(fh_count, sizeof(struct nfs_fh), 4608c2ecf20Sopenharmony_ci gfp_flags); 4618c2ecf20Sopenharmony_ci if (fls->mirror_array[i]->fh_versions == NULL) { 4628c2ecf20Sopenharmony_ci rc = -ENOMEM; 4638c2ecf20Sopenharmony_ci goto out_err_free; 4648c2ecf20Sopenharmony_ci } 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci for (j = 0; j < fh_count; j++) { 4678c2ecf20Sopenharmony_ci rc = decode_nfs_fh(&stream, 4688c2ecf20Sopenharmony_ci &fls->mirror_array[i]->fh_versions[j]); 4698c2ecf20Sopenharmony_ci if (rc) 4708c2ecf20Sopenharmony_ci goto out_err_free; 4718c2ecf20Sopenharmony_ci } 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci fls->mirror_array[i]->fh_versions_cnt = fh_count; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci /* user */ 4768c2ecf20Sopenharmony_ci rc = decode_name(&stream, &id); 4778c2ecf20Sopenharmony_ci if (rc) 4788c2ecf20Sopenharmony_ci goto out_err_free; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci uid = make_kuid(&init_user_ns, id); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci /* group */ 4838c2ecf20Sopenharmony_ci rc = decode_name(&stream, &id); 4848c2ecf20Sopenharmony_ci if (rc) 4858c2ecf20Sopenharmony_ci goto out_err_free; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci gid = make_kgid(&init_user_ns, id); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci if (gfp_flags & __GFP_FS) 4908c2ecf20Sopenharmony_ci kcred = prepare_kernel_cred(NULL); 4918c2ecf20Sopenharmony_ci else { 4928c2ecf20Sopenharmony_ci unsigned int nofs_flags = memalloc_nofs_save(); 4938c2ecf20Sopenharmony_ci kcred = prepare_kernel_cred(NULL); 4948c2ecf20Sopenharmony_ci memalloc_nofs_restore(nofs_flags); 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci rc = -ENOMEM; 4978c2ecf20Sopenharmony_ci if (!kcred) 4988c2ecf20Sopenharmony_ci goto out_err_free; 4998c2ecf20Sopenharmony_ci kcred->fsuid = uid; 5008c2ecf20Sopenharmony_ci kcred->fsgid = gid; 5018c2ecf20Sopenharmony_ci cred = RCU_INITIALIZER(kcred); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci if (lgr->range.iomode == IOMODE_READ) 5048c2ecf20Sopenharmony_ci rcu_assign_pointer(fls->mirror_array[i]->ro_cred, cred); 5058c2ecf20Sopenharmony_ci else 5068c2ecf20Sopenharmony_ci rcu_assign_pointer(fls->mirror_array[i]->rw_cred, cred); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci mirror = ff_layout_add_mirror(lh, fls->mirror_array[i]); 5098c2ecf20Sopenharmony_ci if (mirror != fls->mirror_array[i]) { 5108c2ecf20Sopenharmony_ci /* swap cred ptrs so free_mirror will clean up old */ 5118c2ecf20Sopenharmony_ci if (lgr->range.iomode == IOMODE_READ) { 5128c2ecf20Sopenharmony_ci cred = xchg(&mirror->ro_cred, cred); 5138c2ecf20Sopenharmony_ci rcu_assign_pointer(fls->mirror_array[i]->ro_cred, cred); 5148c2ecf20Sopenharmony_ci } else { 5158c2ecf20Sopenharmony_ci cred = xchg(&mirror->rw_cred, cred); 5168c2ecf20Sopenharmony_ci rcu_assign_pointer(fls->mirror_array[i]->rw_cred, cred); 5178c2ecf20Sopenharmony_ci } 5188c2ecf20Sopenharmony_ci ff_layout_free_mirror(fls->mirror_array[i]); 5198c2ecf20Sopenharmony_ci fls->mirror_array[i] = mirror; 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci dprintk("%s: iomode %s uid %u gid %u\n", __func__, 5238c2ecf20Sopenharmony_ci lgr->range.iomode == IOMODE_READ ? "READ" : "RW", 5248c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, uid), 5258c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, gid)); 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci p = xdr_inline_decode(&stream, 4); 5298c2ecf20Sopenharmony_ci if (!p) 5308c2ecf20Sopenharmony_ci goto out_sort_mirrors; 5318c2ecf20Sopenharmony_ci fls->flags = be32_to_cpup(p); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci p = xdr_inline_decode(&stream, 4); 5348c2ecf20Sopenharmony_ci if (!p) 5358c2ecf20Sopenharmony_ci goto out_sort_mirrors; 5368c2ecf20Sopenharmony_ci for (i=0; i < fls->mirror_array_cnt; i++) 5378c2ecf20Sopenharmony_ci fls->mirror_array[i]->report_interval = be32_to_cpup(p); 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ciout_sort_mirrors: 5408c2ecf20Sopenharmony_ci ff_layout_sort_mirrors(fls); 5418c2ecf20Sopenharmony_ci ret = &fls->generic_hdr; 5428c2ecf20Sopenharmony_ci dprintk("<-- %s (success)\n", __func__); 5438c2ecf20Sopenharmony_ciout_free_page: 5448c2ecf20Sopenharmony_ci __free_page(scratch); 5458c2ecf20Sopenharmony_ci return ret; 5468c2ecf20Sopenharmony_ciout_err_free: 5478c2ecf20Sopenharmony_ci _ff_layout_free_lseg(fls); 5488c2ecf20Sopenharmony_ci ret = ERR_PTR(rc); 5498c2ecf20Sopenharmony_ci dprintk("<-- %s (%d)\n", __func__, rc); 5508c2ecf20Sopenharmony_ci goto out_free_page; 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic void 5548c2ecf20Sopenharmony_ciff_layout_free_lseg(struct pnfs_layout_segment *lseg) 5558c2ecf20Sopenharmony_ci{ 5568c2ecf20Sopenharmony_ci struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci dprintk("--> %s\n", __func__); 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci if (lseg->pls_range.iomode == IOMODE_RW) { 5618c2ecf20Sopenharmony_ci struct nfs4_flexfile_layout *ffl; 5628c2ecf20Sopenharmony_ci struct inode *inode; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci ffl = FF_LAYOUT_FROM_HDR(lseg->pls_layout); 5658c2ecf20Sopenharmony_ci inode = ffl->generic_hdr.plh_inode; 5668c2ecf20Sopenharmony_ci spin_lock(&inode->i_lock); 5678c2ecf20Sopenharmony_ci pnfs_generic_ds_cinfo_release_lseg(&ffl->commit_info, lseg); 5688c2ecf20Sopenharmony_ci spin_unlock(&inode->i_lock); 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci _ff_layout_free_lseg(fls); 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_cistatic void 5748c2ecf20Sopenharmony_cinfs4_ff_start_busy_timer(struct nfs4_ff_busy_timer *timer, ktime_t now) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci /* first IO request? */ 5778c2ecf20Sopenharmony_ci if (atomic_inc_return(&timer->n_ops) == 1) { 5788c2ecf20Sopenharmony_ci timer->start_time = now; 5798c2ecf20Sopenharmony_ci } 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_cistatic ktime_t 5838c2ecf20Sopenharmony_cinfs4_ff_end_busy_timer(struct nfs4_ff_busy_timer *timer, ktime_t now) 5848c2ecf20Sopenharmony_ci{ 5858c2ecf20Sopenharmony_ci ktime_t start; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci if (atomic_dec_return(&timer->n_ops) < 0) 5888c2ecf20Sopenharmony_ci WARN_ON_ONCE(1); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci start = timer->start_time; 5918c2ecf20Sopenharmony_ci timer->start_time = now; 5928c2ecf20Sopenharmony_ci return ktime_sub(now, start); 5938c2ecf20Sopenharmony_ci} 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_cistatic bool 5968c2ecf20Sopenharmony_cinfs4_ff_layoutstat_start_io(struct nfs4_ff_layout_mirror *mirror, 5978c2ecf20Sopenharmony_ci struct nfs4_ff_layoutstat *layoutstat, 5988c2ecf20Sopenharmony_ci ktime_t now) 5998c2ecf20Sopenharmony_ci{ 6008c2ecf20Sopenharmony_ci s64 report_interval = FF_LAYOUTSTATS_REPORT_INTERVAL; 6018c2ecf20Sopenharmony_ci struct nfs4_flexfile_layout *ffl = FF_LAYOUT_FROM_HDR(mirror->layout); 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci nfs4_ff_start_busy_timer(&layoutstat->busy_timer, now); 6048c2ecf20Sopenharmony_ci if (!mirror->start_time) 6058c2ecf20Sopenharmony_ci mirror->start_time = now; 6068c2ecf20Sopenharmony_ci if (mirror->report_interval != 0) 6078c2ecf20Sopenharmony_ci report_interval = (s64)mirror->report_interval * 1000LL; 6088c2ecf20Sopenharmony_ci else if (layoutstats_timer != 0) 6098c2ecf20Sopenharmony_ci report_interval = (s64)layoutstats_timer * 1000LL; 6108c2ecf20Sopenharmony_ci if (ktime_to_ms(ktime_sub(now, ffl->last_report_time)) >= 6118c2ecf20Sopenharmony_ci report_interval) { 6128c2ecf20Sopenharmony_ci ffl->last_report_time = now; 6138c2ecf20Sopenharmony_ci return true; 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci return false; 6178c2ecf20Sopenharmony_ci} 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_cistatic void 6208c2ecf20Sopenharmony_cinfs4_ff_layout_stat_io_update_requested(struct nfs4_ff_layoutstat *layoutstat, 6218c2ecf20Sopenharmony_ci __u64 requested) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci struct nfs4_ff_io_stat *iostat = &layoutstat->io_stat; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci iostat->ops_requested++; 6268c2ecf20Sopenharmony_ci iostat->bytes_requested += requested; 6278c2ecf20Sopenharmony_ci} 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_cistatic void 6308c2ecf20Sopenharmony_cinfs4_ff_layout_stat_io_update_completed(struct nfs4_ff_layoutstat *layoutstat, 6318c2ecf20Sopenharmony_ci __u64 requested, 6328c2ecf20Sopenharmony_ci __u64 completed, 6338c2ecf20Sopenharmony_ci ktime_t time_completed, 6348c2ecf20Sopenharmony_ci ktime_t time_started) 6358c2ecf20Sopenharmony_ci{ 6368c2ecf20Sopenharmony_ci struct nfs4_ff_io_stat *iostat = &layoutstat->io_stat; 6378c2ecf20Sopenharmony_ci ktime_t completion_time = ktime_sub(time_completed, time_started); 6388c2ecf20Sopenharmony_ci ktime_t timer; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci iostat->ops_completed++; 6418c2ecf20Sopenharmony_ci iostat->bytes_completed += completed; 6428c2ecf20Sopenharmony_ci iostat->bytes_not_delivered += requested - completed; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci timer = nfs4_ff_end_busy_timer(&layoutstat->busy_timer, time_completed); 6458c2ecf20Sopenharmony_ci iostat->total_busy_time = 6468c2ecf20Sopenharmony_ci ktime_add(iostat->total_busy_time, timer); 6478c2ecf20Sopenharmony_ci iostat->aggregate_completion_time = 6488c2ecf20Sopenharmony_ci ktime_add(iostat->aggregate_completion_time, 6498c2ecf20Sopenharmony_ci completion_time); 6508c2ecf20Sopenharmony_ci} 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_cistatic void 6538c2ecf20Sopenharmony_cinfs4_ff_layout_stat_io_start_read(struct inode *inode, 6548c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror, 6558c2ecf20Sopenharmony_ci __u64 requested, ktime_t now) 6568c2ecf20Sopenharmony_ci{ 6578c2ecf20Sopenharmony_ci bool report; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci spin_lock(&mirror->lock); 6608c2ecf20Sopenharmony_ci report = nfs4_ff_layoutstat_start_io(mirror, &mirror->read_stat, now); 6618c2ecf20Sopenharmony_ci nfs4_ff_layout_stat_io_update_requested(&mirror->read_stat, requested); 6628c2ecf20Sopenharmony_ci set_bit(NFS4_FF_MIRROR_STAT_AVAIL, &mirror->flags); 6638c2ecf20Sopenharmony_ci spin_unlock(&mirror->lock); 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci if (report) 6668c2ecf20Sopenharmony_ci pnfs_report_layoutstat(inode, GFP_KERNEL); 6678c2ecf20Sopenharmony_ci} 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_cistatic void 6708c2ecf20Sopenharmony_cinfs4_ff_layout_stat_io_end_read(struct rpc_task *task, 6718c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror, 6728c2ecf20Sopenharmony_ci __u64 requested, 6738c2ecf20Sopenharmony_ci __u64 completed) 6748c2ecf20Sopenharmony_ci{ 6758c2ecf20Sopenharmony_ci spin_lock(&mirror->lock); 6768c2ecf20Sopenharmony_ci nfs4_ff_layout_stat_io_update_completed(&mirror->read_stat, 6778c2ecf20Sopenharmony_ci requested, completed, 6788c2ecf20Sopenharmony_ci ktime_get(), task->tk_start); 6798c2ecf20Sopenharmony_ci set_bit(NFS4_FF_MIRROR_STAT_AVAIL, &mirror->flags); 6808c2ecf20Sopenharmony_ci spin_unlock(&mirror->lock); 6818c2ecf20Sopenharmony_ci} 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_cistatic void 6848c2ecf20Sopenharmony_cinfs4_ff_layout_stat_io_start_write(struct inode *inode, 6858c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror, 6868c2ecf20Sopenharmony_ci __u64 requested, ktime_t now) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci bool report; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci spin_lock(&mirror->lock); 6918c2ecf20Sopenharmony_ci report = nfs4_ff_layoutstat_start_io(mirror , &mirror->write_stat, now); 6928c2ecf20Sopenharmony_ci nfs4_ff_layout_stat_io_update_requested(&mirror->write_stat, requested); 6938c2ecf20Sopenharmony_ci set_bit(NFS4_FF_MIRROR_STAT_AVAIL, &mirror->flags); 6948c2ecf20Sopenharmony_ci spin_unlock(&mirror->lock); 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci if (report) 6978c2ecf20Sopenharmony_ci pnfs_report_layoutstat(inode, GFP_NOIO); 6988c2ecf20Sopenharmony_ci} 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_cistatic void 7018c2ecf20Sopenharmony_cinfs4_ff_layout_stat_io_end_write(struct rpc_task *task, 7028c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror, 7038c2ecf20Sopenharmony_ci __u64 requested, 7048c2ecf20Sopenharmony_ci __u64 completed, 7058c2ecf20Sopenharmony_ci enum nfs3_stable_how committed) 7068c2ecf20Sopenharmony_ci{ 7078c2ecf20Sopenharmony_ci if (committed == NFS_UNSTABLE) 7088c2ecf20Sopenharmony_ci requested = completed = 0; 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci spin_lock(&mirror->lock); 7118c2ecf20Sopenharmony_ci nfs4_ff_layout_stat_io_update_completed(&mirror->write_stat, 7128c2ecf20Sopenharmony_ci requested, completed, ktime_get(), task->tk_start); 7138c2ecf20Sopenharmony_ci set_bit(NFS4_FF_MIRROR_STAT_AVAIL, &mirror->flags); 7148c2ecf20Sopenharmony_ci spin_unlock(&mirror->lock); 7158c2ecf20Sopenharmony_ci} 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_cistatic void 7188c2ecf20Sopenharmony_ciff_layout_mark_ds_unreachable(struct pnfs_layout_segment *lseg, u32 idx) 7198c2ecf20Sopenharmony_ci{ 7208c2ecf20Sopenharmony_ci struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx); 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci if (devid) 7238c2ecf20Sopenharmony_ci nfs4_mark_deviceid_unavailable(devid); 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_cistatic void 7278c2ecf20Sopenharmony_ciff_layout_mark_ds_reachable(struct pnfs_layout_segment *lseg, u32 idx) 7288c2ecf20Sopenharmony_ci{ 7298c2ecf20Sopenharmony_ci struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx); 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci if (devid) 7328c2ecf20Sopenharmony_ci nfs4_mark_deviceid_available(devid); 7338c2ecf20Sopenharmony_ci} 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_cistatic struct nfs4_pnfs_ds * 7368c2ecf20Sopenharmony_ciff_layout_choose_ds_for_read(struct pnfs_layout_segment *lseg, 7378c2ecf20Sopenharmony_ci u32 start_idx, u32 *best_idx, 7388c2ecf20Sopenharmony_ci bool check_device) 7398c2ecf20Sopenharmony_ci{ 7408c2ecf20Sopenharmony_ci struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg); 7418c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror; 7428c2ecf20Sopenharmony_ci struct nfs4_pnfs_ds *ds; 7438c2ecf20Sopenharmony_ci bool fail_return = false; 7448c2ecf20Sopenharmony_ci u32 idx; 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci /* mirrors are initially sorted by efficiency */ 7478c2ecf20Sopenharmony_ci for (idx = start_idx; idx < fls->mirror_array_cnt; idx++) { 7488c2ecf20Sopenharmony_ci if (idx+1 == fls->mirror_array_cnt) 7498c2ecf20Sopenharmony_ci fail_return = !check_device; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci mirror = FF_LAYOUT_COMP(lseg, idx); 7528c2ecf20Sopenharmony_ci ds = nfs4_ff_layout_prepare_ds(lseg, mirror, fail_return); 7538c2ecf20Sopenharmony_ci if (!ds) 7548c2ecf20Sopenharmony_ci continue; 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci if (check_device && 7578c2ecf20Sopenharmony_ci nfs4_test_deviceid_unavailable(&mirror->mirror_ds->id_node)) 7588c2ecf20Sopenharmony_ci continue; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci *best_idx = idx; 7618c2ecf20Sopenharmony_ci return ds; 7628c2ecf20Sopenharmony_ci } 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci return NULL; 7658c2ecf20Sopenharmony_ci} 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_cistatic struct nfs4_pnfs_ds * 7688c2ecf20Sopenharmony_ciff_layout_choose_any_ds_for_read(struct pnfs_layout_segment *lseg, 7698c2ecf20Sopenharmony_ci u32 start_idx, u32 *best_idx) 7708c2ecf20Sopenharmony_ci{ 7718c2ecf20Sopenharmony_ci return ff_layout_choose_ds_for_read(lseg, start_idx, best_idx, false); 7728c2ecf20Sopenharmony_ci} 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_cistatic struct nfs4_pnfs_ds * 7758c2ecf20Sopenharmony_ciff_layout_choose_valid_ds_for_read(struct pnfs_layout_segment *lseg, 7768c2ecf20Sopenharmony_ci u32 start_idx, u32 *best_idx) 7778c2ecf20Sopenharmony_ci{ 7788c2ecf20Sopenharmony_ci return ff_layout_choose_ds_for_read(lseg, start_idx, best_idx, true); 7798c2ecf20Sopenharmony_ci} 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_cistatic struct nfs4_pnfs_ds * 7828c2ecf20Sopenharmony_ciff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg, 7838c2ecf20Sopenharmony_ci u32 start_idx, u32 *best_idx) 7848c2ecf20Sopenharmony_ci{ 7858c2ecf20Sopenharmony_ci struct nfs4_pnfs_ds *ds; 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci ds = ff_layout_choose_valid_ds_for_read(lseg, start_idx, best_idx); 7888c2ecf20Sopenharmony_ci if (ds) 7898c2ecf20Sopenharmony_ci return ds; 7908c2ecf20Sopenharmony_ci return ff_layout_choose_any_ds_for_read(lseg, start_idx, best_idx); 7918c2ecf20Sopenharmony_ci} 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_cistatic struct nfs4_pnfs_ds * 7948c2ecf20Sopenharmony_ciff_layout_get_ds_for_read(struct nfs_pageio_descriptor *pgio, 7958c2ecf20Sopenharmony_ci u32 *best_idx) 7968c2ecf20Sopenharmony_ci{ 7978c2ecf20Sopenharmony_ci struct pnfs_layout_segment *lseg = pgio->pg_lseg; 7988c2ecf20Sopenharmony_ci struct nfs4_pnfs_ds *ds; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci ds = ff_layout_choose_best_ds_for_read(lseg, pgio->pg_mirror_idx, 8018c2ecf20Sopenharmony_ci best_idx); 8028c2ecf20Sopenharmony_ci if (ds || !pgio->pg_mirror_idx) 8038c2ecf20Sopenharmony_ci return ds; 8048c2ecf20Sopenharmony_ci return ff_layout_choose_best_ds_for_read(lseg, 0, best_idx); 8058c2ecf20Sopenharmony_ci} 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_cistatic void 8088c2ecf20Sopenharmony_ciff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio, 8098c2ecf20Sopenharmony_ci struct nfs_page *req, 8108c2ecf20Sopenharmony_ci bool strict_iomode) 8118c2ecf20Sopenharmony_ci{ 8128c2ecf20Sopenharmony_ci pnfs_put_lseg(pgio->pg_lseg); 8138c2ecf20Sopenharmony_ci pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, 8148c2ecf20Sopenharmony_ci nfs_req_openctx(req), 8158c2ecf20Sopenharmony_ci req_offset(req), 8168c2ecf20Sopenharmony_ci req->wb_bytes, 8178c2ecf20Sopenharmony_ci IOMODE_READ, 8188c2ecf20Sopenharmony_ci strict_iomode, 8198c2ecf20Sopenharmony_ci GFP_KERNEL); 8208c2ecf20Sopenharmony_ci if (IS_ERR(pgio->pg_lseg)) { 8218c2ecf20Sopenharmony_ci pgio->pg_error = PTR_ERR(pgio->pg_lseg); 8228c2ecf20Sopenharmony_ci pgio->pg_lseg = NULL; 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci} 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_cistatic void 8278c2ecf20Sopenharmony_ciff_layout_pg_check_layout(struct nfs_pageio_descriptor *pgio, 8288c2ecf20Sopenharmony_ci struct nfs_page *req) 8298c2ecf20Sopenharmony_ci{ 8308c2ecf20Sopenharmony_ci pnfs_generic_pg_check_layout(pgio); 8318c2ecf20Sopenharmony_ci pnfs_generic_pg_check_range(pgio, req); 8328c2ecf20Sopenharmony_ci} 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_cistatic void 8358c2ecf20Sopenharmony_ciff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio, 8368c2ecf20Sopenharmony_ci struct nfs_page *req) 8378c2ecf20Sopenharmony_ci{ 8388c2ecf20Sopenharmony_ci struct nfs_pgio_mirror *pgm; 8398c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror; 8408c2ecf20Sopenharmony_ci struct nfs4_pnfs_ds *ds; 8418c2ecf20Sopenharmony_ci u32 ds_idx; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ciretry: 8448c2ecf20Sopenharmony_ci ff_layout_pg_check_layout(pgio, req); 8458c2ecf20Sopenharmony_ci /* Use full layout for now */ 8468c2ecf20Sopenharmony_ci if (!pgio->pg_lseg) { 8478c2ecf20Sopenharmony_ci ff_layout_pg_get_read(pgio, req, false); 8488c2ecf20Sopenharmony_ci if (!pgio->pg_lseg) 8498c2ecf20Sopenharmony_ci goto out_nolseg; 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci if (ff_layout_avoid_read_on_rw(pgio->pg_lseg)) { 8528c2ecf20Sopenharmony_ci ff_layout_pg_get_read(pgio, req, true); 8538c2ecf20Sopenharmony_ci if (!pgio->pg_lseg) 8548c2ecf20Sopenharmony_ci goto out_nolseg; 8558c2ecf20Sopenharmony_ci } 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci ds = ff_layout_get_ds_for_read(pgio, &ds_idx); 8588c2ecf20Sopenharmony_ci if (!ds) { 8598c2ecf20Sopenharmony_ci if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg)) 8608c2ecf20Sopenharmony_ci goto out_mds; 8618c2ecf20Sopenharmony_ci pnfs_generic_pg_cleanup(pgio); 8628c2ecf20Sopenharmony_ci /* Sleep for 1 second before retrying */ 8638c2ecf20Sopenharmony_ci ssleep(1); 8648c2ecf20Sopenharmony_ci goto retry; 8658c2ecf20Sopenharmony_ci } 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci mirror = FF_LAYOUT_COMP(pgio->pg_lseg, ds_idx); 8688c2ecf20Sopenharmony_ci pgm = &pgio->pg_mirrors[0]; 8698c2ecf20Sopenharmony_ci pgm->pg_bsize = mirror->mirror_ds->ds_versions[0].rsize; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci pgio->pg_mirror_idx = ds_idx; 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci if (NFS_SERVER(pgio->pg_inode)->flags & 8748c2ecf20Sopenharmony_ci (NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR)) 8758c2ecf20Sopenharmony_ci pgio->pg_maxretrans = io_maxretrans; 8768c2ecf20Sopenharmony_ci return; 8778c2ecf20Sopenharmony_ciout_nolseg: 8788c2ecf20Sopenharmony_ci if (pgio->pg_error < 0) 8798c2ecf20Sopenharmony_ci return; 8808c2ecf20Sopenharmony_ciout_mds: 8818c2ecf20Sopenharmony_ci trace_pnfs_mds_fallback_pg_init_read(pgio->pg_inode, 8828c2ecf20Sopenharmony_ci 0, NFS4_MAX_UINT64, IOMODE_READ, 8838c2ecf20Sopenharmony_ci NFS_I(pgio->pg_inode)->layout, 8848c2ecf20Sopenharmony_ci pgio->pg_lseg); 8858c2ecf20Sopenharmony_ci pgio->pg_maxretrans = 0; 8868c2ecf20Sopenharmony_ci nfs_pageio_reset_read_mds(pgio); 8878c2ecf20Sopenharmony_ci} 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_cistatic void 8908c2ecf20Sopenharmony_ciff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio, 8918c2ecf20Sopenharmony_ci struct nfs_page *req) 8928c2ecf20Sopenharmony_ci{ 8938c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror; 8948c2ecf20Sopenharmony_ci struct nfs_pgio_mirror *pgm; 8958c2ecf20Sopenharmony_ci struct nfs4_pnfs_ds *ds; 8968c2ecf20Sopenharmony_ci u32 i; 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ciretry: 8998c2ecf20Sopenharmony_ci ff_layout_pg_check_layout(pgio, req); 9008c2ecf20Sopenharmony_ci if (!pgio->pg_lseg) { 9018c2ecf20Sopenharmony_ci pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, 9028c2ecf20Sopenharmony_ci nfs_req_openctx(req), 9038c2ecf20Sopenharmony_ci req_offset(req), 9048c2ecf20Sopenharmony_ci req->wb_bytes, 9058c2ecf20Sopenharmony_ci IOMODE_RW, 9068c2ecf20Sopenharmony_ci false, 9078c2ecf20Sopenharmony_ci GFP_NOFS); 9088c2ecf20Sopenharmony_ci if (IS_ERR(pgio->pg_lseg)) { 9098c2ecf20Sopenharmony_ci pgio->pg_error = PTR_ERR(pgio->pg_lseg); 9108c2ecf20Sopenharmony_ci pgio->pg_lseg = NULL; 9118c2ecf20Sopenharmony_ci return; 9128c2ecf20Sopenharmony_ci } 9138c2ecf20Sopenharmony_ci } 9148c2ecf20Sopenharmony_ci /* If no lseg, fall back to write through mds */ 9158c2ecf20Sopenharmony_ci if (pgio->pg_lseg == NULL) 9168c2ecf20Sopenharmony_ci goto out_mds; 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci /* Use a direct mapping of ds_idx to pgio mirror_idx */ 9198c2ecf20Sopenharmony_ci if (pgio->pg_mirror_count != FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg)) 9208c2ecf20Sopenharmony_ci goto out_eagain; 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci for (i = 0; i < pgio->pg_mirror_count; i++) { 9238c2ecf20Sopenharmony_ci mirror = FF_LAYOUT_COMP(pgio->pg_lseg, i); 9248c2ecf20Sopenharmony_ci ds = nfs4_ff_layout_prepare_ds(pgio->pg_lseg, mirror, true); 9258c2ecf20Sopenharmony_ci if (!ds) { 9268c2ecf20Sopenharmony_ci if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg)) 9278c2ecf20Sopenharmony_ci goto out_mds; 9288c2ecf20Sopenharmony_ci pnfs_generic_pg_cleanup(pgio); 9298c2ecf20Sopenharmony_ci /* Sleep for 1 second before retrying */ 9308c2ecf20Sopenharmony_ci ssleep(1); 9318c2ecf20Sopenharmony_ci goto retry; 9328c2ecf20Sopenharmony_ci } 9338c2ecf20Sopenharmony_ci pgm = &pgio->pg_mirrors[i]; 9348c2ecf20Sopenharmony_ci pgm->pg_bsize = mirror->mirror_ds->ds_versions[0].wsize; 9358c2ecf20Sopenharmony_ci } 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci if (NFS_SERVER(pgio->pg_inode)->flags & 9388c2ecf20Sopenharmony_ci (NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR)) 9398c2ecf20Sopenharmony_ci pgio->pg_maxretrans = io_maxretrans; 9408c2ecf20Sopenharmony_ci return; 9418c2ecf20Sopenharmony_ciout_eagain: 9428c2ecf20Sopenharmony_ci pnfs_generic_pg_cleanup(pgio); 9438c2ecf20Sopenharmony_ci pgio->pg_error = -EAGAIN; 9448c2ecf20Sopenharmony_ci return; 9458c2ecf20Sopenharmony_ciout_mds: 9468c2ecf20Sopenharmony_ci trace_pnfs_mds_fallback_pg_init_write(pgio->pg_inode, 9478c2ecf20Sopenharmony_ci 0, NFS4_MAX_UINT64, IOMODE_RW, 9488c2ecf20Sopenharmony_ci NFS_I(pgio->pg_inode)->layout, 9498c2ecf20Sopenharmony_ci pgio->pg_lseg); 9508c2ecf20Sopenharmony_ci pgio->pg_maxretrans = 0; 9518c2ecf20Sopenharmony_ci nfs_pageio_reset_write_mds(pgio); 9528c2ecf20Sopenharmony_ci pgio->pg_error = -EAGAIN; 9538c2ecf20Sopenharmony_ci} 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_cistatic unsigned int 9568c2ecf20Sopenharmony_ciff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio, 9578c2ecf20Sopenharmony_ci struct nfs_page *req) 9588c2ecf20Sopenharmony_ci{ 9598c2ecf20Sopenharmony_ci if (!pgio->pg_lseg) { 9608c2ecf20Sopenharmony_ci pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, 9618c2ecf20Sopenharmony_ci nfs_req_openctx(req), 9628c2ecf20Sopenharmony_ci req_offset(req), 9638c2ecf20Sopenharmony_ci req->wb_bytes, 9648c2ecf20Sopenharmony_ci IOMODE_RW, 9658c2ecf20Sopenharmony_ci false, 9668c2ecf20Sopenharmony_ci GFP_NOFS); 9678c2ecf20Sopenharmony_ci if (IS_ERR(pgio->pg_lseg)) { 9688c2ecf20Sopenharmony_ci pgio->pg_error = PTR_ERR(pgio->pg_lseg); 9698c2ecf20Sopenharmony_ci pgio->pg_lseg = NULL; 9708c2ecf20Sopenharmony_ci goto out; 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci if (pgio->pg_lseg) 9748c2ecf20Sopenharmony_ci return FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg); 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci trace_pnfs_mds_fallback_pg_get_mirror_count(pgio->pg_inode, 9778c2ecf20Sopenharmony_ci 0, NFS4_MAX_UINT64, IOMODE_RW, 9788c2ecf20Sopenharmony_ci NFS_I(pgio->pg_inode)->layout, 9798c2ecf20Sopenharmony_ci pgio->pg_lseg); 9808c2ecf20Sopenharmony_ci /* no lseg means that pnfs is not in use, so no mirroring here */ 9818c2ecf20Sopenharmony_ci nfs_pageio_reset_write_mds(pgio); 9828c2ecf20Sopenharmony_ciout: 9838c2ecf20Sopenharmony_ci return 1; 9848c2ecf20Sopenharmony_ci} 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_cistatic u32 9878c2ecf20Sopenharmony_ciff_layout_pg_set_mirror_write(struct nfs_pageio_descriptor *desc, u32 idx) 9888c2ecf20Sopenharmony_ci{ 9898c2ecf20Sopenharmony_ci u32 old = desc->pg_mirror_idx; 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci desc->pg_mirror_idx = idx; 9928c2ecf20Sopenharmony_ci return old; 9938c2ecf20Sopenharmony_ci} 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_cistatic struct nfs_pgio_mirror * 9968c2ecf20Sopenharmony_ciff_layout_pg_get_mirror_write(struct nfs_pageio_descriptor *desc, u32 idx) 9978c2ecf20Sopenharmony_ci{ 9988c2ecf20Sopenharmony_ci return &desc->pg_mirrors[idx]; 9998c2ecf20Sopenharmony_ci} 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_cistatic const struct nfs_pageio_ops ff_layout_pg_read_ops = { 10028c2ecf20Sopenharmony_ci .pg_init = ff_layout_pg_init_read, 10038c2ecf20Sopenharmony_ci .pg_test = pnfs_generic_pg_test, 10048c2ecf20Sopenharmony_ci .pg_doio = pnfs_generic_pg_readpages, 10058c2ecf20Sopenharmony_ci .pg_cleanup = pnfs_generic_pg_cleanup, 10068c2ecf20Sopenharmony_ci}; 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_cistatic const struct nfs_pageio_ops ff_layout_pg_write_ops = { 10098c2ecf20Sopenharmony_ci .pg_init = ff_layout_pg_init_write, 10108c2ecf20Sopenharmony_ci .pg_test = pnfs_generic_pg_test, 10118c2ecf20Sopenharmony_ci .pg_doio = pnfs_generic_pg_writepages, 10128c2ecf20Sopenharmony_ci .pg_get_mirror_count = ff_layout_pg_get_mirror_count_write, 10138c2ecf20Sopenharmony_ci .pg_cleanup = pnfs_generic_pg_cleanup, 10148c2ecf20Sopenharmony_ci .pg_get_mirror = ff_layout_pg_get_mirror_write, 10158c2ecf20Sopenharmony_ci .pg_set_mirror = ff_layout_pg_set_mirror_write, 10168c2ecf20Sopenharmony_ci}; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_cistatic void ff_layout_reset_write(struct nfs_pgio_header *hdr, bool retry_pnfs) 10198c2ecf20Sopenharmony_ci{ 10208c2ecf20Sopenharmony_ci struct rpc_task *task = &hdr->task; 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci pnfs_layoutcommit_inode(hdr->inode, false); 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci if (retry_pnfs) { 10258c2ecf20Sopenharmony_ci dprintk("%s Reset task %5u for i/o through pNFS " 10268c2ecf20Sopenharmony_ci "(req %s/%llu, %u bytes @ offset %llu)\n", __func__, 10278c2ecf20Sopenharmony_ci hdr->task.tk_pid, 10288c2ecf20Sopenharmony_ci hdr->inode->i_sb->s_id, 10298c2ecf20Sopenharmony_ci (unsigned long long)NFS_FILEID(hdr->inode), 10308c2ecf20Sopenharmony_ci hdr->args.count, 10318c2ecf20Sopenharmony_ci (unsigned long long)hdr->args.offset); 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci hdr->completion_ops->reschedule_io(hdr); 10348c2ecf20Sopenharmony_ci return; 10358c2ecf20Sopenharmony_ci } 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { 10388c2ecf20Sopenharmony_ci dprintk("%s Reset task %5u for i/o through MDS " 10398c2ecf20Sopenharmony_ci "(req %s/%llu, %u bytes @ offset %llu)\n", __func__, 10408c2ecf20Sopenharmony_ci hdr->task.tk_pid, 10418c2ecf20Sopenharmony_ci hdr->inode->i_sb->s_id, 10428c2ecf20Sopenharmony_ci (unsigned long long)NFS_FILEID(hdr->inode), 10438c2ecf20Sopenharmony_ci hdr->args.count, 10448c2ecf20Sopenharmony_ci (unsigned long long)hdr->args.offset); 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci trace_pnfs_mds_fallback_write_done(hdr->inode, 10478c2ecf20Sopenharmony_ci hdr->args.offset, hdr->args.count, 10488c2ecf20Sopenharmony_ci IOMODE_RW, NFS_I(hdr->inode)->layout, 10498c2ecf20Sopenharmony_ci hdr->lseg); 10508c2ecf20Sopenharmony_ci task->tk_status = pnfs_write_done_resend_to_mds(hdr); 10518c2ecf20Sopenharmony_ci } 10528c2ecf20Sopenharmony_ci} 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_cistatic void ff_layout_resend_pnfs_read(struct nfs_pgio_header *hdr) 10558c2ecf20Sopenharmony_ci{ 10568c2ecf20Sopenharmony_ci u32 idx = hdr->pgio_mirror_idx + 1; 10578c2ecf20Sopenharmony_ci u32 new_idx = 0; 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci if (ff_layout_choose_any_ds_for_read(hdr->lseg, idx, &new_idx)) 10608c2ecf20Sopenharmony_ci ff_layout_send_layouterror(hdr->lseg); 10618c2ecf20Sopenharmony_ci else 10628c2ecf20Sopenharmony_ci pnfs_error_mark_layout_for_return(hdr->inode, hdr->lseg); 10638c2ecf20Sopenharmony_ci pnfs_read_resend_pnfs(hdr, new_idx); 10648c2ecf20Sopenharmony_ci} 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_cistatic void ff_layout_reset_read(struct nfs_pgio_header *hdr) 10678c2ecf20Sopenharmony_ci{ 10688c2ecf20Sopenharmony_ci struct rpc_task *task = &hdr->task; 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci pnfs_layoutcommit_inode(hdr->inode, false); 10718c2ecf20Sopenharmony_ci pnfs_error_mark_layout_for_return(hdr->inode, hdr->lseg); 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { 10748c2ecf20Sopenharmony_ci dprintk("%s Reset task %5u for i/o through MDS " 10758c2ecf20Sopenharmony_ci "(req %s/%llu, %u bytes @ offset %llu)\n", __func__, 10768c2ecf20Sopenharmony_ci hdr->task.tk_pid, 10778c2ecf20Sopenharmony_ci hdr->inode->i_sb->s_id, 10788c2ecf20Sopenharmony_ci (unsigned long long)NFS_FILEID(hdr->inode), 10798c2ecf20Sopenharmony_ci hdr->args.count, 10808c2ecf20Sopenharmony_ci (unsigned long long)hdr->args.offset); 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci trace_pnfs_mds_fallback_read_done(hdr->inode, 10838c2ecf20Sopenharmony_ci hdr->args.offset, hdr->args.count, 10848c2ecf20Sopenharmony_ci IOMODE_READ, NFS_I(hdr->inode)->layout, 10858c2ecf20Sopenharmony_ci hdr->lseg); 10868c2ecf20Sopenharmony_ci task->tk_status = pnfs_read_done_resend_to_mds(hdr); 10878c2ecf20Sopenharmony_ci } 10888c2ecf20Sopenharmony_ci} 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_cistatic int ff_layout_async_handle_error_v4(struct rpc_task *task, 10918c2ecf20Sopenharmony_ci struct nfs4_state *state, 10928c2ecf20Sopenharmony_ci struct nfs_client *clp, 10938c2ecf20Sopenharmony_ci struct pnfs_layout_segment *lseg, 10948c2ecf20Sopenharmony_ci u32 idx) 10958c2ecf20Sopenharmony_ci{ 10968c2ecf20Sopenharmony_ci struct pnfs_layout_hdr *lo = lseg->pls_layout; 10978c2ecf20Sopenharmony_ci struct inode *inode = lo->plh_inode; 10988c2ecf20Sopenharmony_ci struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx); 10998c2ecf20Sopenharmony_ci struct nfs4_slot_table *tbl = &clp->cl_session->fc_slot_table; 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci switch (task->tk_status) { 11028c2ecf20Sopenharmony_ci case -NFS4ERR_BADSESSION: 11038c2ecf20Sopenharmony_ci case -NFS4ERR_BADSLOT: 11048c2ecf20Sopenharmony_ci case -NFS4ERR_BAD_HIGH_SLOT: 11058c2ecf20Sopenharmony_ci case -NFS4ERR_DEADSESSION: 11068c2ecf20Sopenharmony_ci case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: 11078c2ecf20Sopenharmony_ci case -NFS4ERR_SEQ_FALSE_RETRY: 11088c2ecf20Sopenharmony_ci case -NFS4ERR_SEQ_MISORDERED: 11098c2ecf20Sopenharmony_ci dprintk("%s ERROR %d, Reset session. Exchangeid " 11108c2ecf20Sopenharmony_ci "flags 0x%x\n", __func__, task->tk_status, 11118c2ecf20Sopenharmony_ci clp->cl_exchange_flags); 11128c2ecf20Sopenharmony_ci nfs4_schedule_session_recovery(clp->cl_session, task->tk_status); 11138c2ecf20Sopenharmony_ci break; 11148c2ecf20Sopenharmony_ci case -NFS4ERR_DELAY: 11158c2ecf20Sopenharmony_ci case -NFS4ERR_GRACE: 11168c2ecf20Sopenharmony_ci rpc_delay(task, FF_LAYOUT_POLL_RETRY_MAX); 11178c2ecf20Sopenharmony_ci break; 11188c2ecf20Sopenharmony_ci case -NFS4ERR_RETRY_UNCACHED_REP: 11198c2ecf20Sopenharmony_ci break; 11208c2ecf20Sopenharmony_ci /* Invalidate Layout errors */ 11218c2ecf20Sopenharmony_ci case -NFS4ERR_PNFS_NO_LAYOUT: 11228c2ecf20Sopenharmony_ci case -ESTALE: /* mapped NFS4ERR_STALE */ 11238c2ecf20Sopenharmony_ci case -EBADHANDLE: /* mapped NFS4ERR_BADHANDLE */ 11248c2ecf20Sopenharmony_ci case -EISDIR: /* mapped NFS4ERR_ISDIR */ 11258c2ecf20Sopenharmony_ci case -NFS4ERR_FHEXPIRED: 11268c2ecf20Sopenharmony_ci case -NFS4ERR_WRONG_TYPE: 11278c2ecf20Sopenharmony_ci dprintk("%s Invalid layout error %d\n", __func__, 11288c2ecf20Sopenharmony_ci task->tk_status); 11298c2ecf20Sopenharmony_ci /* 11308c2ecf20Sopenharmony_ci * Destroy layout so new i/o will get a new layout. 11318c2ecf20Sopenharmony_ci * Layout will not be destroyed until all current lseg 11328c2ecf20Sopenharmony_ci * references are put. Mark layout as invalid to resend failed 11338c2ecf20Sopenharmony_ci * i/o and all i/o waiting on the slot table to the MDS until 11348c2ecf20Sopenharmony_ci * layout is destroyed and a new valid layout is obtained. 11358c2ecf20Sopenharmony_ci */ 11368c2ecf20Sopenharmony_ci pnfs_destroy_layout(NFS_I(inode)); 11378c2ecf20Sopenharmony_ci rpc_wake_up(&tbl->slot_tbl_waitq); 11388c2ecf20Sopenharmony_ci goto reset; 11398c2ecf20Sopenharmony_ci /* RPC connection errors */ 11408c2ecf20Sopenharmony_ci case -ECONNREFUSED: 11418c2ecf20Sopenharmony_ci case -EHOSTDOWN: 11428c2ecf20Sopenharmony_ci case -EHOSTUNREACH: 11438c2ecf20Sopenharmony_ci case -ENETUNREACH: 11448c2ecf20Sopenharmony_ci case -EIO: 11458c2ecf20Sopenharmony_ci case -ETIMEDOUT: 11468c2ecf20Sopenharmony_ci case -EPIPE: 11478c2ecf20Sopenharmony_ci dprintk("%s DS connection error %d\n", __func__, 11488c2ecf20Sopenharmony_ci task->tk_status); 11498c2ecf20Sopenharmony_ci nfs4_delete_deviceid(devid->ld, devid->nfs_client, 11508c2ecf20Sopenharmony_ci &devid->deviceid); 11518c2ecf20Sopenharmony_ci rpc_wake_up(&tbl->slot_tbl_waitq); 11528c2ecf20Sopenharmony_ci fallthrough; 11538c2ecf20Sopenharmony_ci default: 11548c2ecf20Sopenharmony_ci if (ff_layout_avoid_mds_available_ds(lseg)) 11558c2ecf20Sopenharmony_ci return -NFS4ERR_RESET_TO_PNFS; 11568c2ecf20Sopenharmony_cireset: 11578c2ecf20Sopenharmony_ci dprintk("%s Retry through MDS. Error %d\n", __func__, 11588c2ecf20Sopenharmony_ci task->tk_status); 11598c2ecf20Sopenharmony_ci return -NFS4ERR_RESET_TO_MDS; 11608c2ecf20Sopenharmony_ci } 11618c2ecf20Sopenharmony_ci task->tk_status = 0; 11628c2ecf20Sopenharmony_ci return -EAGAIN; 11638c2ecf20Sopenharmony_ci} 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci/* Retry all errors through either pNFS or MDS except for -EJUKEBOX */ 11668c2ecf20Sopenharmony_cistatic int ff_layout_async_handle_error_v3(struct rpc_task *task, 11678c2ecf20Sopenharmony_ci struct pnfs_layout_segment *lseg, 11688c2ecf20Sopenharmony_ci u32 idx) 11698c2ecf20Sopenharmony_ci{ 11708c2ecf20Sopenharmony_ci struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx); 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci switch (task->tk_status) { 11738c2ecf20Sopenharmony_ci /* File access problems. Don't mark the device as unavailable */ 11748c2ecf20Sopenharmony_ci case -EACCES: 11758c2ecf20Sopenharmony_ci case -ESTALE: 11768c2ecf20Sopenharmony_ci case -EISDIR: 11778c2ecf20Sopenharmony_ci case -EBADHANDLE: 11788c2ecf20Sopenharmony_ci case -ELOOP: 11798c2ecf20Sopenharmony_ci case -ENOSPC: 11808c2ecf20Sopenharmony_ci break; 11818c2ecf20Sopenharmony_ci case -EJUKEBOX: 11828c2ecf20Sopenharmony_ci nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY); 11838c2ecf20Sopenharmony_ci goto out_retry; 11848c2ecf20Sopenharmony_ci default: 11858c2ecf20Sopenharmony_ci dprintk("%s DS connection error %d\n", __func__, 11868c2ecf20Sopenharmony_ci task->tk_status); 11878c2ecf20Sopenharmony_ci nfs4_delete_deviceid(devid->ld, devid->nfs_client, 11888c2ecf20Sopenharmony_ci &devid->deviceid); 11898c2ecf20Sopenharmony_ci } 11908c2ecf20Sopenharmony_ci /* FIXME: Need to prevent infinite looping here. */ 11918c2ecf20Sopenharmony_ci return -NFS4ERR_RESET_TO_PNFS; 11928c2ecf20Sopenharmony_ciout_retry: 11938c2ecf20Sopenharmony_ci task->tk_status = 0; 11948c2ecf20Sopenharmony_ci rpc_restart_call_prepare(task); 11958c2ecf20Sopenharmony_ci rpc_delay(task, NFS_JUKEBOX_RETRY_TIME); 11968c2ecf20Sopenharmony_ci return -EAGAIN; 11978c2ecf20Sopenharmony_ci} 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_cistatic int ff_layout_async_handle_error(struct rpc_task *task, 12008c2ecf20Sopenharmony_ci struct nfs4_state *state, 12018c2ecf20Sopenharmony_ci struct nfs_client *clp, 12028c2ecf20Sopenharmony_ci struct pnfs_layout_segment *lseg, 12038c2ecf20Sopenharmony_ci u32 idx) 12048c2ecf20Sopenharmony_ci{ 12058c2ecf20Sopenharmony_ci int vers = clp->cl_nfs_mod->rpc_vers->number; 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci if (task->tk_status >= 0) { 12088c2ecf20Sopenharmony_ci ff_layout_mark_ds_reachable(lseg, idx); 12098c2ecf20Sopenharmony_ci return 0; 12108c2ecf20Sopenharmony_ci } 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci /* Handle the case of an invalid layout segment */ 12138c2ecf20Sopenharmony_ci if (!pnfs_is_valid_lseg(lseg)) 12148c2ecf20Sopenharmony_ci return -NFS4ERR_RESET_TO_PNFS; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci switch (vers) { 12178c2ecf20Sopenharmony_ci case 3: 12188c2ecf20Sopenharmony_ci return ff_layout_async_handle_error_v3(task, lseg, idx); 12198c2ecf20Sopenharmony_ci case 4: 12208c2ecf20Sopenharmony_ci return ff_layout_async_handle_error_v4(task, state, clp, 12218c2ecf20Sopenharmony_ci lseg, idx); 12228c2ecf20Sopenharmony_ci default: 12238c2ecf20Sopenharmony_ci /* should never happen */ 12248c2ecf20Sopenharmony_ci WARN_ON_ONCE(1); 12258c2ecf20Sopenharmony_ci return 0; 12268c2ecf20Sopenharmony_ci } 12278c2ecf20Sopenharmony_ci} 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_cistatic void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg, 12308c2ecf20Sopenharmony_ci u32 idx, u64 offset, u64 length, 12318c2ecf20Sopenharmony_ci u32 *op_status, int opnum, int error) 12328c2ecf20Sopenharmony_ci{ 12338c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror; 12348c2ecf20Sopenharmony_ci u32 status = *op_status; 12358c2ecf20Sopenharmony_ci int err; 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci if (status == 0) { 12388c2ecf20Sopenharmony_ci switch (error) { 12398c2ecf20Sopenharmony_ci case -ETIMEDOUT: 12408c2ecf20Sopenharmony_ci case -EPFNOSUPPORT: 12418c2ecf20Sopenharmony_ci case -EPROTONOSUPPORT: 12428c2ecf20Sopenharmony_ci case -EOPNOTSUPP: 12438c2ecf20Sopenharmony_ci case -EINVAL: 12448c2ecf20Sopenharmony_ci case -ECONNREFUSED: 12458c2ecf20Sopenharmony_ci case -ECONNRESET: 12468c2ecf20Sopenharmony_ci case -EHOSTDOWN: 12478c2ecf20Sopenharmony_ci case -EHOSTUNREACH: 12488c2ecf20Sopenharmony_ci case -ENETUNREACH: 12498c2ecf20Sopenharmony_ci case -EADDRINUSE: 12508c2ecf20Sopenharmony_ci case -ENOBUFS: 12518c2ecf20Sopenharmony_ci case -EPIPE: 12528c2ecf20Sopenharmony_ci case -EPERM: 12538c2ecf20Sopenharmony_ci *op_status = status = NFS4ERR_NXIO; 12548c2ecf20Sopenharmony_ci break; 12558c2ecf20Sopenharmony_ci case -EACCES: 12568c2ecf20Sopenharmony_ci *op_status = status = NFS4ERR_ACCESS; 12578c2ecf20Sopenharmony_ci break; 12588c2ecf20Sopenharmony_ci default: 12598c2ecf20Sopenharmony_ci return; 12608c2ecf20Sopenharmony_ci } 12618c2ecf20Sopenharmony_ci } 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci mirror = FF_LAYOUT_COMP(lseg, idx); 12648c2ecf20Sopenharmony_ci err = ff_layout_track_ds_error(FF_LAYOUT_FROM_HDR(lseg->pls_layout), 12658c2ecf20Sopenharmony_ci mirror, offset, length, status, opnum, 12668c2ecf20Sopenharmony_ci GFP_NOIO); 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci switch (status) { 12698c2ecf20Sopenharmony_ci case NFS4ERR_DELAY: 12708c2ecf20Sopenharmony_ci case NFS4ERR_GRACE: 12718c2ecf20Sopenharmony_ci break; 12728c2ecf20Sopenharmony_ci case NFS4ERR_NXIO: 12738c2ecf20Sopenharmony_ci ff_layout_mark_ds_unreachable(lseg, idx); 12748c2ecf20Sopenharmony_ci /* 12758c2ecf20Sopenharmony_ci * Don't return the layout if this is a read and we still 12768c2ecf20Sopenharmony_ci * have layouts to try 12778c2ecf20Sopenharmony_ci */ 12788c2ecf20Sopenharmony_ci if (opnum == OP_READ) 12798c2ecf20Sopenharmony_ci break; 12808c2ecf20Sopenharmony_ci fallthrough; 12818c2ecf20Sopenharmony_ci default: 12828c2ecf20Sopenharmony_ci pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode, 12838c2ecf20Sopenharmony_ci lseg); 12848c2ecf20Sopenharmony_ci } 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci dprintk("%s: err %d op %d status %u\n", __func__, err, opnum, status); 12878c2ecf20Sopenharmony_ci} 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci/* NFS_PROTO call done callback routines */ 12908c2ecf20Sopenharmony_cistatic int ff_layout_read_done_cb(struct rpc_task *task, 12918c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr) 12928c2ecf20Sopenharmony_ci{ 12938c2ecf20Sopenharmony_ci int err; 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci if (task->tk_status < 0) { 12968c2ecf20Sopenharmony_ci ff_layout_io_track_ds_error(hdr->lseg, hdr->pgio_mirror_idx, 12978c2ecf20Sopenharmony_ci hdr->args.offset, hdr->args.count, 12988c2ecf20Sopenharmony_ci &hdr->res.op_status, OP_READ, 12998c2ecf20Sopenharmony_ci task->tk_status); 13008c2ecf20Sopenharmony_ci trace_ff_layout_read_error(hdr); 13018c2ecf20Sopenharmony_ci } 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci err = ff_layout_async_handle_error(task, hdr->args.context->state, 13048c2ecf20Sopenharmony_ci hdr->ds_clp, hdr->lseg, 13058c2ecf20Sopenharmony_ci hdr->pgio_mirror_idx); 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci trace_nfs4_pnfs_read(hdr, err); 13088c2ecf20Sopenharmony_ci clear_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags); 13098c2ecf20Sopenharmony_ci clear_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags); 13108c2ecf20Sopenharmony_ci switch (err) { 13118c2ecf20Sopenharmony_ci case -NFS4ERR_RESET_TO_PNFS: 13128c2ecf20Sopenharmony_ci set_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags); 13138c2ecf20Sopenharmony_ci return task->tk_status; 13148c2ecf20Sopenharmony_ci case -NFS4ERR_RESET_TO_MDS: 13158c2ecf20Sopenharmony_ci set_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags); 13168c2ecf20Sopenharmony_ci return task->tk_status; 13178c2ecf20Sopenharmony_ci case -EAGAIN: 13188c2ecf20Sopenharmony_ci goto out_eagain; 13198c2ecf20Sopenharmony_ci } 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci return 0; 13228c2ecf20Sopenharmony_ciout_eagain: 13238c2ecf20Sopenharmony_ci rpc_restart_call_prepare(task); 13248c2ecf20Sopenharmony_ci return -EAGAIN; 13258c2ecf20Sopenharmony_ci} 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_cistatic bool 13288c2ecf20Sopenharmony_ciff_layout_need_layoutcommit(struct pnfs_layout_segment *lseg) 13298c2ecf20Sopenharmony_ci{ 13308c2ecf20Sopenharmony_ci return !(FF_LAYOUT_LSEG(lseg)->flags & FF_FLAGS_NO_LAYOUTCOMMIT); 13318c2ecf20Sopenharmony_ci} 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci/* 13348c2ecf20Sopenharmony_ci * We reference the rpc_cred of the first WRITE that triggers the need for 13358c2ecf20Sopenharmony_ci * a LAYOUTCOMMIT, and use it to send the layoutcommit compound. 13368c2ecf20Sopenharmony_ci * rfc5661 is not clear about which credential should be used. 13378c2ecf20Sopenharmony_ci * 13388c2ecf20Sopenharmony_ci * Flexlayout client should treat DS replied FILE_SYNC as DATA_SYNC, so 13398c2ecf20Sopenharmony_ci * to follow http://www.rfc-editor.org/errata_search.php?rfc=5661&eid=2751 13408c2ecf20Sopenharmony_ci * we always send layoutcommit after DS writes. 13418c2ecf20Sopenharmony_ci */ 13428c2ecf20Sopenharmony_cistatic void 13438c2ecf20Sopenharmony_ciff_layout_set_layoutcommit(struct inode *inode, 13448c2ecf20Sopenharmony_ci struct pnfs_layout_segment *lseg, 13458c2ecf20Sopenharmony_ci loff_t end_offset) 13468c2ecf20Sopenharmony_ci{ 13478c2ecf20Sopenharmony_ci if (!ff_layout_need_layoutcommit(lseg)) 13488c2ecf20Sopenharmony_ci return; 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci pnfs_set_layoutcommit(inode, lseg, end_offset); 13518c2ecf20Sopenharmony_ci dprintk("%s inode %lu pls_end_pos %llu\n", __func__, inode->i_ino, 13528c2ecf20Sopenharmony_ci (unsigned long long) NFS_I(inode)->layout->plh_lwb); 13538c2ecf20Sopenharmony_ci} 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_cistatic void ff_layout_read_record_layoutstats_start(struct rpc_task *task, 13568c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr) 13578c2ecf20Sopenharmony_ci{ 13588c2ecf20Sopenharmony_ci if (test_and_set_bit(NFS_IOHDR_STAT, &hdr->flags)) 13598c2ecf20Sopenharmony_ci return; 13608c2ecf20Sopenharmony_ci nfs4_ff_layout_stat_io_start_read(hdr->inode, 13618c2ecf20Sopenharmony_ci FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx), 13628c2ecf20Sopenharmony_ci hdr->args.count, 13638c2ecf20Sopenharmony_ci task->tk_start); 13648c2ecf20Sopenharmony_ci} 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_cistatic void ff_layout_read_record_layoutstats_done(struct rpc_task *task, 13678c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr) 13688c2ecf20Sopenharmony_ci{ 13698c2ecf20Sopenharmony_ci if (!test_and_clear_bit(NFS_IOHDR_STAT, &hdr->flags)) 13708c2ecf20Sopenharmony_ci return; 13718c2ecf20Sopenharmony_ci nfs4_ff_layout_stat_io_end_read(task, 13728c2ecf20Sopenharmony_ci FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx), 13738c2ecf20Sopenharmony_ci hdr->args.count, 13748c2ecf20Sopenharmony_ci hdr->res.count); 13758c2ecf20Sopenharmony_ci set_bit(NFS_LSEG_LAYOUTRETURN, &hdr->lseg->pls_flags); 13768c2ecf20Sopenharmony_ci} 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_cistatic int ff_layout_read_prepare_common(struct rpc_task *task, 13798c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr) 13808c2ecf20Sopenharmony_ci{ 13818c2ecf20Sopenharmony_ci if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) { 13828c2ecf20Sopenharmony_ci rpc_exit(task, -EIO); 13838c2ecf20Sopenharmony_ci return -EIO; 13848c2ecf20Sopenharmony_ci } 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci ff_layout_read_record_layoutstats_start(task, hdr); 13878c2ecf20Sopenharmony_ci return 0; 13888c2ecf20Sopenharmony_ci} 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci/* 13918c2ecf20Sopenharmony_ci * Call ops for the async read/write cases 13928c2ecf20Sopenharmony_ci * In the case of dense layouts, the offset needs to be reset to its 13938c2ecf20Sopenharmony_ci * original value. 13948c2ecf20Sopenharmony_ci */ 13958c2ecf20Sopenharmony_cistatic void ff_layout_read_prepare_v3(struct rpc_task *task, void *data) 13968c2ecf20Sopenharmony_ci{ 13978c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr = data; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci if (ff_layout_read_prepare_common(task, hdr)) 14008c2ecf20Sopenharmony_ci return; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci rpc_call_start(task); 14038c2ecf20Sopenharmony_ci} 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_cistatic void ff_layout_read_prepare_v4(struct rpc_task *task, void *data) 14068c2ecf20Sopenharmony_ci{ 14078c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr = data; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci if (nfs4_setup_sequence(hdr->ds_clp, 14108c2ecf20Sopenharmony_ci &hdr->args.seq_args, 14118c2ecf20Sopenharmony_ci &hdr->res.seq_res, 14128c2ecf20Sopenharmony_ci task)) 14138c2ecf20Sopenharmony_ci return; 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_ci ff_layout_read_prepare_common(task, hdr); 14168c2ecf20Sopenharmony_ci} 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_cistatic void ff_layout_read_call_done(struct rpc_task *task, void *data) 14198c2ecf20Sopenharmony_ci{ 14208c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr = data; 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status); 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_ci if (test_bit(NFS_IOHDR_REDO, &hdr->flags) && 14258c2ecf20Sopenharmony_ci task->tk_status == 0) { 14268c2ecf20Sopenharmony_ci nfs4_sequence_done(task, &hdr->res.seq_res); 14278c2ecf20Sopenharmony_ci return; 14288c2ecf20Sopenharmony_ci } 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci /* Note this may cause RPC to be resent */ 14318c2ecf20Sopenharmony_ci hdr->mds_ops->rpc_call_done(task, hdr); 14328c2ecf20Sopenharmony_ci} 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_cistatic void ff_layout_read_count_stats(struct rpc_task *task, void *data) 14358c2ecf20Sopenharmony_ci{ 14368c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr = data; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci ff_layout_read_record_layoutstats_done(task, hdr); 14398c2ecf20Sopenharmony_ci rpc_count_iostats_metrics(task, 14408c2ecf20Sopenharmony_ci &NFS_CLIENT(hdr->inode)->cl_metrics[NFSPROC4_CLNT_READ]); 14418c2ecf20Sopenharmony_ci} 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_cistatic void ff_layout_read_release(void *data) 14448c2ecf20Sopenharmony_ci{ 14458c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr = data; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci ff_layout_read_record_layoutstats_done(&hdr->task, hdr); 14488c2ecf20Sopenharmony_ci if (test_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags)) 14498c2ecf20Sopenharmony_ci ff_layout_resend_pnfs_read(hdr); 14508c2ecf20Sopenharmony_ci else if (test_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags)) 14518c2ecf20Sopenharmony_ci ff_layout_reset_read(hdr); 14528c2ecf20Sopenharmony_ci pnfs_generic_rw_release(data); 14538c2ecf20Sopenharmony_ci} 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_cistatic int ff_layout_write_done_cb(struct rpc_task *task, 14578c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr) 14588c2ecf20Sopenharmony_ci{ 14598c2ecf20Sopenharmony_ci loff_t end_offs = 0; 14608c2ecf20Sopenharmony_ci int err; 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci if (task->tk_status < 0) { 14638c2ecf20Sopenharmony_ci ff_layout_io_track_ds_error(hdr->lseg, hdr->pgio_mirror_idx, 14648c2ecf20Sopenharmony_ci hdr->args.offset, hdr->args.count, 14658c2ecf20Sopenharmony_ci &hdr->res.op_status, OP_WRITE, 14668c2ecf20Sopenharmony_ci task->tk_status); 14678c2ecf20Sopenharmony_ci trace_ff_layout_write_error(hdr); 14688c2ecf20Sopenharmony_ci } 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci err = ff_layout_async_handle_error(task, hdr->args.context->state, 14718c2ecf20Sopenharmony_ci hdr->ds_clp, hdr->lseg, 14728c2ecf20Sopenharmony_ci hdr->pgio_mirror_idx); 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci trace_nfs4_pnfs_write(hdr, err); 14758c2ecf20Sopenharmony_ci clear_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags); 14768c2ecf20Sopenharmony_ci clear_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags); 14778c2ecf20Sopenharmony_ci switch (err) { 14788c2ecf20Sopenharmony_ci case -NFS4ERR_RESET_TO_PNFS: 14798c2ecf20Sopenharmony_ci set_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags); 14808c2ecf20Sopenharmony_ci return task->tk_status; 14818c2ecf20Sopenharmony_ci case -NFS4ERR_RESET_TO_MDS: 14828c2ecf20Sopenharmony_ci set_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags); 14838c2ecf20Sopenharmony_ci return task->tk_status; 14848c2ecf20Sopenharmony_ci case -EAGAIN: 14858c2ecf20Sopenharmony_ci return -EAGAIN; 14868c2ecf20Sopenharmony_ci } 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_ci if (hdr->res.verf->committed == NFS_FILE_SYNC || 14898c2ecf20Sopenharmony_ci hdr->res.verf->committed == NFS_DATA_SYNC) 14908c2ecf20Sopenharmony_ci end_offs = hdr->mds_offset + (loff_t)hdr->res.count; 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci /* Note: if the write is unstable, don't set end_offs until commit */ 14938c2ecf20Sopenharmony_ci ff_layout_set_layoutcommit(hdr->inode, hdr->lseg, end_offs); 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_ci /* zero out fattr since we don't care DS attr at all */ 14968c2ecf20Sopenharmony_ci hdr->fattr.valid = 0; 14978c2ecf20Sopenharmony_ci if (task->tk_status >= 0) 14988c2ecf20Sopenharmony_ci nfs_writeback_update_inode(hdr); 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci return 0; 15018c2ecf20Sopenharmony_ci} 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_cistatic int ff_layout_commit_done_cb(struct rpc_task *task, 15048c2ecf20Sopenharmony_ci struct nfs_commit_data *data) 15058c2ecf20Sopenharmony_ci{ 15068c2ecf20Sopenharmony_ci int err; 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci if (task->tk_status < 0) { 15098c2ecf20Sopenharmony_ci ff_layout_io_track_ds_error(data->lseg, data->ds_commit_index, 15108c2ecf20Sopenharmony_ci data->args.offset, data->args.count, 15118c2ecf20Sopenharmony_ci &data->res.op_status, OP_COMMIT, 15128c2ecf20Sopenharmony_ci task->tk_status); 15138c2ecf20Sopenharmony_ci trace_ff_layout_commit_error(data); 15148c2ecf20Sopenharmony_ci } 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci err = ff_layout_async_handle_error(task, NULL, data->ds_clp, 15178c2ecf20Sopenharmony_ci data->lseg, data->ds_commit_index); 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci trace_nfs4_pnfs_commit_ds(data, err); 15208c2ecf20Sopenharmony_ci switch (err) { 15218c2ecf20Sopenharmony_ci case -NFS4ERR_RESET_TO_PNFS: 15228c2ecf20Sopenharmony_ci pnfs_generic_prepare_to_resend_writes(data); 15238c2ecf20Sopenharmony_ci return -EAGAIN; 15248c2ecf20Sopenharmony_ci case -NFS4ERR_RESET_TO_MDS: 15258c2ecf20Sopenharmony_ci pnfs_generic_prepare_to_resend_writes(data); 15268c2ecf20Sopenharmony_ci return -EAGAIN; 15278c2ecf20Sopenharmony_ci case -EAGAIN: 15288c2ecf20Sopenharmony_ci rpc_restart_call_prepare(task); 15298c2ecf20Sopenharmony_ci return -EAGAIN; 15308c2ecf20Sopenharmony_ci } 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci ff_layout_set_layoutcommit(data->inode, data->lseg, data->lwb); 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci return 0; 15358c2ecf20Sopenharmony_ci} 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_cistatic void ff_layout_write_record_layoutstats_start(struct rpc_task *task, 15388c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr) 15398c2ecf20Sopenharmony_ci{ 15408c2ecf20Sopenharmony_ci if (test_and_set_bit(NFS_IOHDR_STAT, &hdr->flags)) 15418c2ecf20Sopenharmony_ci return; 15428c2ecf20Sopenharmony_ci nfs4_ff_layout_stat_io_start_write(hdr->inode, 15438c2ecf20Sopenharmony_ci FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx), 15448c2ecf20Sopenharmony_ci hdr->args.count, 15458c2ecf20Sopenharmony_ci task->tk_start); 15468c2ecf20Sopenharmony_ci} 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_cistatic void ff_layout_write_record_layoutstats_done(struct rpc_task *task, 15498c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr) 15508c2ecf20Sopenharmony_ci{ 15518c2ecf20Sopenharmony_ci if (!test_and_clear_bit(NFS_IOHDR_STAT, &hdr->flags)) 15528c2ecf20Sopenharmony_ci return; 15538c2ecf20Sopenharmony_ci nfs4_ff_layout_stat_io_end_write(task, 15548c2ecf20Sopenharmony_ci FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx), 15558c2ecf20Sopenharmony_ci hdr->args.count, hdr->res.count, 15568c2ecf20Sopenharmony_ci hdr->res.verf->committed); 15578c2ecf20Sopenharmony_ci set_bit(NFS_LSEG_LAYOUTRETURN, &hdr->lseg->pls_flags); 15588c2ecf20Sopenharmony_ci} 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_cistatic int ff_layout_write_prepare_common(struct rpc_task *task, 15618c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr) 15628c2ecf20Sopenharmony_ci{ 15638c2ecf20Sopenharmony_ci if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags))) { 15648c2ecf20Sopenharmony_ci rpc_exit(task, -EIO); 15658c2ecf20Sopenharmony_ci return -EIO; 15668c2ecf20Sopenharmony_ci } 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci ff_layout_write_record_layoutstats_start(task, hdr); 15698c2ecf20Sopenharmony_ci return 0; 15708c2ecf20Sopenharmony_ci} 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_cistatic void ff_layout_write_prepare_v3(struct rpc_task *task, void *data) 15738c2ecf20Sopenharmony_ci{ 15748c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr = data; 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci if (ff_layout_write_prepare_common(task, hdr)) 15778c2ecf20Sopenharmony_ci return; 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci rpc_call_start(task); 15808c2ecf20Sopenharmony_ci} 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_cistatic void ff_layout_write_prepare_v4(struct rpc_task *task, void *data) 15838c2ecf20Sopenharmony_ci{ 15848c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr = data; 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci if (nfs4_setup_sequence(hdr->ds_clp, 15878c2ecf20Sopenharmony_ci &hdr->args.seq_args, 15888c2ecf20Sopenharmony_ci &hdr->res.seq_res, 15898c2ecf20Sopenharmony_ci task)) 15908c2ecf20Sopenharmony_ci return; 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci ff_layout_write_prepare_common(task, hdr); 15938c2ecf20Sopenharmony_ci} 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_cistatic void ff_layout_write_call_done(struct rpc_task *task, void *data) 15968c2ecf20Sopenharmony_ci{ 15978c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr = data; 15988c2ecf20Sopenharmony_ci 15998c2ecf20Sopenharmony_ci if (test_bit(NFS_IOHDR_REDO, &hdr->flags) && 16008c2ecf20Sopenharmony_ci task->tk_status == 0) { 16018c2ecf20Sopenharmony_ci nfs4_sequence_done(task, &hdr->res.seq_res); 16028c2ecf20Sopenharmony_ci return; 16038c2ecf20Sopenharmony_ci } 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci /* Note this may cause RPC to be resent */ 16068c2ecf20Sopenharmony_ci hdr->mds_ops->rpc_call_done(task, hdr); 16078c2ecf20Sopenharmony_ci} 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_cistatic void ff_layout_write_count_stats(struct rpc_task *task, void *data) 16108c2ecf20Sopenharmony_ci{ 16118c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr = data; 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci ff_layout_write_record_layoutstats_done(task, hdr); 16148c2ecf20Sopenharmony_ci rpc_count_iostats_metrics(task, 16158c2ecf20Sopenharmony_ci &NFS_CLIENT(hdr->inode)->cl_metrics[NFSPROC4_CLNT_WRITE]); 16168c2ecf20Sopenharmony_ci} 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_cistatic void ff_layout_write_release(void *data) 16198c2ecf20Sopenharmony_ci{ 16208c2ecf20Sopenharmony_ci struct nfs_pgio_header *hdr = data; 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci ff_layout_write_record_layoutstats_done(&hdr->task, hdr); 16238c2ecf20Sopenharmony_ci if (test_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags)) { 16248c2ecf20Sopenharmony_ci ff_layout_send_layouterror(hdr->lseg); 16258c2ecf20Sopenharmony_ci ff_layout_reset_write(hdr, true); 16268c2ecf20Sopenharmony_ci } else if (test_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags)) 16278c2ecf20Sopenharmony_ci ff_layout_reset_write(hdr, false); 16288c2ecf20Sopenharmony_ci pnfs_generic_rw_release(data); 16298c2ecf20Sopenharmony_ci} 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_cistatic void ff_layout_commit_record_layoutstats_start(struct rpc_task *task, 16328c2ecf20Sopenharmony_ci struct nfs_commit_data *cdata) 16338c2ecf20Sopenharmony_ci{ 16348c2ecf20Sopenharmony_ci if (test_and_set_bit(NFS_IOHDR_STAT, &cdata->flags)) 16358c2ecf20Sopenharmony_ci return; 16368c2ecf20Sopenharmony_ci nfs4_ff_layout_stat_io_start_write(cdata->inode, 16378c2ecf20Sopenharmony_ci FF_LAYOUT_COMP(cdata->lseg, cdata->ds_commit_index), 16388c2ecf20Sopenharmony_ci 0, task->tk_start); 16398c2ecf20Sopenharmony_ci} 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_cistatic void ff_layout_commit_record_layoutstats_done(struct rpc_task *task, 16428c2ecf20Sopenharmony_ci struct nfs_commit_data *cdata) 16438c2ecf20Sopenharmony_ci{ 16448c2ecf20Sopenharmony_ci struct nfs_page *req; 16458c2ecf20Sopenharmony_ci __u64 count = 0; 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci if (!test_and_clear_bit(NFS_IOHDR_STAT, &cdata->flags)) 16488c2ecf20Sopenharmony_ci return; 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci if (task->tk_status == 0) { 16518c2ecf20Sopenharmony_ci list_for_each_entry(req, &cdata->pages, wb_list) 16528c2ecf20Sopenharmony_ci count += req->wb_bytes; 16538c2ecf20Sopenharmony_ci } 16548c2ecf20Sopenharmony_ci nfs4_ff_layout_stat_io_end_write(task, 16558c2ecf20Sopenharmony_ci FF_LAYOUT_COMP(cdata->lseg, cdata->ds_commit_index), 16568c2ecf20Sopenharmony_ci count, count, NFS_FILE_SYNC); 16578c2ecf20Sopenharmony_ci set_bit(NFS_LSEG_LAYOUTRETURN, &cdata->lseg->pls_flags); 16588c2ecf20Sopenharmony_ci} 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_cistatic void ff_layout_commit_prepare_common(struct rpc_task *task, 16618c2ecf20Sopenharmony_ci struct nfs_commit_data *cdata) 16628c2ecf20Sopenharmony_ci{ 16638c2ecf20Sopenharmony_ci ff_layout_commit_record_layoutstats_start(task, cdata); 16648c2ecf20Sopenharmony_ci} 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_cistatic void ff_layout_commit_prepare_v3(struct rpc_task *task, void *data) 16678c2ecf20Sopenharmony_ci{ 16688c2ecf20Sopenharmony_ci ff_layout_commit_prepare_common(task, data); 16698c2ecf20Sopenharmony_ci rpc_call_start(task); 16708c2ecf20Sopenharmony_ci} 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_cistatic void ff_layout_commit_prepare_v4(struct rpc_task *task, void *data) 16738c2ecf20Sopenharmony_ci{ 16748c2ecf20Sopenharmony_ci struct nfs_commit_data *wdata = data; 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_ci if (nfs4_setup_sequence(wdata->ds_clp, 16778c2ecf20Sopenharmony_ci &wdata->args.seq_args, 16788c2ecf20Sopenharmony_ci &wdata->res.seq_res, 16798c2ecf20Sopenharmony_ci task)) 16808c2ecf20Sopenharmony_ci return; 16818c2ecf20Sopenharmony_ci ff_layout_commit_prepare_common(task, data); 16828c2ecf20Sopenharmony_ci} 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_cistatic void ff_layout_commit_done(struct rpc_task *task, void *data) 16858c2ecf20Sopenharmony_ci{ 16868c2ecf20Sopenharmony_ci pnfs_generic_write_commit_done(task, data); 16878c2ecf20Sopenharmony_ci} 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_cistatic void ff_layout_commit_count_stats(struct rpc_task *task, void *data) 16908c2ecf20Sopenharmony_ci{ 16918c2ecf20Sopenharmony_ci struct nfs_commit_data *cdata = data; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci ff_layout_commit_record_layoutstats_done(task, cdata); 16948c2ecf20Sopenharmony_ci rpc_count_iostats_metrics(task, 16958c2ecf20Sopenharmony_ci &NFS_CLIENT(cdata->inode)->cl_metrics[NFSPROC4_CLNT_COMMIT]); 16968c2ecf20Sopenharmony_ci} 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_cistatic void ff_layout_commit_release(void *data) 16998c2ecf20Sopenharmony_ci{ 17008c2ecf20Sopenharmony_ci struct nfs_commit_data *cdata = data; 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci ff_layout_commit_record_layoutstats_done(&cdata->task, cdata); 17038c2ecf20Sopenharmony_ci pnfs_generic_commit_release(data); 17048c2ecf20Sopenharmony_ci} 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_cistatic const struct rpc_call_ops ff_layout_read_call_ops_v3 = { 17078c2ecf20Sopenharmony_ci .rpc_call_prepare = ff_layout_read_prepare_v3, 17088c2ecf20Sopenharmony_ci .rpc_call_done = ff_layout_read_call_done, 17098c2ecf20Sopenharmony_ci .rpc_count_stats = ff_layout_read_count_stats, 17108c2ecf20Sopenharmony_ci .rpc_release = ff_layout_read_release, 17118c2ecf20Sopenharmony_ci}; 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_cistatic const struct rpc_call_ops ff_layout_read_call_ops_v4 = { 17148c2ecf20Sopenharmony_ci .rpc_call_prepare = ff_layout_read_prepare_v4, 17158c2ecf20Sopenharmony_ci .rpc_call_done = ff_layout_read_call_done, 17168c2ecf20Sopenharmony_ci .rpc_count_stats = ff_layout_read_count_stats, 17178c2ecf20Sopenharmony_ci .rpc_release = ff_layout_read_release, 17188c2ecf20Sopenharmony_ci}; 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_cistatic const struct rpc_call_ops ff_layout_write_call_ops_v3 = { 17218c2ecf20Sopenharmony_ci .rpc_call_prepare = ff_layout_write_prepare_v3, 17228c2ecf20Sopenharmony_ci .rpc_call_done = ff_layout_write_call_done, 17238c2ecf20Sopenharmony_ci .rpc_count_stats = ff_layout_write_count_stats, 17248c2ecf20Sopenharmony_ci .rpc_release = ff_layout_write_release, 17258c2ecf20Sopenharmony_ci}; 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_cistatic const struct rpc_call_ops ff_layout_write_call_ops_v4 = { 17288c2ecf20Sopenharmony_ci .rpc_call_prepare = ff_layout_write_prepare_v4, 17298c2ecf20Sopenharmony_ci .rpc_call_done = ff_layout_write_call_done, 17308c2ecf20Sopenharmony_ci .rpc_count_stats = ff_layout_write_count_stats, 17318c2ecf20Sopenharmony_ci .rpc_release = ff_layout_write_release, 17328c2ecf20Sopenharmony_ci}; 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_cistatic const struct rpc_call_ops ff_layout_commit_call_ops_v3 = { 17358c2ecf20Sopenharmony_ci .rpc_call_prepare = ff_layout_commit_prepare_v3, 17368c2ecf20Sopenharmony_ci .rpc_call_done = ff_layout_commit_done, 17378c2ecf20Sopenharmony_ci .rpc_count_stats = ff_layout_commit_count_stats, 17388c2ecf20Sopenharmony_ci .rpc_release = ff_layout_commit_release, 17398c2ecf20Sopenharmony_ci}; 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_cistatic const struct rpc_call_ops ff_layout_commit_call_ops_v4 = { 17428c2ecf20Sopenharmony_ci .rpc_call_prepare = ff_layout_commit_prepare_v4, 17438c2ecf20Sopenharmony_ci .rpc_call_done = ff_layout_commit_done, 17448c2ecf20Sopenharmony_ci .rpc_count_stats = ff_layout_commit_count_stats, 17458c2ecf20Sopenharmony_ci .rpc_release = ff_layout_commit_release, 17468c2ecf20Sopenharmony_ci}; 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_cistatic enum pnfs_try_status 17498c2ecf20Sopenharmony_ciff_layout_read_pagelist(struct nfs_pgio_header *hdr) 17508c2ecf20Sopenharmony_ci{ 17518c2ecf20Sopenharmony_ci struct pnfs_layout_segment *lseg = hdr->lseg; 17528c2ecf20Sopenharmony_ci struct nfs4_pnfs_ds *ds; 17538c2ecf20Sopenharmony_ci struct rpc_clnt *ds_clnt; 17548c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror; 17558c2ecf20Sopenharmony_ci const struct cred *ds_cred; 17568c2ecf20Sopenharmony_ci loff_t offset = hdr->args.offset; 17578c2ecf20Sopenharmony_ci u32 idx = hdr->pgio_mirror_idx; 17588c2ecf20Sopenharmony_ci int vers; 17598c2ecf20Sopenharmony_ci struct nfs_fh *fh; 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci dprintk("--> %s ino %lu pgbase %u req %zu@%llu\n", 17628c2ecf20Sopenharmony_ci __func__, hdr->inode->i_ino, 17638c2ecf20Sopenharmony_ci hdr->args.pgbase, (size_t)hdr->args.count, offset); 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci mirror = FF_LAYOUT_COMP(lseg, idx); 17668c2ecf20Sopenharmony_ci ds = nfs4_ff_layout_prepare_ds(lseg, mirror, false); 17678c2ecf20Sopenharmony_ci if (!ds) 17688c2ecf20Sopenharmony_ci goto out_failed; 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci ds_clnt = nfs4_ff_find_or_create_ds_client(mirror, ds->ds_clp, 17718c2ecf20Sopenharmony_ci hdr->inode); 17728c2ecf20Sopenharmony_ci if (IS_ERR(ds_clnt)) 17738c2ecf20Sopenharmony_ci goto out_failed; 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_ci ds_cred = ff_layout_get_ds_cred(mirror, &lseg->pls_range, hdr->cred); 17768c2ecf20Sopenharmony_ci if (!ds_cred) 17778c2ecf20Sopenharmony_ci goto out_failed; 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ci vers = nfs4_ff_layout_ds_version(mirror); 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_ci dprintk("%s USE DS: %s cl_count %d vers %d\n", __func__, 17828c2ecf20Sopenharmony_ci ds->ds_remotestr, refcount_read(&ds->ds_clp->cl_count), vers); 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci hdr->pgio_done_cb = ff_layout_read_done_cb; 17858c2ecf20Sopenharmony_ci refcount_inc(&ds->ds_clp->cl_count); 17868c2ecf20Sopenharmony_ci hdr->ds_clp = ds->ds_clp; 17878c2ecf20Sopenharmony_ci fh = nfs4_ff_layout_select_ds_fh(mirror); 17888c2ecf20Sopenharmony_ci if (fh) 17898c2ecf20Sopenharmony_ci hdr->args.fh = fh; 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_ci nfs4_ff_layout_select_ds_stateid(mirror, &hdr->args.stateid); 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci /* 17948c2ecf20Sopenharmony_ci * Note that if we ever decide to split across DSes, 17958c2ecf20Sopenharmony_ci * then we may need to handle dense-like offsets. 17968c2ecf20Sopenharmony_ci */ 17978c2ecf20Sopenharmony_ci hdr->args.offset = offset; 17988c2ecf20Sopenharmony_ci hdr->mds_offset = offset; 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci /* Perform an asynchronous read to ds */ 18018c2ecf20Sopenharmony_ci nfs_initiate_pgio(ds_clnt, hdr, ds_cred, ds->ds_clp->rpc_ops, 18028c2ecf20Sopenharmony_ci vers == 3 ? &ff_layout_read_call_ops_v3 : 18038c2ecf20Sopenharmony_ci &ff_layout_read_call_ops_v4, 18048c2ecf20Sopenharmony_ci 0, RPC_TASK_SOFTCONN); 18058c2ecf20Sopenharmony_ci put_cred(ds_cred); 18068c2ecf20Sopenharmony_ci return PNFS_ATTEMPTED; 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_ciout_failed: 18098c2ecf20Sopenharmony_ci if (ff_layout_avoid_mds_available_ds(lseg)) 18108c2ecf20Sopenharmony_ci return PNFS_TRY_AGAIN; 18118c2ecf20Sopenharmony_ci trace_pnfs_mds_fallback_read_pagelist(hdr->inode, 18128c2ecf20Sopenharmony_ci hdr->args.offset, hdr->args.count, 18138c2ecf20Sopenharmony_ci IOMODE_READ, NFS_I(hdr->inode)->layout, lseg); 18148c2ecf20Sopenharmony_ci return PNFS_NOT_ATTEMPTED; 18158c2ecf20Sopenharmony_ci} 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci/* Perform async writes. */ 18188c2ecf20Sopenharmony_cistatic enum pnfs_try_status 18198c2ecf20Sopenharmony_ciff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync) 18208c2ecf20Sopenharmony_ci{ 18218c2ecf20Sopenharmony_ci struct pnfs_layout_segment *lseg = hdr->lseg; 18228c2ecf20Sopenharmony_ci struct nfs4_pnfs_ds *ds; 18238c2ecf20Sopenharmony_ci struct rpc_clnt *ds_clnt; 18248c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror; 18258c2ecf20Sopenharmony_ci const struct cred *ds_cred; 18268c2ecf20Sopenharmony_ci loff_t offset = hdr->args.offset; 18278c2ecf20Sopenharmony_ci int vers; 18288c2ecf20Sopenharmony_ci struct nfs_fh *fh; 18298c2ecf20Sopenharmony_ci u32 idx = hdr->pgio_mirror_idx; 18308c2ecf20Sopenharmony_ci 18318c2ecf20Sopenharmony_ci mirror = FF_LAYOUT_COMP(lseg, idx); 18328c2ecf20Sopenharmony_ci ds = nfs4_ff_layout_prepare_ds(lseg, mirror, true); 18338c2ecf20Sopenharmony_ci if (!ds) 18348c2ecf20Sopenharmony_ci goto out_failed; 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ci ds_clnt = nfs4_ff_find_or_create_ds_client(mirror, ds->ds_clp, 18378c2ecf20Sopenharmony_ci hdr->inode); 18388c2ecf20Sopenharmony_ci if (IS_ERR(ds_clnt)) 18398c2ecf20Sopenharmony_ci goto out_failed; 18408c2ecf20Sopenharmony_ci 18418c2ecf20Sopenharmony_ci ds_cred = ff_layout_get_ds_cred(mirror, &lseg->pls_range, hdr->cred); 18428c2ecf20Sopenharmony_ci if (!ds_cred) 18438c2ecf20Sopenharmony_ci goto out_failed; 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci vers = nfs4_ff_layout_ds_version(mirror); 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_ci dprintk("%s ino %lu sync %d req %zu@%llu DS: %s cl_count %d vers %d\n", 18488c2ecf20Sopenharmony_ci __func__, hdr->inode->i_ino, sync, (size_t) hdr->args.count, 18498c2ecf20Sopenharmony_ci offset, ds->ds_remotestr, refcount_read(&ds->ds_clp->cl_count), 18508c2ecf20Sopenharmony_ci vers); 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci hdr->pgio_done_cb = ff_layout_write_done_cb; 18538c2ecf20Sopenharmony_ci refcount_inc(&ds->ds_clp->cl_count); 18548c2ecf20Sopenharmony_ci hdr->ds_clp = ds->ds_clp; 18558c2ecf20Sopenharmony_ci hdr->ds_commit_idx = idx; 18568c2ecf20Sopenharmony_ci fh = nfs4_ff_layout_select_ds_fh(mirror); 18578c2ecf20Sopenharmony_ci if (fh) 18588c2ecf20Sopenharmony_ci hdr->args.fh = fh; 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_ci nfs4_ff_layout_select_ds_stateid(mirror, &hdr->args.stateid); 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci /* 18638c2ecf20Sopenharmony_ci * Note that if we ever decide to split across DSes, 18648c2ecf20Sopenharmony_ci * then we may need to handle dense-like offsets. 18658c2ecf20Sopenharmony_ci */ 18668c2ecf20Sopenharmony_ci hdr->args.offset = offset; 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci /* Perform an asynchronous write */ 18698c2ecf20Sopenharmony_ci nfs_initiate_pgio(ds_clnt, hdr, ds_cred, ds->ds_clp->rpc_ops, 18708c2ecf20Sopenharmony_ci vers == 3 ? &ff_layout_write_call_ops_v3 : 18718c2ecf20Sopenharmony_ci &ff_layout_write_call_ops_v4, 18728c2ecf20Sopenharmony_ci sync, RPC_TASK_SOFTCONN); 18738c2ecf20Sopenharmony_ci put_cred(ds_cred); 18748c2ecf20Sopenharmony_ci return PNFS_ATTEMPTED; 18758c2ecf20Sopenharmony_ci 18768c2ecf20Sopenharmony_ciout_failed: 18778c2ecf20Sopenharmony_ci if (ff_layout_avoid_mds_available_ds(lseg)) 18788c2ecf20Sopenharmony_ci return PNFS_TRY_AGAIN; 18798c2ecf20Sopenharmony_ci trace_pnfs_mds_fallback_write_pagelist(hdr->inode, 18808c2ecf20Sopenharmony_ci hdr->args.offset, hdr->args.count, 18818c2ecf20Sopenharmony_ci IOMODE_RW, NFS_I(hdr->inode)->layout, lseg); 18828c2ecf20Sopenharmony_ci return PNFS_NOT_ATTEMPTED; 18838c2ecf20Sopenharmony_ci} 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_cistatic u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i) 18868c2ecf20Sopenharmony_ci{ 18878c2ecf20Sopenharmony_ci return i; 18888c2ecf20Sopenharmony_ci} 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_cistatic struct nfs_fh * 18918c2ecf20Sopenharmony_ciselect_ds_fh_from_commit(struct pnfs_layout_segment *lseg, u32 i) 18928c2ecf20Sopenharmony_ci{ 18938c2ecf20Sopenharmony_ci struct nfs4_ff_layout_segment *flseg = FF_LAYOUT_LSEG(lseg); 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci /* FIXME: Assume that there is only one NFS version available 18968c2ecf20Sopenharmony_ci * for the DS. 18978c2ecf20Sopenharmony_ci */ 18988c2ecf20Sopenharmony_ci return &flseg->mirror_array[i]->fh_versions[0]; 18998c2ecf20Sopenharmony_ci} 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_cistatic int ff_layout_initiate_commit(struct nfs_commit_data *data, int how) 19028c2ecf20Sopenharmony_ci{ 19038c2ecf20Sopenharmony_ci struct pnfs_layout_segment *lseg = data->lseg; 19048c2ecf20Sopenharmony_ci struct nfs4_pnfs_ds *ds; 19058c2ecf20Sopenharmony_ci struct rpc_clnt *ds_clnt; 19068c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror; 19078c2ecf20Sopenharmony_ci const struct cred *ds_cred; 19088c2ecf20Sopenharmony_ci u32 idx; 19098c2ecf20Sopenharmony_ci int vers, ret; 19108c2ecf20Sopenharmony_ci struct nfs_fh *fh; 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci if (!lseg || !(pnfs_is_valid_lseg(lseg) || 19138c2ecf20Sopenharmony_ci test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))) 19148c2ecf20Sopenharmony_ci goto out_err; 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); 19178c2ecf20Sopenharmony_ci mirror = FF_LAYOUT_COMP(lseg, idx); 19188c2ecf20Sopenharmony_ci ds = nfs4_ff_layout_prepare_ds(lseg, mirror, true); 19198c2ecf20Sopenharmony_ci if (!ds) 19208c2ecf20Sopenharmony_ci goto out_err; 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci ds_clnt = nfs4_ff_find_or_create_ds_client(mirror, ds->ds_clp, 19238c2ecf20Sopenharmony_ci data->inode); 19248c2ecf20Sopenharmony_ci if (IS_ERR(ds_clnt)) 19258c2ecf20Sopenharmony_ci goto out_err; 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci ds_cred = ff_layout_get_ds_cred(mirror, &lseg->pls_range, data->cred); 19288c2ecf20Sopenharmony_ci if (!ds_cred) 19298c2ecf20Sopenharmony_ci goto out_err; 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci vers = nfs4_ff_layout_ds_version(mirror); 19328c2ecf20Sopenharmony_ci 19338c2ecf20Sopenharmony_ci dprintk("%s ino %lu, how %d cl_count %d vers %d\n", __func__, 19348c2ecf20Sopenharmony_ci data->inode->i_ino, how, refcount_read(&ds->ds_clp->cl_count), 19358c2ecf20Sopenharmony_ci vers); 19368c2ecf20Sopenharmony_ci data->commit_done_cb = ff_layout_commit_done_cb; 19378c2ecf20Sopenharmony_ci data->cred = ds_cred; 19388c2ecf20Sopenharmony_ci refcount_inc(&ds->ds_clp->cl_count); 19398c2ecf20Sopenharmony_ci data->ds_clp = ds->ds_clp; 19408c2ecf20Sopenharmony_ci fh = select_ds_fh_from_commit(lseg, data->ds_commit_index); 19418c2ecf20Sopenharmony_ci if (fh) 19428c2ecf20Sopenharmony_ci data->args.fh = fh; 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci ret = nfs_initiate_commit(ds_clnt, data, ds->ds_clp->rpc_ops, 19458c2ecf20Sopenharmony_ci vers == 3 ? &ff_layout_commit_call_ops_v3 : 19468c2ecf20Sopenharmony_ci &ff_layout_commit_call_ops_v4, 19478c2ecf20Sopenharmony_ci how, RPC_TASK_SOFTCONN); 19488c2ecf20Sopenharmony_ci put_cred(ds_cred); 19498c2ecf20Sopenharmony_ci return ret; 19508c2ecf20Sopenharmony_ciout_err: 19518c2ecf20Sopenharmony_ci pnfs_generic_prepare_to_resend_writes(data); 19528c2ecf20Sopenharmony_ci pnfs_generic_commit_release(data); 19538c2ecf20Sopenharmony_ci return -EAGAIN; 19548c2ecf20Sopenharmony_ci} 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_cistatic int 19578c2ecf20Sopenharmony_ciff_layout_commit_pagelist(struct inode *inode, struct list_head *mds_pages, 19588c2ecf20Sopenharmony_ci int how, struct nfs_commit_info *cinfo) 19598c2ecf20Sopenharmony_ci{ 19608c2ecf20Sopenharmony_ci return pnfs_generic_commit_pagelist(inode, mds_pages, how, cinfo, 19618c2ecf20Sopenharmony_ci ff_layout_initiate_commit); 19628c2ecf20Sopenharmony_ci} 19638c2ecf20Sopenharmony_ci 19648c2ecf20Sopenharmony_cistatic struct pnfs_ds_commit_info * 19658c2ecf20Sopenharmony_ciff_layout_get_ds_info(struct inode *inode) 19668c2ecf20Sopenharmony_ci{ 19678c2ecf20Sopenharmony_ci struct pnfs_layout_hdr *layout = NFS_I(inode)->layout; 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_ci if (layout == NULL) 19708c2ecf20Sopenharmony_ci return NULL; 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_ci return &FF_LAYOUT_FROM_HDR(layout)->commit_info; 19738c2ecf20Sopenharmony_ci} 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_cistatic void 19768c2ecf20Sopenharmony_ciff_layout_setup_ds_info(struct pnfs_ds_commit_info *fl_cinfo, 19778c2ecf20Sopenharmony_ci struct pnfs_layout_segment *lseg) 19788c2ecf20Sopenharmony_ci{ 19798c2ecf20Sopenharmony_ci struct nfs4_ff_layout_segment *flseg = FF_LAYOUT_LSEG(lseg); 19808c2ecf20Sopenharmony_ci struct inode *inode = lseg->pls_layout->plh_inode; 19818c2ecf20Sopenharmony_ci struct pnfs_commit_array *array, *new; 19828c2ecf20Sopenharmony_ci 19838c2ecf20Sopenharmony_ci new = pnfs_alloc_commit_array(flseg->mirror_array_cnt, GFP_NOIO); 19848c2ecf20Sopenharmony_ci if (new) { 19858c2ecf20Sopenharmony_ci spin_lock(&inode->i_lock); 19868c2ecf20Sopenharmony_ci array = pnfs_add_commit_array(fl_cinfo, new, lseg); 19878c2ecf20Sopenharmony_ci spin_unlock(&inode->i_lock); 19888c2ecf20Sopenharmony_ci if (array != new) 19898c2ecf20Sopenharmony_ci pnfs_free_commit_array(new); 19908c2ecf20Sopenharmony_ci } 19918c2ecf20Sopenharmony_ci} 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_cistatic void 19948c2ecf20Sopenharmony_ciff_layout_release_ds_info(struct pnfs_ds_commit_info *fl_cinfo, 19958c2ecf20Sopenharmony_ci struct inode *inode) 19968c2ecf20Sopenharmony_ci{ 19978c2ecf20Sopenharmony_ci spin_lock(&inode->i_lock); 19988c2ecf20Sopenharmony_ci pnfs_generic_ds_cinfo_destroy(fl_cinfo); 19998c2ecf20Sopenharmony_ci spin_unlock(&inode->i_lock); 20008c2ecf20Sopenharmony_ci} 20018c2ecf20Sopenharmony_ci 20028c2ecf20Sopenharmony_cistatic void 20038c2ecf20Sopenharmony_ciff_layout_free_deviceid_node(struct nfs4_deviceid_node *d) 20048c2ecf20Sopenharmony_ci{ 20058c2ecf20Sopenharmony_ci nfs4_ff_layout_free_deviceid(container_of(d, struct nfs4_ff_layout_ds, 20068c2ecf20Sopenharmony_ci id_node)); 20078c2ecf20Sopenharmony_ci} 20088c2ecf20Sopenharmony_ci 20098c2ecf20Sopenharmony_cistatic int ff_layout_encode_ioerr(struct xdr_stream *xdr, 20108c2ecf20Sopenharmony_ci const struct nfs4_layoutreturn_args *args, 20118c2ecf20Sopenharmony_ci const struct nfs4_flexfile_layoutreturn_args *ff_args) 20128c2ecf20Sopenharmony_ci{ 20138c2ecf20Sopenharmony_ci __be32 *start; 20148c2ecf20Sopenharmony_ci 20158c2ecf20Sopenharmony_ci start = xdr_reserve_space(xdr, 4); 20168c2ecf20Sopenharmony_ci if (unlikely(!start)) 20178c2ecf20Sopenharmony_ci return -E2BIG; 20188c2ecf20Sopenharmony_ci 20198c2ecf20Sopenharmony_ci *start = cpu_to_be32(ff_args->num_errors); 20208c2ecf20Sopenharmony_ci /* This assume we always return _ALL_ layouts */ 20218c2ecf20Sopenharmony_ci return ff_layout_encode_ds_ioerr(xdr, &ff_args->errors); 20228c2ecf20Sopenharmony_ci} 20238c2ecf20Sopenharmony_ci 20248c2ecf20Sopenharmony_cistatic void 20258c2ecf20Sopenharmony_ciencode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len) 20268c2ecf20Sopenharmony_ci{ 20278c2ecf20Sopenharmony_ci WARN_ON_ONCE(xdr_stream_encode_opaque_fixed(xdr, buf, len) < 0); 20288c2ecf20Sopenharmony_ci} 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_cistatic void 20318c2ecf20Sopenharmony_ciff_layout_encode_ff_iostat_head(struct xdr_stream *xdr, 20328c2ecf20Sopenharmony_ci const nfs4_stateid *stateid, 20338c2ecf20Sopenharmony_ci const struct nfs42_layoutstat_devinfo *devinfo) 20348c2ecf20Sopenharmony_ci{ 20358c2ecf20Sopenharmony_ci __be32 *p; 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 8 + 8); 20388c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, devinfo->offset); 20398c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, devinfo->length); 20408c2ecf20Sopenharmony_ci encode_opaque_fixed(xdr, stateid->data, NFS4_STATEID_SIZE); 20418c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 4*8); 20428c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, devinfo->read_count); 20438c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, devinfo->read_bytes); 20448c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, devinfo->write_count); 20458c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, devinfo->write_bytes); 20468c2ecf20Sopenharmony_ci encode_opaque_fixed(xdr, devinfo->dev_id.data, NFS4_DEVICEID4_SIZE); 20478c2ecf20Sopenharmony_ci} 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_cistatic void 20508c2ecf20Sopenharmony_ciff_layout_encode_ff_iostat(struct xdr_stream *xdr, 20518c2ecf20Sopenharmony_ci const nfs4_stateid *stateid, 20528c2ecf20Sopenharmony_ci const struct nfs42_layoutstat_devinfo *devinfo) 20538c2ecf20Sopenharmony_ci{ 20548c2ecf20Sopenharmony_ci ff_layout_encode_ff_iostat_head(xdr, stateid, devinfo); 20558c2ecf20Sopenharmony_ci ff_layout_encode_ff_layoutupdate(xdr, devinfo, 20568c2ecf20Sopenharmony_ci devinfo->ld_private.data); 20578c2ecf20Sopenharmony_ci} 20588c2ecf20Sopenharmony_ci 20598c2ecf20Sopenharmony_ci/* report nothing for now */ 20608c2ecf20Sopenharmony_cistatic void ff_layout_encode_iostats_array(struct xdr_stream *xdr, 20618c2ecf20Sopenharmony_ci const struct nfs4_layoutreturn_args *args, 20628c2ecf20Sopenharmony_ci struct nfs4_flexfile_layoutreturn_args *ff_args) 20638c2ecf20Sopenharmony_ci{ 20648c2ecf20Sopenharmony_ci __be32 *p; 20658c2ecf20Sopenharmony_ci int i; 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 4); 20688c2ecf20Sopenharmony_ci *p = cpu_to_be32(ff_args->num_dev); 20698c2ecf20Sopenharmony_ci for (i = 0; i < ff_args->num_dev; i++) 20708c2ecf20Sopenharmony_ci ff_layout_encode_ff_iostat(xdr, 20718c2ecf20Sopenharmony_ci &args->layout->plh_stateid, 20728c2ecf20Sopenharmony_ci &ff_args->devinfo[i]); 20738c2ecf20Sopenharmony_ci} 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_cistatic void 20768c2ecf20Sopenharmony_ciff_layout_free_iostats_array(struct nfs42_layoutstat_devinfo *devinfo, 20778c2ecf20Sopenharmony_ci unsigned int num_entries) 20788c2ecf20Sopenharmony_ci{ 20798c2ecf20Sopenharmony_ci unsigned int i; 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_ci for (i = 0; i < num_entries; i++) { 20828c2ecf20Sopenharmony_ci if (!devinfo[i].ld_private.ops) 20838c2ecf20Sopenharmony_ci continue; 20848c2ecf20Sopenharmony_ci if (!devinfo[i].ld_private.ops->free) 20858c2ecf20Sopenharmony_ci continue; 20868c2ecf20Sopenharmony_ci devinfo[i].ld_private.ops->free(&devinfo[i].ld_private); 20878c2ecf20Sopenharmony_ci } 20888c2ecf20Sopenharmony_ci} 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_cistatic struct nfs4_deviceid_node * 20918c2ecf20Sopenharmony_ciff_layout_alloc_deviceid_node(struct nfs_server *server, 20928c2ecf20Sopenharmony_ci struct pnfs_device *pdev, gfp_t gfp_flags) 20938c2ecf20Sopenharmony_ci{ 20948c2ecf20Sopenharmony_ci struct nfs4_ff_layout_ds *dsaddr; 20958c2ecf20Sopenharmony_ci 20968c2ecf20Sopenharmony_ci dsaddr = nfs4_ff_alloc_deviceid_node(server, pdev, gfp_flags); 20978c2ecf20Sopenharmony_ci if (!dsaddr) 20988c2ecf20Sopenharmony_ci return NULL; 20998c2ecf20Sopenharmony_ci return &dsaddr->id_node; 21008c2ecf20Sopenharmony_ci} 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_cistatic void 21038c2ecf20Sopenharmony_ciff_layout_encode_layoutreturn(struct xdr_stream *xdr, 21048c2ecf20Sopenharmony_ci const void *voidargs, 21058c2ecf20Sopenharmony_ci const struct nfs4_xdr_opaque_data *ff_opaque) 21068c2ecf20Sopenharmony_ci{ 21078c2ecf20Sopenharmony_ci const struct nfs4_layoutreturn_args *args = voidargs; 21088c2ecf20Sopenharmony_ci struct nfs4_flexfile_layoutreturn_args *ff_args = ff_opaque->data; 21098c2ecf20Sopenharmony_ci struct xdr_buf tmp_buf = { 21108c2ecf20Sopenharmony_ci .head = { 21118c2ecf20Sopenharmony_ci [0] = { 21128c2ecf20Sopenharmony_ci .iov_base = page_address(ff_args->pages[0]), 21138c2ecf20Sopenharmony_ci }, 21148c2ecf20Sopenharmony_ci }, 21158c2ecf20Sopenharmony_ci .buflen = PAGE_SIZE, 21168c2ecf20Sopenharmony_ci }; 21178c2ecf20Sopenharmony_ci struct xdr_stream tmp_xdr; 21188c2ecf20Sopenharmony_ci __be32 *start; 21198c2ecf20Sopenharmony_ci 21208c2ecf20Sopenharmony_ci dprintk("%s: Begin\n", __func__); 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci xdr_init_encode(&tmp_xdr, &tmp_buf, NULL, NULL); 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci ff_layout_encode_ioerr(&tmp_xdr, args, ff_args); 21258c2ecf20Sopenharmony_ci ff_layout_encode_iostats_array(&tmp_xdr, args, ff_args); 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_ci start = xdr_reserve_space(xdr, 4); 21288c2ecf20Sopenharmony_ci *start = cpu_to_be32(tmp_buf.len); 21298c2ecf20Sopenharmony_ci xdr_write_pages(xdr, ff_args->pages, 0, tmp_buf.len); 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_ci dprintk("%s: Return\n", __func__); 21328c2ecf20Sopenharmony_ci} 21338c2ecf20Sopenharmony_ci 21348c2ecf20Sopenharmony_cistatic void 21358c2ecf20Sopenharmony_ciff_layout_free_layoutreturn(struct nfs4_xdr_opaque_data *args) 21368c2ecf20Sopenharmony_ci{ 21378c2ecf20Sopenharmony_ci struct nfs4_flexfile_layoutreturn_args *ff_args; 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci if (!args->data) 21408c2ecf20Sopenharmony_ci return; 21418c2ecf20Sopenharmony_ci ff_args = args->data; 21428c2ecf20Sopenharmony_ci args->data = NULL; 21438c2ecf20Sopenharmony_ci 21448c2ecf20Sopenharmony_ci ff_layout_free_ds_ioerr(&ff_args->errors); 21458c2ecf20Sopenharmony_ci ff_layout_free_iostats_array(ff_args->devinfo, ff_args->num_dev); 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_ci put_page(ff_args->pages[0]); 21488c2ecf20Sopenharmony_ci kfree(ff_args); 21498c2ecf20Sopenharmony_ci} 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_cistatic const struct nfs4_xdr_opaque_ops layoutreturn_ops = { 21528c2ecf20Sopenharmony_ci .encode = ff_layout_encode_layoutreturn, 21538c2ecf20Sopenharmony_ci .free = ff_layout_free_layoutreturn, 21548c2ecf20Sopenharmony_ci}; 21558c2ecf20Sopenharmony_ci 21568c2ecf20Sopenharmony_cistatic int 21578c2ecf20Sopenharmony_ciff_layout_prepare_layoutreturn(struct nfs4_layoutreturn_args *args) 21588c2ecf20Sopenharmony_ci{ 21598c2ecf20Sopenharmony_ci struct nfs4_flexfile_layoutreturn_args *ff_args; 21608c2ecf20Sopenharmony_ci struct nfs4_flexfile_layout *ff_layout = FF_LAYOUT_FROM_HDR(args->layout); 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_ci ff_args = kmalloc(sizeof(*ff_args), GFP_KERNEL); 21638c2ecf20Sopenharmony_ci if (!ff_args) 21648c2ecf20Sopenharmony_ci goto out_nomem; 21658c2ecf20Sopenharmony_ci ff_args->pages[0] = alloc_page(GFP_KERNEL); 21668c2ecf20Sopenharmony_ci if (!ff_args->pages[0]) 21678c2ecf20Sopenharmony_ci goto out_nomem_free; 21688c2ecf20Sopenharmony_ci 21698c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ff_args->errors); 21708c2ecf20Sopenharmony_ci ff_args->num_errors = ff_layout_fetch_ds_ioerr(args->layout, 21718c2ecf20Sopenharmony_ci &args->range, &ff_args->errors, 21728c2ecf20Sopenharmony_ci FF_LAYOUTRETURN_MAXERR); 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_ci spin_lock(&args->inode->i_lock); 21758c2ecf20Sopenharmony_ci ff_args->num_dev = ff_layout_mirror_prepare_stats(&ff_layout->generic_hdr, 21768c2ecf20Sopenharmony_ci &ff_args->devinfo[0], ARRAY_SIZE(ff_args->devinfo)); 21778c2ecf20Sopenharmony_ci spin_unlock(&args->inode->i_lock); 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_ci args->ld_private->ops = &layoutreturn_ops; 21808c2ecf20Sopenharmony_ci args->ld_private->data = ff_args; 21818c2ecf20Sopenharmony_ci return 0; 21828c2ecf20Sopenharmony_ciout_nomem_free: 21838c2ecf20Sopenharmony_ci kfree(ff_args); 21848c2ecf20Sopenharmony_ciout_nomem: 21858c2ecf20Sopenharmony_ci return -ENOMEM; 21868c2ecf20Sopenharmony_ci} 21878c2ecf20Sopenharmony_ci 21888c2ecf20Sopenharmony_ci#ifdef CONFIG_NFS_V4_2 21898c2ecf20Sopenharmony_civoid 21908c2ecf20Sopenharmony_ciff_layout_send_layouterror(struct pnfs_layout_segment *lseg) 21918c2ecf20Sopenharmony_ci{ 21928c2ecf20Sopenharmony_ci struct pnfs_layout_hdr *lo = lseg->pls_layout; 21938c2ecf20Sopenharmony_ci struct nfs42_layout_error *errors; 21948c2ecf20Sopenharmony_ci LIST_HEAD(head); 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci if (!nfs_server_capable(lo->plh_inode, NFS_CAP_LAYOUTERROR)) 21978c2ecf20Sopenharmony_ci return; 21988c2ecf20Sopenharmony_ci ff_layout_fetch_ds_ioerr(lo, &lseg->pls_range, &head, -1); 21998c2ecf20Sopenharmony_ci if (list_empty(&head)) 22008c2ecf20Sopenharmony_ci return; 22018c2ecf20Sopenharmony_ci 22028c2ecf20Sopenharmony_ci errors = kmalloc_array(NFS42_LAYOUTERROR_MAX, 22038c2ecf20Sopenharmony_ci sizeof(*errors), GFP_NOFS); 22048c2ecf20Sopenharmony_ci if (errors != NULL) { 22058c2ecf20Sopenharmony_ci const struct nfs4_ff_layout_ds_err *pos; 22068c2ecf20Sopenharmony_ci size_t n = 0; 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci list_for_each_entry(pos, &head, list) { 22098c2ecf20Sopenharmony_ci errors[n].offset = pos->offset; 22108c2ecf20Sopenharmony_ci errors[n].length = pos->length; 22118c2ecf20Sopenharmony_ci nfs4_stateid_copy(&errors[n].stateid, &pos->stateid); 22128c2ecf20Sopenharmony_ci errors[n].errors[0].dev_id = pos->deviceid; 22138c2ecf20Sopenharmony_ci errors[n].errors[0].status = pos->status; 22148c2ecf20Sopenharmony_ci errors[n].errors[0].opnum = pos->opnum; 22158c2ecf20Sopenharmony_ci n++; 22168c2ecf20Sopenharmony_ci if (!list_is_last(&pos->list, &head) && 22178c2ecf20Sopenharmony_ci n < NFS42_LAYOUTERROR_MAX) 22188c2ecf20Sopenharmony_ci continue; 22198c2ecf20Sopenharmony_ci if (nfs42_proc_layouterror(lseg, errors, n) < 0) 22208c2ecf20Sopenharmony_ci break; 22218c2ecf20Sopenharmony_ci n = 0; 22228c2ecf20Sopenharmony_ci } 22238c2ecf20Sopenharmony_ci kfree(errors); 22248c2ecf20Sopenharmony_ci } 22258c2ecf20Sopenharmony_ci ff_layout_free_ds_ioerr(&head); 22268c2ecf20Sopenharmony_ci} 22278c2ecf20Sopenharmony_ci#else 22288c2ecf20Sopenharmony_civoid 22298c2ecf20Sopenharmony_ciff_layout_send_layouterror(struct pnfs_layout_segment *lseg) 22308c2ecf20Sopenharmony_ci{ 22318c2ecf20Sopenharmony_ci} 22328c2ecf20Sopenharmony_ci#endif 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_cistatic int 22358c2ecf20Sopenharmony_ciff_layout_ntop4(const struct sockaddr *sap, char *buf, const size_t buflen) 22368c2ecf20Sopenharmony_ci{ 22378c2ecf20Sopenharmony_ci const struct sockaddr_in *sin = (struct sockaddr_in *)sap; 22388c2ecf20Sopenharmony_ci 22398c2ecf20Sopenharmony_ci return snprintf(buf, buflen, "%pI4", &sin->sin_addr); 22408c2ecf20Sopenharmony_ci} 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_cistatic size_t 22438c2ecf20Sopenharmony_ciff_layout_ntop6_noscopeid(const struct sockaddr *sap, char *buf, 22448c2ecf20Sopenharmony_ci const int buflen) 22458c2ecf20Sopenharmony_ci{ 22468c2ecf20Sopenharmony_ci const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; 22478c2ecf20Sopenharmony_ci const struct in6_addr *addr = &sin6->sin6_addr; 22488c2ecf20Sopenharmony_ci 22498c2ecf20Sopenharmony_ci /* 22508c2ecf20Sopenharmony_ci * RFC 4291, Section 2.2.2 22518c2ecf20Sopenharmony_ci * 22528c2ecf20Sopenharmony_ci * Shorthanded ANY address 22538c2ecf20Sopenharmony_ci */ 22548c2ecf20Sopenharmony_ci if (ipv6_addr_any(addr)) 22558c2ecf20Sopenharmony_ci return snprintf(buf, buflen, "::"); 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci /* 22588c2ecf20Sopenharmony_ci * RFC 4291, Section 2.2.2 22598c2ecf20Sopenharmony_ci * 22608c2ecf20Sopenharmony_ci * Shorthanded loopback address 22618c2ecf20Sopenharmony_ci */ 22628c2ecf20Sopenharmony_ci if (ipv6_addr_loopback(addr)) 22638c2ecf20Sopenharmony_ci return snprintf(buf, buflen, "::1"); 22648c2ecf20Sopenharmony_ci 22658c2ecf20Sopenharmony_ci /* 22668c2ecf20Sopenharmony_ci * RFC 4291, Section 2.2.3 22678c2ecf20Sopenharmony_ci * 22688c2ecf20Sopenharmony_ci * Special presentation address format for mapped v4 22698c2ecf20Sopenharmony_ci * addresses. 22708c2ecf20Sopenharmony_ci */ 22718c2ecf20Sopenharmony_ci if (ipv6_addr_v4mapped(addr)) 22728c2ecf20Sopenharmony_ci return snprintf(buf, buflen, "::ffff:%pI4", 22738c2ecf20Sopenharmony_ci &addr->s6_addr32[3]); 22748c2ecf20Sopenharmony_ci 22758c2ecf20Sopenharmony_ci /* 22768c2ecf20Sopenharmony_ci * RFC 4291, Section 2.2.1 22778c2ecf20Sopenharmony_ci */ 22788c2ecf20Sopenharmony_ci return snprintf(buf, buflen, "%pI6c", addr); 22798c2ecf20Sopenharmony_ci} 22808c2ecf20Sopenharmony_ci 22818c2ecf20Sopenharmony_ci/* Derived from rpc_sockaddr2uaddr */ 22828c2ecf20Sopenharmony_cistatic void 22838c2ecf20Sopenharmony_ciff_layout_encode_netaddr(struct xdr_stream *xdr, struct nfs4_pnfs_ds_addr *da) 22848c2ecf20Sopenharmony_ci{ 22858c2ecf20Sopenharmony_ci struct sockaddr *sap = (struct sockaddr *)&da->da_addr; 22868c2ecf20Sopenharmony_ci char portbuf[RPCBIND_MAXUADDRPLEN]; 22878c2ecf20Sopenharmony_ci char addrbuf[RPCBIND_MAXUADDRLEN]; 22888c2ecf20Sopenharmony_ci char *netid; 22898c2ecf20Sopenharmony_ci unsigned short port; 22908c2ecf20Sopenharmony_ci int len, netid_len; 22918c2ecf20Sopenharmony_ci __be32 *p; 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_ci switch (sap->sa_family) { 22948c2ecf20Sopenharmony_ci case AF_INET: 22958c2ecf20Sopenharmony_ci if (ff_layout_ntop4(sap, addrbuf, sizeof(addrbuf)) == 0) 22968c2ecf20Sopenharmony_ci return; 22978c2ecf20Sopenharmony_ci port = ntohs(((struct sockaddr_in *)sap)->sin_port); 22988c2ecf20Sopenharmony_ci netid = "tcp"; 22998c2ecf20Sopenharmony_ci netid_len = 3; 23008c2ecf20Sopenharmony_ci break; 23018c2ecf20Sopenharmony_ci case AF_INET6: 23028c2ecf20Sopenharmony_ci if (ff_layout_ntop6_noscopeid(sap, addrbuf, sizeof(addrbuf)) == 0) 23038c2ecf20Sopenharmony_ci return; 23048c2ecf20Sopenharmony_ci port = ntohs(((struct sockaddr_in6 *)sap)->sin6_port); 23058c2ecf20Sopenharmony_ci netid = "tcp6"; 23068c2ecf20Sopenharmony_ci netid_len = 4; 23078c2ecf20Sopenharmony_ci break; 23088c2ecf20Sopenharmony_ci default: 23098c2ecf20Sopenharmony_ci /* we only support tcp and tcp6 */ 23108c2ecf20Sopenharmony_ci WARN_ON_ONCE(1); 23118c2ecf20Sopenharmony_ci return; 23128c2ecf20Sopenharmony_ci } 23138c2ecf20Sopenharmony_ci 23148c2ecf20Sopenharmony_ci snprintf(portbuf, sizeof(portbuf), ".%u.%u", port >> 8, port & 0xff); 23158c2ecf20Sopenharmony_ci len = strlcat(addrbuf, portbuf, sizeof(addrbuf)); 23168c2ecf20Sopenharmony_ci 23178c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 4 + netid_len); 23188c2ecf20Sopenharmony_ci xdr_encode_opaque(p, netid, netid_len); 23198c2ecf20Sopenharmony_ci 23208c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 4 + len); 23218c2ecf20Sopenharmony_ci xdr_encode_opaque(p, addrbuf, len); 23228c2ecf20Sopenharmony_ci} 23238c2ecf20Sopenharmony_ci 23248c2ecf20Sopenharmony_cistatic void 23258c2ecf20Sopenharmony_ciff_layout_encode_nfstime(struct xdr_stream *xdr, 23268c2ecf20Sopenharmony_ci ktime_t t) 23278c2ecf20Sopenharmony_ci{ 23288c2ecf20Sopenharmony_ci struct timespec64 ts; 23298c2ecf20Sopenharmony_ci __be32 *p; 23308c2ecf20Sopenharmony_ci 23318c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 12); 23328c2ecf20Sopenharmony_ci ts = ktime_to_timespec64(t); 23338c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, ts.tv_sec); 23348c2ecf20Sopenharmony_ci *p++ = cpu_to_be32(ts.tv_nsec); 23358c2ecf20Sopenharmony_ci} 23368c2ecf20Sopenharmony_ci 23378c2ecf20Sopenharmony_cistatic void 23388c2ecf20Sopenharmony_ciff_layout_encode_io_latency(struct xdr_stream *xdr, 23398c2ecf20Sopenharmony_ci struct nfs4_ff_io_stat *stat) 23408c2ecf20Sopenharmony_ci{ 23418c2ecf20Sopenharmony_ci __be32 *p; 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 5 * 8); 23448c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, stat->ops_requested); 23458c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, stat->bytes_requested); 23468c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, stat->ops_completed); 23478c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, stat->bytes_completed); 23488c2ecf20Sopenharmony_ci p = xdr_encode_hyper(p, stat->bytes_not_delivered); 23498c2ecf20Sopenharmony_ci ff_layout_encode_nfstime(xdr, stat->total_busy_time); 23508c2ecf20Sopenharmony_ci ff_layout_encode_nfstime(xdr, stat->aggregate_completion_time); 23518c2ecf20Sopenharmony_ci} 23528c2ecf20Sopenharmony_ci 23538c2ecf20Sopenharmony_cistatic void 23548c2ecf20Sopenharmony_ciff_layout_encode_ff_layoutupdate(struct xdr_stream *xdr, 23558c2ecf20Sopenharmony_ci const struct nfs42_layoutstat_devinfo *devinfo, 23568c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror) 23578c2ecf20Sopenharmony_ci{ 23588c2ecf20Sopenharmony_ci struct nfs4_pnfs_ds_addr *da; 23598c2ecf20Sopenharmony_ci struct nfs4_pnfs_ds *ds = mirror->mirror_ds->ds; 23608c2ecf20Sopenharmony_ci struct nfs_fh *fh = &mirror->fh_versions[0]; 23618c2ecf20Sopenharmony_ci __be32 *p; 23628c2ecf20Sopenharmony_ci 23638c2ecf20Sopenharmony_ci da = list_first_entry(&ds->ds_addrs, struct nfs4_pnfs_ds_addr, da_node); 23648c2ecf20Sopenharmony_ci dprintk("%s: DS %s: encoding address %s\n", 23658c2ecf20Sopenharmony_ci __func__, ds->ds_remotestr, da->da_remotestr); 23668c2ecf20Sopenharmony_ci /* netaddr4 */ 23678c2ecf20Sopenharmony_ci ff_layout_encode_netaddr(xdr, da); 23688c2ecf20Sopenharmony_ci /* nfs_fh4 */ 23698c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 4 + fh->size); 23708c2ecf20Sopenharmony_ci xdr_encode_opaque(p, fh->data, fh->size); 23718c2ecf20Sopenharmony_ci /* ff_io_latency4 read */ 23728c2ecf20Sopenharmony_ci spin_lock(&mirror->lock); 23738c2ecf20Sopenharmony_ci ff_layout_encode_io_latency(xdr, &mirror->read_stat.io_stat); 23748c2ecf20Sopenharmony_ci /* ff_io_latency4 write */ 23758c2ecf20Sopenharmony_ci ff_layout_encode_io_latency(xdr, &mirror->write_stat.io_stat); 23768c2ecf20Sopenharmony_ci spin_unlock(&mirror->lock); 23778c2ecf20Sopenharmony_ci /* nfstime4 */ 23788c2ecf20Sopenharmony_ci ff_layout_encode_nfstime(xdr, ktime_sub(ktime_get(), mirror->start_time)); 23798c2ecf20Sopenharmony_ci /* bool */ 23808c2ecf20Sopenharmony_ci p = xdr_reserve_space(xdr, 4); 23818c2ecf20Sopenharmony_ci *p = cpu_to_be32(false); 23828c2ecf20Sopenharmony_ci} 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_cistatic void 23858c2ecf20Sopenharmony_ciff_layout_encode_layoutstats(struct xdr_stream *xdr, const void *args, 23868c2ecf20Sopenharmony_ci const struct nfs4_xdr_opaque_data *opaque) 23878c2ecf20Sopenharmony_ci{ 23888c2ecf20Sopenharmony_ci struct nfs42_layoutstat_devinfo *devinfo = container_of(opaque, 23898c2ecf20Sopenharmony_ci struct nfs42_layoutstat_devinfo, ld_private); 23908c2ecf20Sopenharmony_ci __be32 *start; 23918c2ecf20Sopenharmony_ci 23928c2ecf20Sopenharmony_ci /* layoutupdate length */ 23938c2ecf20Sopenharmony_ci start = xdr_reserve_space(xdr, 4); 23948c2ecf20Sopenharmony_ci ff_layout_encode_ff_layoutupdate(xdr, devinfo, opaque->data); 23958c2ecf20Sopenharmony_ci 23968c2ecf20Sopenharmony_ci *start = cpu_to_be32((xdr->p - start - 1) * 4); 23978c2ecf20Sopenharmony_ci} 23988c2ecf20Sopenharmony_ci 23998c2ecf20Sopenharmony_cistatic void 24008c2ecf20Sopenharmony_ciff_layout_free_layoutstats(struct nfs4_xdr_opaque_data *opaque) 24018c2ecf20Sopenharmony_ci{ 24028c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror = opaque->data; 24038c2ecf20Sopenharmony_ci 24048c2ecf20Sopenharmony_ci ff_layout_put_mirror(mirror); 24058c2ecf20Sopenharmony_ci} 24068c2ecf20Sopenharmony_ci 24078c2ecf20Sopenharmony_cistatic const struct nfs4_xdr_opaque_ops layoutstat_ops = { 24088c2ecf20Sopenharmony_ci .encode = ff_layout_encode_layoutstats, 24098c2ecf20Sopenharmony_ci .free = ff_layout_free_layoutstats, 24108c2ecf20Sopenharmony_ci}; 24118c2ecf20Sopenharmony_ci 24128c2ecf20Sopenharmony_cistatic int 24138c2ecf20Sopenharmony_ciff_layout_mirror_prepare_stats(struct pnfs_layout_hdr *lo, 24148c2ecf20Sopenharmony_ci struct nfs42_layoutstat_devinfo *devinfo, 24158c2ecf20Sopenharmony_ci int dev_limit) 24168c2ecf20Sopenharmony_ci{ 24178c2ecf20Sopenharmony_ci struct nfs4_flexfile_layout *ff_layout = FF_LAYOUT_FROM_HDR(lo); 24188c2ecf20Sopenharmony_ci struct nfs4_ff_layout_mirror *mirror; 24198c2ecf20Sopenharmony_ci struct nfs4_deviceid_node *dev; 24208c2ecf20Sopenharmony_ci int i = 0; 24218c2ecf20Sopenharmony_ci 24228c2ecf20Sopenharmony_ci list_for_each_entry(mirror, &ff_layout->mirrors, mirrors) { 24238c2ecf20Sopenharmony_ci if (i >= dev_limit) 24248c2ecf20Sopenharmony_ci break; 24258c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(mirror->mirror_ds)) 24268c2ecf20Sopenharmony_ci continue; 24278c2ecf20Sopenharmony_ci if (!test_and_clear_bit(NFS4_FF_MIRROR_STAT_AVAIL, &mirror->flags)) 24288c2ecf20Sopenharmony_ci continue; 24298c2ecf20Sopenharmony_ci /* mirror refcount put in cleanup_layoutstats */ 24308c2ecf20Sopenharmony_ci if (!refcount_inc_not_zero(&mirror->ref)) 24318c2ecf20Sopenharmony_ci continue; 24328c2ecf20Sopenharmony_ci dev = &mirror->mirror_ds->id_node; 24338c2ecf20Sopenharmony_ci memcpy(&devinfo->dev_id, &dev->deviceid, NFS4_DEVICEID4_SIZE); 24348c2ecf20Sopenharmony_ci devinfo->offset = 0; 24358c2ecf20Sopenharmony_ci devinfo->length = NFS4_MAX_UINT64; 24368c2ecf20Sopenharmony_ci spin_lock(&mirror->lock); 24378c2ecf20Sopenharmony_ci devinfo->read_count = mirror->read_stat.io_stat.ops_completed; 24388c2ecf20Sopenharmony_ci devinfo->read_bytes = mirror->read_stat.io_stat.bytes_completed; 24398c2ecf20Sopenharmony_ci devinfo->write_count = mirror->write_stat.io_stat.ops_completed; 24408c2ecf20Sopenharmony_ci devinfo->write_bytes = mirror->write_stat.io_stat.bytes_completed; 24418c2ecf20Sopenharmony_ci spin_unlock(&mirror->lock); 24428c2ecf20Sopenharmony_ci devinfo->layout_type = LAYOUT_FLEX_FILES; 24438c2ecf20Sopenharmony_ci devinfo->ld_private.ops = &layoutstat_ops; 24448c2ecf20Sopenharmony_ci devinfo->ld_private.data = mirror; 24458c2ecf20Sopenharmony_ci 24468c2ecf20Sopenharmony_ci devinfo++; 24478c2ecf20Sopenharmony_ci i++; 24488c2ecf20Sopenharmony_ci } 24498c2ecf20Sopenharmony_ci return i; 24508c2ecf20Sopenharmony_ci} 24518c2ecf20Sopenharmony_ci 24528c2ecf20Sopenharmony_cistatic int 24538c2ecf20Sopenharmony_ciff_layout_prepare_layoutstats(struct nfs42_layoutstat_args *args) 24548c2ecf20Sopenharmony_ci{ 24558c2ecf20Sopenharmony_ci struct nfs4_flexfile_layout *ff_layout; 24568c2ecf20Sopenharmony_ci const int dev_count = PNFS_LAYOUTSTATS_MAXDEV; 24578c2ecf20Sopenharmony_ci 24588c2ecf20Sopenharmony_ci /* For now, send at most PNFS_LAYOUTSTATS_MAXDEV statistics */ 24598c2ecf20Sopenharmony_ci args->devinfo = kmalloc_array(dev_count, sizeof(*args->devinfo), GFP_NOIO); 24608c2ecf20Sopenharmony_ci if (!args->devinfo) 24618c2ecf20Sopenharmony_ci return -ENOMEM; 24628c2ecf20Sopenharmony_ci 24638c2ecf20Sopenharmony_ci spin_lock(&args->inode->i_lock); 24648c2ecf20Sopenharmony_ci ff_layout = FF_LAYOUT_FROM_HDR(NFS_I(args->inode)->layout); 24658c2ecf20Sopenharmony_ci args->num_dev = ff_layout_mirror_prepare_stats(&ff_layout->generic_hdr, 24668c2ecf20Sopenharmony_ci &args->devinfo[0], dev_count); 24678c2ecf20Sopenharmony_ci spin_unlock(&args->inode->i_lock); 24688c2ecf20Sopenharmony_ci if (!args->num_dev) { 24698c2ecf20Sopenharmony_ci kfree(args->devinfo); 24708c2ecf20Sopenharmony_ci args->devinfo = NULL; 24718c2ecf20Sopenharmony_ci return -ENOENT; 24728c2ecf20Sopenharmony_ci } 24738c2ecf20Sopenharmony_ci 24748c2ecf20Sopenharmony_ci return 0; 24758c2ecf20Sopenharmony_ci} 24768c2ecf20Sopenharmony_ci 24778c2ecf20Sopenharmony_cistatic int 24788c2ecf20Sopenharmony_ciff_layout_set_layoutdriver(struct nfs_server *server, 24798c2ecf20Sopenharmony_ci const struct nfs_fh *dummy) 24808c2ecf20Sopenharmony_ci{ 24818c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_NFS_V4_2) 24828c2ecf20Sopenharmony_ci server->caps |= NFS_CAP_LAYOUTSTATS; 24838c2ecf20Sopenharmony_ci#endif 24848c2ecf20Sopenharmony_ci return 0; 24858c2ecf20Sopenharmony_ci} 24868c2ecf20Sopenharmony_ci 24878c2ecf20Sopenharmony_cistatic const struct pnfs_commit_ops ff_layout_commit_ops = { 24888c2ecf20Sopenharmony_ci .setup_ds_info = ff_layout_setup_ds_info, 24898c2ecf20Sopenharmony_ci .release_ds_info = ff_layout_release_ds_info, 24908c2ecf20Sopenharmony_ci .mark_request_commit = pnfs_layout_mark_request_commit, 24918c2ecf20Sopenharmony_ci .clear_request_commit = pnfs_generic_clear_request_commit, 24928c2ecf20Sopenharmony_ci .scan_commit_lists = pnfs_generic_scan_commit_lists, 24938c2ecf20Sopenharmony_ci .recover_commit_reqs = pnfs_generic_recover_commit_reqs, 24948c2ecf20Sopenharmony_ci .commit_pagelist = ff_layout_commit_pagelist, 24958c2ecf20Sopenharmony_ci}; 24968c2ecf20Sopenharmony_ci 24978c2ecf20Sopenharmony_cistatic struct pnfs_layoutdriver_type flexfilelayout_type = { 24988c2ecf20Sopenharmony_ci .id = LAYOUT_FLEX_FILES, 24998c2ecf20Sopenharmony_ci .name = "LAYOUT_FLEX_FILES", 25008c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 25018c2ecf20Sopenharmony_ci .flags = PNFS_LAYOUTGET_ON_OPEN, 25028c2ecf20Sopenharmony_ci .max_layoutget_response = 4096, /* 1 page or so... */ 25038c2ecf20Sopenharmony_ci .set_layoutdriver = ff_layout_set_layoutdriver, 25048c2ecf20Sopenharmony_ci .alloc_layout_hdr = ff_layout_alloc_layout_hdr, 25058c2ecf20Sopenharmony_ci .free_layout_hdr = ff_layout_free_layout_hdr, 25068c2ecf20Sopenharmony_ci .alloc_lseg = ff_layout_alloc_lseg, 25078c2ecf20Sopenharmony_ci .free_lseg = ff_layout_free_lseg, 25088c2ecf20Sopenharmony_ci .add_lseg = ff_layout_add_lseg, 25098c2ecf20Sopenharmony_ci .pg_read_ops = &ff_layout_pg_read_ops, 25108c2ecf20Sopenharmony_ci .pg_write_ops = &ff_layout_pg_write_ops, 25118c2ecf20Sopenharmony_ci .get_ds_info = ff_layout_get_ds_info, 25128c2ecf20Sopenharmony_ci .free_deviceid_node = ff_layout_free_deviceid_node, 25138c2ecf20Sopenharmony_ci .read_pagelist = ff_layout_read_pagelist, 25148c2ecf20Sopenharmony_ci .write_pagelist = ff_layout_write_pagelist, 25158c2ecf20Sopenharmony_ci .alloc_deviceid_node = ff_layout_alloc_deviceid_node, 25168c2ecf20Sopenharmony_ci .prepare_layoutreturn = ff_layout_prepare_layoutreturn, 25178c2ecf20Sopenharmony_ci .sync = pnfs_nfs_generic_sync, 25188c2ecf20Sopenharmony_ci .prepare_layoutstats = ff_layout_prepare_layoutstats, 25198c2ecf20Sopenharmony_ci}; 25208c2ecf20Sopenharmony_ci 25218c2ecf20Sopenharmony_cistatic int __init nfs4flexfilelayout_init(void) 25228c2ecf20Sopenharmony_ci{ 25238c2ecf20Sopenharmony_ci printk(KERN_INFO "%s: NFSv4 Flexfile Layout Driver Registering...\n", 25248c2ecf20Sopenharmony_ci __func__); 25258c2ecf20Sopenharmony_ci return pnfs_register_layoutdriver(&flexfilelayout_type); 25268c2ecf20Sopenharmony_ci} 25278c2ecf20Sopenharmony_ci 25288c2ecf20Sopenharmony_cistatic void __exit nfs4flexfilelayout_exit(void) 25298c2ecf20Sopenharmony_ci{ 25308c2ecf20Sopenharmony_ci printk(KERN_INFO "%s: NFSv4 Flexfile Layout Driver Unregistering...\n", 25318c2ecf20Sopenharmony_ci __func__); 25328c2ecf20Sopenharmony_ci pnfs_unregister_layoutdriver(&flexfilelayout_type); 25338c2ecf20Sopenharmony_ci} 25348c2ecf20Sopenharmony_ci 25358c2ecf20Sopenharmony_ciMODULE_ALIAS("nfs-layouttype4-4"); 25368c2ecf20Sopenharmony_ci 25378c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 25388c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("The NFSv4 flexfile layout driver"); 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_cimodule_init(nfs4flexfilelayout_init); 25418c2ecf20Sopenharmony_cimodule_exit(nfs4flexfilelayout_exit); 25428c2ecf20Sopenharmony_ci 25438c2ecf20Sopenharmony_cimodule_param(io_maxretrans, ushort, 0644); 25448c2ecf20Sopenharmony_ciMODULE_PARM_DESC(io_maxretrans, "The number of times the NFSv4.1 client " 25458c2ecf20Sopenharmony_ci "retries an I/O request before returning an error. "); 2546