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