xref: /openbmc/linux/fs/nfsd/flexfilelayout.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
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