1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2016 Tom Haynes <loghyr@primarydata.com>
5 * The following implements a super-simple flex-file server
6 * where the NFSv4.1 mds is also the ds. And the storage is
7 * the same. I.e., writing to the mds via a NFSv4.1 WRITE
8 * goes to the same location as the NFSv3 WRITE.
10 #include <linux/slab.h>
12 #include <linux/nfsd/debug.h>
14 #include <linux/sunrpc/addr.h>
16 #include "flexfilelayoutxdr.h"
19 #define NFSDDBG_FACILITY NFSDDBG_PNFS
22 nfsd4_ff_proc_layoutget(struct inode
*inode
, const struct svc_fh
*fhp
,
23 struct nfsd4_layoutget
*args
)
25 struct nfsd4_layout_seg
*seg
= &args
->lg_seg
;
26 u32 device_generation
= 0;
30 struct pnfs_ff_layout
*fl
;
33 * The super simple flex file server has 1 mirror, 1 data server,
34 * and 1 file handle. So instead of 4 allocs, do 1 for now.
35 * Zero it out for the stateid - don't want junk in there!
38 fl
= kzalloc(sizeof(*fl
), GFP_KERNEL
);
41 args
->lg_content
= fl
;
44 * Avoid layout commit, try to force the I/O to the DS,
45 * and for fun, cause all IOMODE_RW layout segments to
46 * effectively be WRITE only.
48 fl
->flags
= FF_FLAGS_NO_LAYOUTCOMMIT
| FF_FLAGS_NO_IO_THRU_MDS
|
51 /* Do not allow a IOMODE_READ segment to have write pemissions */
52 if (seg
->iomode
== IOMODE_READ
) {
53 u
= from_kuid(&init_user_ns
, inode
->i_uid
) + 1;
54 fl
->uid
= make_kuid(&init_user_ns
, u
);
56 fl
->uid
= inode
->i_uid
;
57 fl
->gid
= inode
->i_gid
;
59 error
= nfsd4_set_deviceid(&fl
->deviceid
, fhp
, device_generation
);
63 fl
->fh
.size
= fhp
->fh_handle
.fh_size
;
64 memcpy(fl
->fh
.data
, &fhp
->fh_handle
.fh_base
, fl
->fh
.size
);
66 /* Give whole file layout segments */
68 seg
->length
= NFS4_MAX_UINT64
;
70 dprintk("GET: 0x%llx:0x%llx %d\n", seg
->offset
, seg
->length
,
76 return nfserrno(error
);
80 nfsd4_ff_proc_getdeviceinfo(struct super_block
*sb
, struct svc_rqst
*rqstp
,
81 struct nfs4_client
*clp
, struct nfsd4_getdeviceinfo
*gdp
)
83 struct pnfs_ff_device_addr
*da
;
86 char addr
[INET6_ADDRSTRLEN
];
88 da
= kzalloc(sizeof(struct pnfs_ff_device_addr
), GFP_KERNEL
);
90 return nfserrno(-ENOMEM
);
95 da
->minor_version
= 0;
97 da
->rsize
= svc_max_payload(rqstp
);
98 da
->wsize
= da
->rsize
;
100 rpc_ntop((struct sockaddr
*)&rqstp
->rq_daddr
,
101 addr
, INET6_ADDRSTRLEN
);
102 if (rqstp
->rq_daddr
.ss_family
== AF_INET
) {
103 struct sockaddr_in
*sin
;
105 sin
= (struct sockaddr_in
*)&rqstp
->rq_daddr
;
106 port
= ntohs(sin
->sin_port
);
107 snprintf(da
->netaddr
.netid
, FF_NETID_LEN
+ 1, "tcp");
108 da
->netaddr
.netid_len
= 3;
110 struct sockaddr_in6
*sin6
;
112 sin6
= (struct sockaddr_in6
*)&rqstp
->rq_daddr
;
113 port
= ntohs(sin6
->sin6_port
);
114 snprintf(da
->netaddr
.netid
, FF_NETID_LEN
+ 1, "tcp6");
115 da
->netaddr
.netid_len
= 4;
118 da
->netaddr
.addr_len
=
119 snprintf(da
->netaddr
.addr
, FF_ADDR_LEN
+ 1,
120 "%s.%hhu.%hhu", addr
, port
>> 8, port
& 0xff);
122 da
->tightly_coupled
= false;
127 const struct nfsd4_layout_ops ff_layout_ops
= {
129 NOTIFY_DEVICEID4_DELETE
| NOTIFY_DEVICEID4_CHANGE
,
130 .disable_recalls
= true,
131 .proc_getdeviceinfo
= nfsd4_ff_proc_getdeviceinfo
,
132 .encode_getdeviceinfo
= nfsd4_ff_encode_getdeviceinfo
,
133 .proc_layoutget
= nfsd4_ff_proc_layoutget
,
134 .encode_layoutget
= nfsd4_ff_encode_layoutget
,