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