2 * Copyright (c) 2016 Tom Haynes <loghyr@primarydata.com>
4 * The following implements a super-simple flex-file server
5 * where the NFSv4.1 mds is also the ds. And the storage is
6 * the same. I.e., writing to the mds via a NFSv4.1 WRITE
7 * goes to the same location as the NFSv3 WRITE.
9 #include <linux/slab.h>
11 #include <linux/nfsd/debug.h>
13 #include <linux/sunrpc/addr.h>
15 #include "flexfilelayoutxdr.h"
18 #define NFSDDBG_FACILITY NFSDDBG_PNFS
21 nfsd4_ff_proc_layoutget(struct inode
*inode
, const struct svc_fh
*fhp
,
22 struct nfsd4_layoutget
*args
)
24 struct nfsd4_layout_seg
*seg
= &args
->lg_seg
;
25 u32 device_generation
= 0;
29 struct pnfs_ff_layout
*fl
;
32 * The super simple flex file server has 1 mirror, 1 data server,
33 * and 1 file handle. So instead of 4 allocs, do 1 for now.
34 * Zero it out for the stateid - don't want junk in there!
37 fl
= kzalloc(sizeof(*fl
), GFP_KERNEL
);
40 args
->lg_content
= fl
;
43 * Avoid layout commit, try to force the I/O to the DS,
44 * and for fun, cause all IOMODE_RW layout segments to
45 * effectively be WRITE only.
47 fl
->flags
= FF_FLAGS_NO_LAYOUTCOMMIT
| FF_FLAGS_NO_IO_THRU_MDS
|
50 /* Do not allow a IOMODE_READ segment to have write pemissions */
51 if (seg
->iomode
== IOMODE_READ
) {
52 u
= from_kuid(&init_user_ns
, inode
->i_uid
) + 1;
53 fl
->uid
= make_kuid(&init_user_ns
, u
);
55 fl
->uid
= inode
->i_uid
;
56 fl
->gid
= inode
->i_gid
;
58 error
= nfsd4_set_deviceid(&fl
->deviceid
, fhp
, device_generation
);
62 fl
->fh
.size
= fhp
->fh_handle
.fh_size
;
63 memcpy(fl
->fh
.data
, &fhp
->fh_handle
.fh_base
, fl
->fh
.size
);
65 /* Give whole file layout segments */
67 seg
->length
= NFS4_MAX_UINT64
;
69 dprintk("GET: 0x%llx:0x%llx %d\n", seg
->offset
, seg
->length
,
75 return nfserrno(error
);
79 nfsd4_ff_proc_getdeviceinfo(struct super_block
*sb
, struct svc_rqst
*rqstp
,
80 struct nfs4_client
*clp
, struct nfsd4_getdeviceinfo
*gdp
)
82 struct pnfs_ff_device_addr
*da
;
85 char addr
[INET6_ADDRSTRLEN
];
87 da
= kzalloc(sizeof(struct pnfs_ff_device_addr
), GFP_KERNEL
);
89 return nfserrno(-ENOMEM
);
94 da
->minor_version
= 0;
96 da
->rsize
= svc_max_payload(rqstp
);
97 da
->wsize
= da
->rsize
;
99 rpc_ntop((struct sockaddr
*)&rqstp
->rq_daddr
,
100 addr
, INET6_ADDRSTRLEN
);
101 if (rqstp
->rq_daddr
.ss_family
== AF_INET
) {
102 struct sockaddr_in
*sin
;
104 sin
= (struct sockaddr_in
*)&rqstp
->rq_daddr
;
105 port
= ntohs(sin
->sin_port
);
106 snprintf(da
->netaddr
.netid
, FF_NETID_LEN
+ 1, "tcp");
107 da
->netaddr
.netid_len
= 3;
109 struct sockaddr_in6
*sin6
;
111 sin6
= (struct sockaddr_in6
*)&rqstp
->rq_daddr
;
112 port
= ntohs(sin6
->sin6_port
);
113 snprintf(da
->netaddr
.netid
, FF_NETID_LEN
+ 1, "tcp6");
114 da
->netaddr
.netid_len
= 4;
117 da
->netaddr
.addr_len
=
118 snprintf(da
->netaddr
.addr
, FF_ADDR_LEN
+ 1,
119 "%s.%hhu.%hhu", addr
, port
>> 8, port
& 0xff);
121 da
->tightly_coupled
= false;
126 const struct nfsd4_layout_ops ff_layout_ops
= {
128 NOTIFY_DEVICEID4_DELETE
| NOTIFY_DEVICEID4_CHANGE
,
129 .disable_recalls
= true,
130 .proc_getdeviceinfo
= nfsd4_ff_proc_getdeviceinfo
,
131 .encode_getdeviceinfo
= nfsd4_ff_encode_getdeviceinfo
,
132 .proc_layoutget
= nfsd4_ff_proc_layoutget
,
133 .encode_layoutget
= nfsd4_ff_encode_layoutget
,