Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2016 Tom Haynes <loghyr@primarydata.com>
0004  *
0005  * The following implements a super-simple flex-file server
0006  * where the NFSv4.1 mds is also the ds. And the storage is
0007  * the same. I.e., writing to the mds via a NFSv4.1 WRITE
0008  * goes to the same location as the NFSv3 WRITE.
0009  */
0010 #include <linux/slab.h>
0011 
0012 #include <linux/nfsd/debug.h>
0013 
0014 #include <linux/sunrpc/addr.h>
0015 
0016 #include "flexfilelayoutxdr.h"
0017 #include "pnfs.h"
0018 
0019 #define NFSDDBG_FACILITY    NFSDDBG_PNFS
0020 
0021 static __be32
0022 nfsd4_ff_proc_layoutget(struct inode *inode, const struct svc_fh *fhp,
0023         struct nfsd4_layoutget *args)
0024 {
0025     struct nfsd4_layout_seg *seg = &args->lg_seg;
0026     u32 device_generation = 0;
0027     int error;
0028     uid_t u;
0029 
0030     struct pnfs_ff_layout *fl;
0031 
0032     /*
0033      * The super simple flex file server has 1 mirror, 1 data server,
0034      * and 1 file handle. So instead of 4 allocs, do 1 for now.
0035      * Zero it out for the stateid - don't want junk in there!
0036      */
0037     error = -ENOMEM;
0038     fl = kzalloc(sizeof(*fl), GFP_KERNEL);
0039     if (!fl)
0040         goto out_error;
0041     args->lg_content = fl;
0042 
0043     /*
0044      * Avoid layout commit, try to force the I/O to the DS,
0045      * and for fun, cause all IOMODE_RW layout segments to
0046      * effectively be WRITE only.
0047      */
0048     fl->flags = FF_FLAGS_NO_LAYOUTCOMMIT | FF_FLAGS_NO_IO_THRU_MDS |
0049             FF_FLAGS_NO_READ_IO;
0050 
0051     /* Do not allow a IOMODE_READ segment to have write pemissions */
0052     if (seg->iomode == IOMODE_READ) {
0053         u = from_kuid(&init_user_ns, inode->i_uid) + 1;
0054         fl->uid = make_kuid(&init_user_ns, u);
0055     } else
0056         fl->uid = inode->i_uid;
0057     fl->gid = inode->i_gid;
0058 
0059     error = nfsd4_set_deviceid(&fl->deviceid, fhp, device_generation);
0060     if (error)
0061         goto out_error;
0062 
0063     fl->fh.size = fhp->fh_handle.fh_size;
0064     memcpy(fl->fh.data, &fhp->fh_handle.fh_raw, fl->fh.size);
0065 
0066     /* Give whole file layout segments */
0067     seg->offset = 0;
0068     seg->length = NFS4_MAX_UINT64;
0069 
0070     dprintk("GET: 0x%llx:0x%llx %d\n", seg->offset, seg->length,
0071         seg->iomode);
0072     return 0;
0073 
0074 out_error:
0075     seg->length = 0;
0076     return nfserrno(error);
0077 }
0078 
0079 static __be32
0080 nfsd4_ff_proc_getdeviceinfo(struct super_block *sb, struct svc_rqst *rqstp,
0081         struct nfs4_client *clp, struct nfsd4_getdeviceinfo *gdp)
0082 {
0083     struct pnfs_ff_device_addr *da;
0084 
0085     u16 port;
0086     char addr[INET6_ADDRSTRLEN];
0087 
0088     da = kzalloc(sizeof(struct pnfs_ff_device_addr), GFP_KERNEL);
0089     if (!da)
0090         return nfserrno(-ENOMEM);
0091 
0092     gdp->gd_device = da;
0093 
0094     da->version = 3;
0095     da->minor_version = 0;
0096 
0097     da->rsize = svc_max_payload(rqstp);
0098     da->wsize = da->rsize;
0099 
0100     rpc_ntop((struct sockaddr *)&rqstp->rq_daddr,
0101          addr, INET6_ADDRSTRLEN);
0102     if (rqstp->rq_daddr.ss_family == AF_INET) {
0103         struct sockaddr_in *sin;
0104 
0105         sin = (struct sockaddr_in *)&rqstp->rq_daddr;
0106         port = ntohs(sin->sin_port);
0107         snprintf(da->netaddr.netid, FF_NETID_LEN + 1, "tcp");
0108         da->netaddr.netid_len = 3;
0109     } else {
0110         struct sockaddr_in6 *sin6;
0111 
0112         sin6 = (struct sockaddr_in6 *)&rqstp->rq_daddr;
0113         port = ntohs(sin6->sin6_port);
0114         snprintf(da->netaddr.netid, FF_NETID_LEN + 1, "tcp6");
0115         da->netaddr.netid_len = 4;
0116     }
0117 
0118     da->netaddr.addr_len =
0119         snprintf(da->netaddr.addr, FF_ADDR_LEN + 1,
0120              "%s.%d.%d", addr, port >> 8, port & 0xff);
0121 
0122     da->tightly_coupled = false;
0123 
0124     return 0;
0125 }
0126 
0127 const struct nfsd4_layout_ops ff_layout_ops = {
0128     .notify_types       =
0129             NOTIFY_DEVICEID4_DELETE | NOTIFY_DEVICEID4_CHANGE,
0130     .disable_recalls    = true,
0131     .proc_getdeviceinfo = nfsd4_ff_proc_getdeviceinfo,
0132     .encode_getdeviceinfo   = nfsd4_ff_encode_getdeviceinfo,
0133     .proc_layoutget     = nfsd4_ff_proc_layoutget,
0134     .encode_layoutget   = nfsd4_ff_encode_layoutget,
0135 };