root/fs/nfsd/flexfilelayout.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfsd4_ff_proc_layoutget
  2. nfsd4_ff_proc_getdeviceinfo

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (c) 2016 Tom Haynes <loghyr@primarydata.com>
   4  *
   5  * The following implements a super-simple flex-file server
   6  * where the NFSv4.1 mds is also the ds. And the storage is
   7  * the same. I.e., writing to the mds via a NFSv4.1 WRITE
   8  * goes to the same location as the NFSv3 WRITE.
   9  */
  10 #include <linux/slab.h>
  11 
  12 #include <linux/nfsd/debug.h>
  13 
  14 #include <linux/sunrpc/addr.h>
  15 
  16 #include "flexfilelayoutxdr.h"
  17 #include "pnfs.h"
  18 
  19 #define NFSDDBG_FACILITY        NFSDDBG_PNFS
  20 
  21 static __be32
  22 nfsd4_ff_proc_layoutget(struct inode *inode, const struct svc_fh *fhp,
  23                 struct nfsd4_layoutget *args)
  24 {
  25         struct nfsd4_layout_seg *seg = &args->lg_seg;
  26         u32 device_generation = 0;
  27         int error;
  28         uid_t u;
  29 
  30         struct pnfs_ff_layout *fl;
  31 
  32         /*
  33          * The super simple flex file server has 1 mirror, 1 data server,
  34          * and 1 file handle. So instead of 4 allocs, do 1 for now.
  35          * Zero it out for the stateid - don't want junk in there!
  36          */
  37         error = -ENOMEM;
  38         fl = kzalloc(sizeof(*fl), GFP_KERNEL);
  39         if (!fl)
  40                 goto out_error;
  41         args->lg_content = fl;
  42 
  43         /*
  44          * Avoid layout commit, try to force the I/O to the DS,
  45          * and for fun, cause all IOMODE_RW layout segments to
  46          * effectively be WRITE only.
  47          */
  48         fl->flags = FF_FLAGS_NO_LAYOUTCOMMIT | FF_FLAGS_NO_IO_THRU_MDS |
  49                     FF_FLAGS_NO_READ_IO;
  50 
  51         /* Do not allow a IOMODE_READ segment to have write pemissions */
  52         if (seg->iomode == IOMODE_READ) {
  53                 u = from_kuid(&init_user_ns, inode->i_uid) + 1;
  54                 fl->uid = make_kuid(&init_user_ns, u);
  55         } else
  56                 fl->uid = inode->i_uid;
  57         fl->gid = inode->i_gid;
  58 
  59         error = nfsd4_set_deviceid(&fl->deviceid, fhp, device_generation);
  60         if (error)
  61                 goto out_error;
  62 
  63         fl->fh.size = fhp->fh_handle.fh_size;
  64         memcpy(fl->fh.data, &fhp->fh_handle.fh_base, fl->fh.size);
  65 
  66         /* Give whole file layout segments */
  67         seg->offset = 0;
  68         seg->length = NFS4_MAX_UINT64;
  69 
  70         dprintk("GET: 0x%llx:0x%llx %d\n", seg->offset, seg->length,
  71                 seg->iomode);
  72         return 0;
  73 
  74 out_error:
  75         seg->length = 0;
  76         return nfserrno(error);
  77 }
  78 
  79 static __be32
  80 nfsd4_ff_proc_getdeviceinfo(struct super_block *sb, struct svc_rqst *rqstp,
  81                 struct nfs4_client *clp, struct nfsd4_getdeviceinfo *gdp)
  82 {
  83         struct pnfs_ff_device_addr *da;
  84 
  85         u16 port;
  86         char addr[INET6_ADDRSTRLEN];
  87 
  88         da = kzalloc(sizeof(struct pnfs_ff_device_addr), GFP_KERNEL);
  89         if (!da)
  90                 return nfserrno(-ENOMEM);
  91 
  92         gdp->gd_device = da;
  93 
  94         da->version = 3;
  95         da->minor_version = 0;
  96 
  97         da->rsize = svc_max_payload(rqstp);
  98         da->wsize = da->rsize;
  99 
 100         rpc_ntop((struct sockaddr *)&rqstp->rq_daddr,
 101                  addr, INET6_ADDRSTRLEN);
 102         if (rqstp->rq_daddr.ss_family == AF_INET) {
 103                 struct sockaddr_in *sin;
 104 
 105                 sin = (struct sockaddr_in *)&rqstp->rq_daddr;
 106                 port = ntohs(sin->sin_port);
 107                 snprintf(da->netaddr.netid, FF_NETID_LEN + 1, "tcp");
 108                 da->netaddr.netid_len = 3;
 109         } else {
 110                 struct sockaddr_in6 *sin6;
 111 
 112                 sin6 = (struct sockaddr_in6 *)&rqstp->rq_daddr;
 113                 port = ntohs(sin6->sin6_port);
 114                 snprintf(da->netaddr.netid, FF_NETID_LEN + 1, "tcp6");
 115                 da->netaddr.netid_len = 4;
 116         }
 117 
 118         da->netaddr.addr_len =
 119                 snprintf(da->netaddr.addr, FF_ADDR_LEN + 1,
 120                          "%s.%hhu.%hhu", addr, port >> 8, port & 0xff);
 121 
 122         da->tightly_coupled = false;
 123 
 124         return 0;
 125 }
 126 
 127 const struct nfsd4_layout_ops ff_layout_ops = {
 128         .notify_types           =
 129                         NOTIFY_DEVICEID4_DELETE | NOTIFY_DEVICEID4_CHANGE,
 130         .disable_recalls        = true,
 131         .proc_getdeviceinfo     = nfsd4_ff_proc_getdeviceinfo,
 132         .encode_getdeviceinfo   = nfsd4_ff_encode_getdeviceinfo,
 133         .proc_layoutget         = nfsd4_ff_proc_layoutget,
 134         .encode_layoutget       = nfsd4_ff_encode_layoutget,
 135 };

/* [<][>][^][v][top][bottom][index][help] */