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