1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
29b9960a0STom Haynes /*
39b9960a0STom Haynes * Copyright (c) 2016 Tom Haynes <loghyr@primarydata.com>
49b9960a0STom Haynes *
59b9960a0STom Haynes * The following implements a super-simple flex-file server
69b9960a0STom Haynes * where the NFSv4.1 mds is also the ds. And the storage is
79b9960a0STom Haynes * the same. I.e., writing to the mds via a NFSv4.1 WRITE
89b9960a0STom Haynes * goes to the same location as the NFSv3 WRITE.
99b9960a0STom Haynes */
109b9960a0STom Haynes #include <linux/slab.h>
119b9960a0STom Haynes
129b9960a0STom Haynes #include <linux/nfsd/debug.h>
139b9960a0STom Haynes
149b9960a0STom Haynes #include <linux/sunrpc/addr.h>
159b9960a0STom Haynes
169b9960a0STom Haynes #include "flexfilelayoutxdr.h"
179b9960a0STom Haynes #include "pnfs.h"
18*cb12fae1SJeff Layton #include "vfs.h"
199b9960a0STom Haynes
209b9960a0STom Haynes #define NFSDDBG_FACILITY NFSDDBG_PNFS
219b9960a0STom Haynes
229b9960a0STom Haynes static __be32
nfsd4_ff_proc_layoutget(struct inode * inode,const struct svc_fh * fhp,struct nfsd4_layoutget * args)239b9960a0STom Haynes nfsd4_ff_proc_layoutget(struct inode *inode, const struct svc_fh *fhp,
249b9960a0STom Haynes struct nfsd4_layoutget *args)
259b9960a0STom Haynes {
269b9960a0STom Haynes struct nfsd4_layout_seg *seg = &args->lg_seg;
279b9960a0STom Haynes u32 device_generation = 0;
289b9960a0STom Haynes int error;
299b9960a0STom Haynes uid_t u;
309b9960a0STom Haynes
319b9960a0STom Haynes struct pnfs_ff_layout *fl;
329b9960a0STom Haynes
339b9960a0STom Haynes /*
349b9960a0STom Haynes * The super simple flex file server has 1 mirror, 1 data server,
359b9960a0STom Haynes * and 1 file handle. So instead of 4 allocs, do 1 for now.
369b9960a0STom Haynes * Zero it out for the stateid - don't want junk in there!
379b9960a0STom Haynes */
389b9960a0STom Haynes error = -ENOMEM;
399b9960a0STom Haynes fl = kzalloc(sizeof(*fl), GFP_KERNEL);
409b9960a0STom Haynes if (!fl)
419b9960a0STom Haynes goto out_error;
429b9960a0STom Haynes args->lg_content = fl;
439b9960a0STom Haynes
449b9960a0STom Haynes /*
459b9960a0STom Haynes * Avoid layout commit, try to force the I/O to the DS,
469b9960a0STom Haynes * and for fun, cause all IOMODE_RW layout segments to
479b9960a0STom Haynes * effectively be WRITE only.
489b9960a0STom Haynes */
499b9960a0STom Haynes fl->flags = FF_FLAGS_NO_LAYOUTCOMMIT | FF_FLAGS_NO_IO_THRU_MDS |
509b9960a0STom Haynes FF_FLAGS_NO_READ_IO;
519b9960a0STom Haynes
529b9960a0STom Haynes /* Do not allow a IOMODE_READ segment to have write pemissions */
539b9960a0STom Haynes if (seg->iomode == IOMODE_READ) {
549b9960a0STom Haynes u = from_kuid(&init_user_ns, inode->i_uid) + 1;
559b9960a0STom Haynes fl->uid = make_kuid(&init_user_ns, u);
569b9960a0STom Haynes } else
579b9960a0STom Haynes fl->uid = inode->i_uid;
589b9960a0STom Haynes fl->gid = inode->i_gid;
599b9960a0STom Haynes
609b9960a0STom Haynes error = nfsd4_set_deviceid(&fl->deviceid, fhp, device_generation);
619b9960a0STom Haynes if (error)
629b9960a0STom Haynes goto out_error;
639b9960a0STom Haynes
649b9960a0STom Haynes fl->fh.size = fhp->fh_handle.fh_size;
65d8b26071SNeilBrown memcpy(fl->fh.data, &fhp->fh_handle.fh_raw, fl->fh.size);
669b9960a0STom Haynes
679b9960a0STom Haynes /* Give whole file layout segments */
689b9960a0STom Haynes seg->offset = 0;
699b9960a0STom Haynes seg->length = NFS4_MAX_UINT64;
709b9960a0STom Haynes
719b9960a0STom Haynes dprintk("GET: 0x%llx:0x%llx %d\n", seg->offset, seg->length,
729b9960a0STom Haynes seg->iomode);
739b9960a0STom Haynes return 0;
749b9960a0STom Haynes
759b9960a0STom Haynes out_error:
769b9960a0STom Haynes seg->length = 0;
779b9960a0STom Haynes return nfserrno(error);
789b9960a0STom Haynes }
799b9960a0STom Haynes
809b9960a0STom Haynes static __be32
nfsd4_ff_proc_getdeviceinfo(struct super_block * sb,struct svc_rqst * rqstp,struct nfs4_client * clp,struct nfsd4_getdeviceinfo * gdp)819b9960a0STom Haynes nfsd4_ff_proc_getdeviceinfo(struct super_block *sb, struct svc_rqst *rqstp,
829b9960a0STom Haynes struct nfs4_client *clp, struct nfsd4_getdeviceinfo *gdp)
839b9960a0STom Haynes {
849b9960a0STom Haynes struct pnfs_ff_device_addr *da;
859b9960a0STom Haynes
869b9960a0STom Haynes u16 port;
879b9960a0STom Haynes char addr[INET6_ADDRSTRLEN];
889b9960a0STom Haynes
899b9960a0STom Haynes da = kzalloc(sizeof(struct pnfs_ff_device_addr), GFP_KERNEL);
909b9960a0STom Haynes if (!da)
919b9960a0STom Haynes return nfserrno(-ENOMEM);
929b9960a0STom Haynes
939b9960a0STom Haynes gdp->gd_device = da;
949b9960a0STom Haynes
959b9960a0STom Haynes da->version = 3;
969b9960a0STom Haynes da->minor_version = 0;
979b9960a0STom Haynes
989b9960a0STom Haynes da->rsize = svc_max_payload(rqstp);
999b9960a0STom Haynes da->wsize = da->rsize;
1009b9960a0STom Haynes
1019b9960a0STom Haynes rpc_ntop((struct sockaddr *)&rqstp->rq_daddr,
1029b9960a0STom Haynes addr, INET6_ADDRSTRLEN);
1039b9960a0STom Haynes if (rqstp->rq_daddr.ss_family == AF_INET) {
1049b9960a0STom Haynes struct sockaddr_in *sin;
1059b9960a0STom Haynes
1069b9960a0STom Haynes sin = (struct sockaddr_in *)&rqstp->rq_daddr;
1079b9960a0STom Haynes port = ntohs(sin->sin_port);
1089b9960a0STom Haynes snprintf(da->netaddr.netid, FF_NETID_LEN + 1, "tcp");
1099b9960a0STom Haynes da->netaddr.netid_len = 3;
1109b9960a0STom Haynes } else {
1119b9960a0STom Haynes struct sockaddr_in6 *sin6;
1129b9960a0STom Haynes
1139b9960a0STom Haynes sin6 = (struct sockaddr_in6 *)&rqstp->rq_daddr;
1149b9960a0STom Haynes port = ntohs(sin6->sin6_port);
1159b9960a0STom Haynes snprintf(da->netaddr.netid, FF_NETID_LEN + 1, "tcp6");
1169b9960a0STom Haynes da->netaddr.netid_len = 4;
1179b9960a0STom Haynes }
1189b9960a0STom Haynes
1199b9960a0STom Haynes da->netaddr.addr_len =
1209b9960a0STom Haynes snprintf(da->netaddr.addr, FF_ADDR_LEN + 1,
1214e1b04afSBill Wendling "%s.%d.%d", addr, port >> 8, port & 0xff);
1229b9960a0STom Haynes
1239b9960a0STom Haynes da->tightly_coupled = false;
1249b9960a0STom Haynes
1259b9960a0STom Haynes return 0;
1269b9960a0STom Haynes }
1279b9960a0STom Haynes
1289b9960a0STom Haynes const struct nfsd4_layout_ops ff_layout_ops = {
1299b9960a0STom Haynes .notify_types =
1309b9960a0STom Haynes NOTIFY_DEVICEID4_DELETE | NOTIFY_DEVICEID4_CHANGE,
1311983a66fSJeff Layton .disable_recalls = true,
1329b9960a0STom Haynes .proc_getdeviceinfo = nfsd4_ff_proc_getdeviceinfo,
1339b9960a0STom Haynes .encode_getdeviceinfo = nfsd4_ff_encode_getdeviceinfo,
1349b9960a0STom Haynes .proc_layoutget = nfsd4_ff_proc_layoutget,
1359b9960a0STom Haynes .encode_layoutget = nfsd4_ff_encode_layoutget,
1369b9960a0STom Haynes };
137