1*d96b98a3SKenneth D. Merry /*- 2*d96b98a3SKenneth D. Merry * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ 3*d96b98a3SKenneth D. Merry * Copyright (c) 2013 Spectra Logic Corporation 4*d96b98a3SKenneth D. Merry * 5*d96b98a3SKenneth D. Merry * Redistribution and use in source and binary forms, with or without 6*d96b98a3SKenneth D. Merry * modification, are permitted provided that the following conditions 7*d96b98a3SKenneth D. Merry * are met: 8*d96b98a3SKenneth D. Merry * 1. Redistributions of source code must retain the above copyright 9*d96b98a3SKenneth D. Merry * notice, this list of conditions and the following disclaimer. 10*d96b98a3SKenneth D. Merry * 2. Redistributions in binary form must reproduce the above copyright 11*d96b98a3SKenneth D. Merry * notice, this list of conditions and the following disclaimer in the 12*d96b98a3SKenneth D. Merry * documentation and/or other materials provided with the distribution. 13*d96b98a3SKenneth D. Merry * 14*d96b98a3SKenneth D. Merry * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*d96b98a3SKenneth D. Merry * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*d96b98a3SKenneth D. Merry * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*d96b98a3SKenneth D. Merry * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*d96b98a3SKenneth D. Merry * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*d96b98a3SKenneth D. Merry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*d96b98a3SKenneth D. Merry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*d96b98a3SKenneth D. Merry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*d96b98a3SKenneth D. Merry * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*d96b98a3SKenneth D. Merry * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*d96b98a3SKenneth D. Merry * SUCH DAMAGE. 25*d96b98a3SKenneth D. Merry */ 26*d96b98a3SKenneth D. Merry 27*d96b98a3SKenneth D. Merry #include <sys/cdefs.h> 28*d96b98a3SKenneth D. Merry __FBSDID("$FreeBSD$"); 29*d96b98a3SKenneth D. Merry 30*d96b98a3SKenneth D. Merry #include <fs/nfs/nfsport.h> 31*d96b98a3SKenneth D. Merry 32*d96b98a3SKenneth D. Merry #include <rpc/rpc.h> 33*d96b98a3SKenneth D. Merry #include <fs/nfs/xdr_subs.h> 34*d96b98a3SKenneth D. Merry #include <fs/nfs/nfs.h> 35*d96b98a3SKenneth D. Merry #include <fs/nfs/nfsproto.h> 36*d96b98a3SKenneth D. Merry #include <fs/nfs/nfsm_subs.h> 37*d96b98a3SKenneth D. Merry #include <nfsserver/nfs_fha.h> 38*d96b98a3SKenneth D. Merry #include <fs/nfsserver/nfs_fha_new.h> 39*d96b98a3SKenneth D. Merry 40*d96b98a3SKenneth D. Merry static void fhanew_init(void *foo); 41*d96b98a3SKenneth D. Merry static void fhanew_uninit(void *foo); 42*d96b98a3SKenneth D. Merry rpcproc_t fhanew_get_procnum(rpcproc_t procnum); 43*d96b98a3SKenneth D. Merry int fhanew_realign(struct mbuf **mb, int malloc_flags); 44*d96b98a3SKenneth D. Merry int fhanew_get_fh(fhandle_t *fh, int v3, struct mbuf **md, caddr_t *dpos); 45*d96b98a3SKenneth D. Merry int fhanew_is_read(rpcproc_t procnum); 46*d96b98a3SKenneth D. Merry int fhanew_is_write(rpcproc_t procnum); 47*d96b98a3SKenneth D. Merry int fhanew_get_offset(struct mbuf **md, caddr_t *dpos, int v3, 48*d96b98a3SKenneth D. Merry struct fha_info *info); 49*d96b98a3SKenneth D. Merry int fhanew_no_offset(rpcproc_t procnum); 50*d96b98a3SKenneth D. Merry void fhanew_set_locktype(rpcproc_t procnum, struct fha_info *info); 51*d96b98a3SKenneth D. Merry static int fhenew_stats_sysctl(SYSCTL_HANDLER_ARGS); 52*d96b98a3SKenneth D. Merry 53*d96b98a3SKenneth D. Merry static struct fha_params fhanew_softc; 54*d96b98a3SKenneth D. Merry 55*d96b98a3SKenneth D. Merry SYSCTL_DECL(_vfs_nfsd); 56*d96b98a3SKenneth D. Merry 57*d96b98a3SKenneth D. Merry extern int newnfs_nfsv3_procid[]; 58*d96b98a3SKenneth D. Merry extern SVCPOOL *nfsrvd_pool; 59*d96b98a3SKenneth D. Merry 60*d96b98a3SKenneth D. Merry SYSINIT(nfs_fhanew, SI_SUB_ROOT_CONF, SI_ORDER_ANY, fhanew_init, NULL); 61*d96b98a3SKenneth D. Merry SYSUNINIT(nfs_fhanew, SI_SUB_ROOT_CONF, SI_ORDER_ANY, fhanew_uninit, NULL); 62*d96b98a3SKenneth D. Merry 63*d96b98a3SKenneth D. Merry static void 64*d96b98a3SKenneth D. Merry fhanew_init(void *foo) 65*d96b98a3SKenneth D. Merry { 66*d96b98a3SKenneth D. Merry struct fha_params *softc; 67*d96b98a3SKenneth D. Merry 68*d96b98a3SKenneth D. Merry softc = &fhanew_softc; 69*d96b98a3SKenneth D. Merry 70*d96b98a3SKenneth D. Merry bzero(softc, sizeof(*softc)); 71*d96b98a3SKenneth D. Merry 72*d96b98a3SKenneth D. Merry /* 73*d96b98a3SKenneth D. Merry * Setup the callbacks for this FHA personality. 74*d96b98a3SKenneth D. Merry */ 75*d96b98a3SKenneth D. Merry softc->callbacks.get_procnum = fhanew_get_procnum; 76*d96b98a3SKenneth D. Merry softc->callbacks.realign = fhanew_realign; 77*d96b98a3SKenneth D. Merry softc->callbacks.get_fh = fhanew_get_fh; 78*d96b98a3SKenneth D. Merry softc->callbacks.is_read = fhanew_is_read; 79*d96b98a3SKenneth D. Merry softc->callbacks.is_write = fhanew_is_write; 80*d96b98a3SKenneth D. Merry softc->callbacks.get_offset = fhanew_get_offset; 81*d96b98a3SKenneth D. Merry softc->callbacks.no_offset = fhanew_no_offset; 82*d96b98a3SKenneth D. Merry softc->callbacks.set_locktype = fhanew_set_locktype; 83*d96b98a3SKenneth D. Merry softc->callbacks.fhe_stats_sysctl = fhenew_stats_sysctl; 84*d96b98a3SKenneth D. Merry 85*d96b98a3SKenneth D. Merry snprintf(softc->server_name, sizeof(softc->server_name), 86*d96b98a3SKenneth D. Merry FHANEW_SERVER_NAME); 87*d96b98a3SKenneth D. Merry 88*d96b98a3SKenneth D. Merry softc->pool = &nfsrvd_pool; 89*d96b98a3SKenneth D. Merry 90*d96b98a3SKenneth D. Merry /* 91*d96b98a3SKenneth D. Merry * Initialize the sysctl context list for the fha module. 92*d96b98a3SKenneth D. Merry */ 93*d96b98a3SKenneth D. Merry sysctl_ctx_init(&softc->sysctl_ctx); 94*d96b98a3SKenneth D. Merry softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx, 95*d96b98a3SKenneth D. Merry SYSCTL_STATIC_CHILDREN(_vfs_nfsd), OID_AUTO, "fha", CTLFLAG_RD, 96*d96b98a3SKenneth D. Merry 0, "fha node"); 97*d96b98a3SKenneth D. Merry if (softc->sysctl_tree == NULL) { 98*d96b98a3SKenneth D. Merry printf("%s: unable to allocate sysctl tree\n", __func__); 99*d96b98a3SKenneth D. Merry return; 100*d96b98a3SKenneth D. Merry } 101*d96b98a3SKenneth D. Merry 102*d96b98a3SKenneth D. Merry fha_init(softc); 103*d96b98a3SKenneth D. Merry } 104*d96b98a3SKenneth D. Merry 105*d96b98a3SKenneth D. Merry static void 106*d96b98a3SKenneth D. Merry fhanew_uninit(void *foo) 107*d96b98a3SKenneth D. Merry { 108*d96b98a3SKenneth D. Merry struct fha_params *softc; 109*d96b98a3SKenneth D. Merry 110*d96b98a3SKenneth D. Merry softc = &fhanew_softc; 111*d96b98a3SKenneth D. Merry 112*d96b98a3SKenneth D. Merry fha_uninit(softc); 113*d96b98a3SKenneth D. Merry } 114*d96b98a3SKenneth D. Merry 115*d96b98a3SKenneth D. Merry rpcproc_t 116*d96b98a3SKenneth D. Merry fhanew_get_procnum(rpcproc_t procnum) 117*d96b98a3SKenneth D. Merry { 118*d96b98a3SKenneth D. Merry if (procnum > NFSV2PROC_STATFS) 119*d96b98a3SKenneth D. Merry return (-1); 120*d96b98a3SKenneth D. Merry 121*d96b98a3SKenneth D. Merry return (newnfs_nfsv3_procid[procnum]); 122*d96b98a3SKenneth D. Merry } 123*d96b98a3SKenneth D. Merry 124*d96b98a3SKenneth D. Merry int 125*d96b98a3SKenneth D. Merry fhanew_realign(struct mbuf **mb, int malloc_flags) 126*d96b98a3SKenneth D. Merry { 127*d96b98a3SKenneth D. Merry return (newnfs_realign(mb, malloc_flags)); 128*d96b98a3SKenneth D. Merry } 129*d96b98a3SKenneth D. Merry 130*d96b98a3SKenneth D. Merry int 131*d96b98a3SKenneth D. Merry fhanew_get_fh(fhandle_t *fh, int v3, struct mbuf **md, caddr_t *dpos) 132*d96b98a3SKenneth D. Merry { 133*d96b98a3SKenneth D. Merry struct nfsrv_descript lnd, *nd; 134*d96b98a3SKenneth D. Merry uint32_t *tl; 135*d96b98a3SKenneth D. Merry int error, len; 136*d96b98a3SKenneth D. Merry 137*d96b98a3SKenneth D. Merry error = 0; 138*d96b98a3SKenneth D. Merry len = 0; 139*d96b98a3SKenneth D. Merry nd = &lnd; 140*d96b98a3SKenneth D. Merry 141*d96b98a3SKenneth D. Merry nd->nd_md = *md; 142*d96b98a3SKenneth D. Merry nd->nd_dpos = *dpos; 143*d96b98a3SKenneth D. Merry 144*d96b98a3SKenneth D. Merry if (v3) { 145*d96b98a3SKenneth D. Merry NFSM_DISSECT_NONBLOCK(tl, uint32_t *, NFSX_UNSIGNED); 146*d96b98a3SKenneth D. Merry if ((len = fxdr_unsigned(int, *tl)) <= 0 || len > NFSX_FHMAX) { 147*d96b98a3SKenneth D. Merry error = EBADRPC; 148*d96b98a3SKenneth D. Merry goto nfsmout; 149*d96b98a3SKenneth D. Merry } 150*d96b98a3SKenneth D. Merry } else { 151*d96b98a3SKenneth D. Merry len = NFSX_V2FH; 152*d96b98a3SKenneth D. Merry } 153*d96b98a3SKenneth D. Merry 154*d96b98a3SKenneth D. Merry if (len != 0) { 155*d96b98a3SKenneth D. Merry NFSM_DISSECT_NONBLOCK(tl, uint32_t *, len); 156*d96b98a3SKenneth D. Merry bcopy(tl, fh, len); 157*d96b98a3SKenneth D. Merry } else 158*d96b98a3SKenneth D. Merry bzero(fh, sizeof(*fh)); 159*d96b98a3SKenneth D. Merry 160*d96b98a3SKenneth D. Merry nfsmout: 161*d96b98a3SKenneth D. Merry *md = nd->nd_md; 162*d96b98a3SKenneth D. Merry *dpos = nd->nd_dpos; 163*d96b98a3SKenneth D. Merry 164*d96b98a3SKenneth D. Merry return (error); 165*d96b98a3SKenneth D. Merry } 166*d96b98a3SKenneth D. Merry 167*d96b98a3SKenneth D. Merry int 168*d96b98a3SKenneth D. Merry fhanew_is_read(rpcproc_t procnum) 169*d96b98a3SKenneth D. Merry { 170*d96b98a3SKenneth D. Merry if (procnum == NFSPROC_READ) 171*d96b98a3SKenneth D. Merry return (1); 172*d96b98a3SKenneth D. Merry else 173*d96b98a3SKenneth D. Merry return (0); 174*d96b98a3SKenneth D. Merry } 175*d96b98a3SKenneth D. Merry 176*d96b98a3SKenneth D. Merry int 177*d96b98a3SKenneth D. Merry fhanew_is_write(rpcproc_t procnum) 178*d96b98a3SKenneth D. Merry { 179*d96b98a3SKenneth D. Merry if (procnum == NFSPROC_WRITE) 180*d96b98a3SKenneth D. Merry return (1); 181*d96b98a3SKenneth D. Merry else 182*d96b98a3SKenneth D. Merry return (0); 183*d96b98a3SKenneth D. Merry } 184*d96b98a3SKenneth D. Merry 185*d96b98a3SKenneth D. Merry int 186*d96b98a3SKenneth D. Merry fhanew_get_offset(struct mbuf **md, caddr_t *dpos, int v3, 187*d96b98a3SKenneth D. Merry struct fha_info *info) 188*d96b98a3SKenneth D. Merry { 189*d96b98a3SKenneth D. Merry struct nfsrv_descript lnd, *nd; 190*d96b98a3SKenneth D. Merry uint32_t *tl; 191*d96b98a3SKenneth D. Merry int error; 192*d96b98a3SKenneth D. Merry 193*d96b98a3SKenneth D. Merry error = 0; 194*d96b98a3SKenneth D. Merry 195*d96b98a3SKenneth D. Merry nd = &lnd; 196*d96b98a3SKenneth D. Merry nd->nd_md = *md; 197*d96b98a3SKenneth D. Merry nd->nd_dpos = *dpos; 198*d96b98a3SKenneth D. Merry 199*d96b98a3SKenneth D. Merry if (v3) { 200*d96b98a3SKenneth D. Merry NFSM_DISSECT_NONBLOCK(tl, uint32_t *, 2 * NFSX_UNSIGNED); 201*d96b98a3SKenneth D. Merry info->offset = fxdr_hyper(tl); 202*d96b98a3SKenneth D. Merry } else { 203*d96b98a3SKenneth D. Merry NFSM_DISSECT_NONBLOCK(tl, uint32_t *, NFSX_UNSIGNED); 204*d96b98a3SKenneth D. Merry info->offset = fxdr_unsigned(uint32_t, *tl); 205*d96b98a3SKenneth D. Merry } 206*d96b98a3SKenneth D. Merry 207*d96b98a3SKenneth D. Merry nfsmout: 208*d96b98a3SKenneth D. Merry *md = nd->nd_md; 209*d96b98a3SKenneth D. Merry *dpos = nd->nd_dpos; 210*d96b98a3SKenneth D. Merry 211*d96b98a3SKenneth D. Merry return (error); 212*d96b98a3SKenneth D. Merry } 213*d96b98a3SKenneth D. Merry 214*d96b98a3SKenneth D. Merry int 215*d96b98a3SKenneth D. Merry fhanew_no_offset(rpcproc_t procnum) 216*d96b98a3SKenneth D. Merry { 217*d96b98a3SKenneth D. Merry if (procnum == NFSPROC_FSSTAT || 218*d96b98a3SKenneth D. Merry procnum == NFSPROC_FSINFO || 219*d96b98a3SKenneth D. Merry procnum == NFSPROC_PATHCONF || 220*d96b98a3SKenneth D. Merry procnum == NFSPROC_NOOP || 221*d96b98a3SKenneth D. Merry procnum == NFSPROC_NULL) 222*d96b98a3SKenneth D. Merry return (1); 223*d96b98a3SKenneth D. Merry else 224*d96b98a3SKenneth D. Merry return (0); 225*d96b98a3SKenneth D. Merry } 226*d96b98a3SKenneth D. Merry 227*d96b98a3SKenneth D. Merry void 228*d96b98a3SKenneth D. Merry fhanew_set_locktype(rpcproc_t procnum, struct fha_info *info) 229*d96b98a3SKenneth D. Merry { 230*d96b98a3SKenneth D. Merry switch (procnum) { 231*d96b98a3SKenneth D. Merry case NFSPROC_NULL: 232*d96b98a3SKenneth D. Merry case NFSPROC_GETATTR: 233*d96b98a3SKenneth D. Merry case NFSPROC_LOOKUP: 234*d96b98a3SKenneth D. Merry case NFSPROC_ACCESS: 235*d96b98a3SKenneth D. Merry case NFSPROC_READLINK: 236*d96b98a3SKenneth D. Merry case NFSPROC_READ: 237*d96b98a3SKenneth D. Merry case NFSPROC_READDIR: 238*d96b98a3SKenneth D. Merry case NFSPROC_READDIRPLUS: 239*d96b98a3SKenneth D. Merry case NFSPROC_WRITE: 240*d96b98a3SKenneth D. Merry info->locktype = LK_SHARED; 241*d96b98a3SKenneth D. Merry break; 242*d96b98a3SKenneth D. Merry case NFSPROC_SETATTR: 243*d96b98a3SKenneth D. Merry case NFSPROC_CREATE: 244*d96b98a3SKenneth D. Merry case NFSPROC_MKDIR: 245*d96b98a3SKenneth D. Merry case NFSPROC_SYMLINK: 246*d96b98a3SKenneth D. Merry case NFSPROC_MKNOD: 247*d96b98a3SKenneth D. Merry case NFSPROC_REMOVE: 248*d96b98a3SKenneth D. Merry case NFSPROC_RMDIR: 249*d96b98a3SKenneth D. Merry case NFSPROC_RENAME: 250*d96b98a3SKenneth D. Merry case NFSPROC_LINK: 251*d96b98a3SKenneth D. Merry case NFSPROC_FSSTAT: 252*d96b98a3SKenneth D. Merry case NFSPROC_FSINFO: 253*d96b98a3SKenneth D. Merry case NFSPROC_PATHCONF: 254*d96b98a3SKenneth D. Merry case NFSPROC_COMMIT: 255*d96b98a3SKenneth D. Merry case NFSPROC_NOOP: 256*d96b98a3SKenneth D. Merry info->locktype = LK_EXCLUSIVE; 257*d96b98a3SKenneth D. Merry break; 258*d96b98a3SKenneth D. Merry } 259*d96b98a3SKenneth D. Merry } 260*d96b98a3SKenneth D. Merry 261*d96b98a3SKenneth D. Merry static int 262*d96b98a3SKenneth D. Merry fhenew_stats_sysctl(SYSCTL_HANDLER_ARGS) 263*d96b98a3SKenneth D. Merry { 264*d96b98a3SKenneth D. Merry return (fhe_stats_sysctl(oidp, arg1, arg2, req, &fhanew_softc)); 265*d96b98a3SKenneth D. Merry } 266*d96b98a3SKenneth D. Merry 267*d96b98a3SKenneth D. Merry 268*d96b98a3SKenneth D. Merry SVCTHREAD * 269*d96b98a3SKenneth D. Merry fhanew_assign(SVCTHREAD *this_thread, struct svc_req *req) 270*d96b98a3SKenneth D. Merry { 271*d96b98a3SKenneth D. Merry return (fha_assign(this_thread, req, &fhanew_softc)); 272*d96b98a3SKenneth D. Merry } 273