LCOV - code coverage report
Current view: top level - fs/nfs/filelayout - filelayoutdev.c (source / functions) Hit Total Coverage
Test: Real Lines: 0 95 0.0 %
Date: 2020-10-17 15:46:16 Functions: 0 7 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

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

Generated by: LCOV version 1.14