Date: Fri, 13 Jan 2012 03:38:09 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r230041 - in projects/nfsv4.1-client/sys/fs: nfs nfsclient Message-ID: <201201130338.q0D3c9dE039573@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rmacklem Date: Fri Jan 13 03:38:08 2012 New Revision: 230041 URL: http://svn.freebsd.org/changeset/base/230041 Log: Update the layout handling functions and add new functions that hang the layouts and device info structures for pNFS off of the client id structure. Also, cleaned up the indentation of the client id structure. This code is still untested at this point. Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h projects/nfsv4.1-client/sys/fs/nfs/nfsport.h projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c Fri Jan 13 02:33:55 2012 (r230040) +++ projects/nfsv4.1-client/sys/fs/nfs/nfs_commonport.c Fri Jan 13 03:38:08 2012 (r230041) @@ -104,6 +104,7 @@ MALLOC_DEFINE(M_NEWNFSDIROFF, "NFSCL dir "New NFS directory offset data"); MALLOC_DEFINE(M_NEWNFSDROLLBACK, "NFSD rollback", "New NFS local lock rollback"); +MALLOC_DEFINE(M_NEWNFSLAYOUT, "NFSCL layout", "NFSv4.1 Layout"); MALLOC_DEFINE(M_NEWNFSFLAYOUT, "NFSCL flayout", "NFSv4.1 File Layout"); MALLOC_DEFINE(M_NEWNFSDEVINFO, "NFSCL devinfo", "NFSv4.1 Device Info"); Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h Fri Jan 13 02:33:55 2012 (r230040) +++ projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h Fri Jan 13 03:38:08 2012 (r230041) @@ -74,7 +74,7 @@ struct nfscllockowner; struct nfscllock; struct nfscldeleg; struct nfscllayout; -struct nfsclfldevinfo; +struct nfscldevinfo; struct nfsv4lock; struct nfsvattr; struct nfs_vattr; @@ -444,10 +444,11 @@ int nfsrpc_destroysession(struct nfsmoun struct ucred *, NFSPROC_T *); int nfsrpc_destroyclient(struct nfsmount *, struct nfsclclient *, struct ucred *, NFSPROC_T *); -int nfsrpc_layoutget(vnode_t, int, uint64_t, uint64_t, uint64_t, - struct nfscllayout *, struct ucred *, NFSPROC_T *, void *); +int nfsrpc_layoutget(struct nfsmount *, uint8_t *, int, int, uint64_t, uint64_t, + uint64_t, nfsv4stateid_t *, int *, struct nfsclflayouthead *, + struct ucred *, NFSPROC_T *, void *); int nfsrpc_getdeviceinfo(struct nfsmount *, uint8_t *, int, uint32_t *, - struct nfsclfldevinfo **, struct ucred *, NFSPROC_T *); + struct nfscldevinfo **, struct ucred *, NFSPROC_T *); int nfsrpc_layoutcommit(vnode_t, off_t, uint64_t, int, nfsv4stateid_t *, int, off_t, int, struct timespec, int, int, uint8_t *, int *, uint64_t *, struct ucred *, NFSPROC_T *, void *); @@ -514,6 +515,13 @@ void nfscl_deleggetmodtime(vnode_t, stru int nfscl_tryclose(struct nfsclopen *, struct ucred *, struct nfsmount *, NFSPROC_T *); void nfscl_cleanup(NFSPROC_T *); +int nfscl_layout(struct nfsmount *, u_int8_t *, int, nfsv4stateid_t *, int, + struct nfsclflayouthead *, struct nfscllayout **, struct ucred *, + NFSPROC_T *); +struct nfscllayout *nfscl_getlayout(struct nfsmount *, uint8_t *, int); +void nfscl_rellayout(struct nfscllayout *); +void nfscl_reldevinfo(struct nfscldevinfo *); +void nfscl_adddevinfo(struct nfsmount *, struct nfscldevinfo *); /* nfs_clport.c */ int nfscl_nget(mount_t, vnode_t, struct nfsfh *, Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h Fri Jan 13 02:33:55 2012 (r230040) +++ projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h Fri Jan 13 03:38:08 2012 (r230041) @@ -43,9 +43,18 @@ LIST_HEAD(nfscldeleghash, nfscldeleg); TAILQ_HEAD(nfscllayouthead, nfscllayout); LIST_HEAD(nfscllayouthash, nfscllayout); LIST_HEAD(nfsclflayouthead, nfsclflayout); +TAILQ_HEAD(nfscldevinfohead, nfscldevinfo); +LIST_HEAD(nfscldevinfohash, nfscldevinfo); #define NFSCLDELEGHASHSIZE 256 -#define NFSCLDELEGHASH(c, f, l) \ +#define NFSCLDELEGHASH(c, f, l) \ (&((c)->nfsc_deleghash[ncl_hash((f), (l)) % NFSCLDELEGHASHSIZE])) +#define NFSCLLAYOUTHASHSIZE 256 +#define NFSCLLAYOUTHASH(c, f, l) \ + (&((c)->nfsc_layouthash[ncl_hash((f), (l)) % NFSCLLAYOUTHASHSIZE])) +#define NFSCLDEVINFOHASHSIZE 16 +#define NFSCLDEVINFOHASH(c, f) \ + (&((c)->nfsc_devinfohash[ncl_hash((f), NFSX_V4DEVICEID) % \ + NFSCLDEVINFOHASHSIZE])) /* Structure for NFSv4.1 session stuff. */ struct nfsclsession { @@ -64,18 +73,22 @@ struct nfsclclient { struct nfsclownerhead nfsc_owner; struct nfscldeleghead nfsc_deleg; struct nfscldeleghash nfsc_deleghash[NFSCLDELEGHASHSIZE]; - struct nfsv4lock nfsc_lock; + struct nfscllayouthead nfsc_layout; + struct nfscllayouthash nfsc_layouthash[NFSCLLAYOUTHASHSIZE]; + struct nfscldevinfohead nfsc_devinfo; + struct nfscldevinfohash nfsc_devinfohash[NFSCLDEVINFOHASHSIZE]; + struct nfsv4lock nfsc_lock; struct nfsclsession nfsc_sess; - struct proc *nfsc_renewthread; - struct nfsmount *nfsc_nmp; - time_t nfsc_expire; - u_int32_t nfsc_clientidrev; - u_int32_t nfsc_renew; - u_int32_t nfsc_cbident; - u_int16_t nfsc_flags; - u_int16_t nfsc_backslots; /* Number of back channel slots. */ - u_int16_t nfsc_idlen; - u_int8_t nfsc_id[1]; /* Malloc'd to correct length */ + struct proc *nfsc_renewthread; + struct nfsmount *nfsc_nmp; + time_t nfsc_expire; + u_int32_t nfsc_clientidrev; + u_int32_t nfsc_renew; + u_int32_t nfsc_cbident; + u_int16_t nfsc_flags; + u_int16_t nfsc_backslots; /* # of back channel slots. */ + u_int16_t nfsc_idlen; + u_int8_t nfsc_id[1]; /* Malloc'd to correct length */ }; #define nfsc_mtx nfsc_sess.nfsess_mtx @@ -209,6 +222,7 @@ struct nfscllayout { nfsv4stateid_t nfsly_stateid; struct nfsclflayouthead nfsly_flay; struct nfsclclient *nfsly_clp; + uint32_t nfsly_refcnt; uint16_t nfsly_retonclose; uint16_t nfsly_fhlen; uint8_t nfsly_fh[1]; @@ -240,11 +254,12 @@ struct nfsclflayout { * of them. (This implies a limit of 256 on nfsdi_addrcnt, since the * indices select which address.) */ -struct nfsclfldevinfo { - TAILQ_ENTRY(nfsclfldevinfo) nfsdi_list; - LIST_ENTRY(nfsclfldevinfo) nfsdi_hash; +struct nfscldevinfo { + TAILQ_ENTRY(nfscldevinfo) nfsdi_list; + LIST_ENTRY(nfscldevinfo) nfsdi_hash; uint8_t nfsdi_deviceid[NFSX_V4DEVICEID]; struct nfsclclient *nfsdi_clp; + uint32_t nfsdi_refcnt; uint16_t nfsdi_stripecnt; uint16_t nfsdi_addrcnt; struct sockaddr_storage nfsdi_data[1]; @@ -255,7 +270,7 @@ struct nfsclfldevinfo { * Return a pointer to the address at "pos". */ static __inline struct sockaddr_storage * -nfsfldi_addr(struct nfsclfldevinfo *ndi, int pos) +nfsfldi_addr(struct nfscldevinfo *ndi, int pos) { if (pos >= ndi->nfsdi_addrcnt) @@ -267,7 +282,7 @@ nfsfldi_addr(struct nfsclfldevinfo *ndi, * Return the Nth ("pos") stripe index. */ static __inline int -nfsfldi_stripeindex(struct nfsclfldevinfo *ndi, int pos) +nfsfldi_stripeindex(struct nfscldevinfo *ndi, int pos) { uint8_t *valp; @@ -282,7 +297,7 @@ nfsfldi_stripeindex(struct nfsclfldevinf * Set the Nth ("pos") stripe index to "val". */ static __inline void -nfsfldi_setstripeindex(struct nfsclfldevinfo *ndi, int pos, uint8_t val) +nfsfldi_setstripeindex(struct nfscldevinfo *ndi, int pos, uint8_t val) { uint8_t *valp; Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsport.h ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfs/nfsport.h Fri Jan 13 02:33:55 2012 (r230040) +++ projects/nfsv4.1-client/sys/fs/nfs/nfsport.h Fri Jan 13 03:38:08 2012 (r230041) @@ -428,13 +428,13 @@ struct ext_nfsstats { #include <fs/nfs/rpcv2.h> #include <fs/nfs/nfsproto.h> #include <fs/nfs/nfs.h> +#include <fs/nfs/nfsclstate.h> #include <fs/nfs/nfs_var.h> #include <fs/nfs/nfsm_subs.h> #include <fs/nfs/nfsrvcache.h> #include <fs/nfs/nfsrvstate.h> #include <fs/nfs/xdr_subs.h> #include <fs/nfs/nfscl.h> -#include <fs/nfs/nfsclstate.h> #include <nfsclient/nfsargs.h> #include <fs/nfsclient/nfsmount.h> @@ -732,6 +732,7 @@ MALLOC_DECLARE(M_NEWNFSV4NODE); MALLOC_DECLARE(M_NEWNFSDIRECTIO); MALLOC_DECLARE(M_NEWNFSMNT); MALLOC_DECLARE(M_NEWNFSDROLLBACK); +MALLOC_DECLARE(M_NEWNFSLAYOUT); MALLOC_DECLARE(M_NEWNFSFLAYOUT); MALLOC_DECLARE(M_NEWNFSDEVINFO); #define M_NFSRVCACHE M_NEWNFSRVCACHE @@ -753,6 +754,7 @@ MALLOC_DECLARE(M_NEWNFSDEVINFO); #define M_NFSV4NODE M_NEWNFSV4NODE #define M_NFSDIRECTIO M_NEWNFSDIRECTIO #define M_NFSDROLLBACK M_NEWNFSDROLLBACK +#define M_NFSLAYOUT M_NEWNFSLAYOUT #define M_NFSFLAYOUT M_NEWNFSFLAYOUT #define M_NFSDEVINFO M_NEWNFSDEVINFO Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c Fri Jan 13 02:33:55 2012 (r230040) +++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c Fri Jan 13 03:38:08 2012 (r230041) @@ -85,6 +85,8 @@ static int nfsrpc_locku(struct nfsrv_des u_int32_t, struct ucred *, NFSPROC_T *, int); static int nfsrpc_setaclrpc(vnode_t, struct ucred *, NFSPROC_T *, struct acl *, nfsv4stateid_t *, void *); +static int nfsrpc_getlayout(struct nfsmount *, struct nfsfh *, int, uint32_t *, + nfsv4stateid_t *, struct ucred *, NFSPROC_T *); /* * nfs null call from vfs. @@ -222,6 +224,8 @@ nfsrpc_open(vnode_t vp, int amode, struc struct nfsmount *nmp = VFSTONFS(vnode_mount(vp)); u_int32_t mode, clidrev; int ret, newone, error, expireret = 0, retrycnt; + int iomode; + nfsv4stateid_t stateid; /* * For NFSv4, Open Ops are only done on Regular Files. @@ -229,10 +233,13 @@ nfsrpc_open(vnode_t vp, int amode, struc if (vnode_vtype(vp) != VREG) return (0); mode = 0; + iomode = NFSLAYOUTIOMODE_READ; if (amode & FREAD) mode |= NFSV4OPEN_ACCESSREAD; - if (amode & FWRITE) + if (amode & FWRITE) { mode |= NFSV4OPEN_ACCESSWRITE; + iomode = NFSLAYOUTIOMODE_RW; + } nfhp = np->n_fhp; retrycnt = 0; @@ -284,6 +291,16 @@ else printf(" fhl=0\n"); op->nfso_own->nfsow_clp, nfhp->nfh_fh, nfhp->nfh_len, cred, p, &dp); } + + /* Try and get a Layout, if it is supported. */ + if (error == 0 && NFSHASPNFS(nmp)) { + stateid.seqid = op->nfso_stateid.seqid; + stateid.other[0] = op->nfso_stateid.other[0]; + stateid.other[1] = op->nfso_stateid.other[1]; + stateid.other[2] = op->nfso_stateid.other[2]; + (void)nfsrpc_getlayout(nmp, nfhp, iomode, + NULL, &stateid, cred, p); + } } else { error = EIO; } @@ -4301,6 +4318,11 @@ printf("exch err=%d reps=%d\n",error,nd- clp->nfsc_sequenceid = fxdr_unsigned(uint32_t, *tl++); v41flags = fxdr_unsigned(uint32_t, *tl); printf("v41fl=0x%x\n", v41flags); + if ((v41flags & NFSV4EXCH_USEPNFSMDS) != 0) { + NFSLOCKMNT(nmp); + nmp->nm_state |= NFSSTA_PNFS; + NFSUNLOCKMNT(nmp); + } } error = nd->nd_repstat; nfsmout: @@ -4457,21 +4479,20 @@ nfsrpc_destroyclient(struct nfsmount *nm * Do the NFSv4.1 LayoutGet. */ int -nfsrpc_layoutget(vnode_t vp, int iomode, uint64_t offset, uint64_t len, - uint64_t minlen, struct nfscllayout *lp, struct ucred *cred, +nfsrpc_layoutget(struct nfsmount *nmp, uint8_t *fhp, int fhlen, int iomode, + uint64_t offset, uint64_t len, uint64_t minlen, nfsv4stateid_t *stateidp, + int *retonclosep, struct nfsclflayouthead *flhp, struct ucred *cred, NFSPROC_T *p, void *stuff) { uint32_t *tl; struct nfsrv_descript nfsd, *nd = &nfsd; - struct nfsfh *fhp; - struct nfsclflayout *flp, *nflp, *tflp; - struct nfsnode *np; - int cnt, error, fhcnt, fhlen, i, j; + struct nfsfh *nfhp; + struct nfsclflayout *flp, *prevflp, *tflp; + int cnt, error, fhcnt, nfhlen, i, j; uint8_t *cp; - np = VTONFS(vp); flp = NULL; - NFSCL_REQSTART(nd, NFSPROC_LAYOUTGET, vp); + nfscl_reqstart(nd, NFSPROC_LAYOUTGET, nmp, fhp, fhlen, NULL, NULL); NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER + NFSX_STATEID); *tl++ = newnfs_false; /* Don't signal availability. */ @@ -4483,25 +4504,27 @@ nfsrpc_layoutget(vnode_t vp, int iomode, tl += 2; txdr_hyper(minlen, tl); tl += 2; - *tl++ = lp->nfsly_stateid.seqid; - *tl++ = lp->nfsly_stateid.other[0]; - *tl++ = lp->nfsly_stateid.other[1]; - *tl++ = lp->nfsly_stateid.other[2]; + *tl++ = stateidp->seqid; + *tl++ = stateidp->other[0]; + *tl++ = stateidp->other[1]; + *tl++ = stateidp->other[2]; *tl = txdr_unsigned(100000); /* take a large layout list */ nd->nd_flag |= ND_USEGSSNAME; - error = nfscl_request(nd, vp, p, cred, stuff); + error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred, + NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL); if (error) return (error); if (nd->nd_repstat == 0) { NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_STATEID); - if (*tl++ != 0) { - lp->nfsly_retonclose = 1; -printf("layg setting retonclose\n"); - } - lp->nfsly_stateid.seqid = *tl++; - lp->nfsly_stateid.other[0] = *tl++; - lp->nfsly_stateid.other[1] = *tl++; - lp->nfsly_stateid.other[2] = *tl++; + if (*tl++ != 0) + *retonclosep = 1; + else + *retonclosep = 0; +printf("retonclose=%d\n", *retonclosep); + stateidp->seqid = *tl++; + stateidp->other[0] = *tl++; + stateidp->other[1] = *tl++; + stateidp->other[2] = *tl++; cnt = fxdr_unsigned(int, *tl); printf("layg cnt=%d\n", cnt); if (cnt <= 0 || cnt > 10000) { @@ -4551,35 +4574,31 @@ printf("layg iom=%d\n", iomode); } for (j = 0; j < fhcnt; j++) { NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); - fhlen = fxdr_unsigned(int, *tl); - if (fhlen <= 0 || fhlen > NFSX_V4FHMAX) { + nfhlen = fxdr_unsigned(int, *tl); + if (nfhlen <= 0 || nfhlen > NFSX_V4FHMAX) { error = NFSERR_BADXDR; goto nfsmout; } - fhp = malloc(sizeof(*fhp) + fhlen - 1, + nfhp = malloc(sizeof(*nfhp) + nfhlen - 1, M_NFSFH, M_WAITOK); - flp->nfsfl_fh[j] = fhp; + flp->nfsfl_fh[j] = nfhp; flp->nfsfl_fhcnt++; - fhp->nfh_len = fhlen; + nfhp->nfh_len = nfhlen; NFSM_DISSECT(cp, uint8_t *, NFSM_RNDUP(fhlen)); - NFSBCOPY(cp, fhp->nfh_fh, fhlen); + NFSBCOPY(cp, nfhp->nfh_fh, nfhlen); } - if (LIST_EMPTY(&lp->nfsly_flay) || - LIST_FIRST(&lp->nfsly_flay)->nfsfl_off >= - flp->nfsfl_off) - LIST_INSERT_HEAD(&lp->nfsly_flay, flp, - nfsfl_list); - else { - nflp = LIST_FIRST(&lp->nfsly_flay); - tflp = LIST_NEXT(nflp, nfsfl_list); - while (tflp != NULL) { - if (tflp->nfsfl_off >= flp->nfsfl_off) - break; - nflp = tflp; - tflp = LIST_NEXT(tflp, nfsfl_list); - } - LIST_INSERT_AFTER(nflp, flp, nfsfl_list); + /* Maintain the list in increasing offset order. */ + tflp = LIST_FIRST(flhp); + prevflp = NULL; + while (tflp != NULL && + tflp->nfsfl_off < flp->nfsfl_off) { + prevflp = tflp; + tflp = LIST_NEXT(tflp, nfsfl_list); } + if (prevflp == NULL) + LIST_INSERT_HEAD(flhp, flp, nfsfl_list); + else + LIST_INSERT_AFTER(prevflp, flp, nfsfl_list); flp = NULL; } } @@ -4600,14 +4619,14 @@ nfsmout: */ int nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *deviceid, int layouttype, - uint32_t *notifybitsp, struct nfsclfldevinfo **ndip, struct ucred *cred, + uint32_t *notifybitsp, struct nfscldevinfo **ndip, struct ucred *cred, NFSPROC_T *p) { uint32_t cnt, *tl; struct nfsrv_descript nfsd; struct sockaddr_storage ss, *sa; struct nfsrv_descript *nd = &nfsd; - struct nfsclfldevinfo *ndi; + struct nfscldevinfo *ndi; int addrcnt, bitcnt, error, i, isudp, j, pos, safilled, stripecnt; uint8_t stripeindex; @@ -4659,6 +4678,7 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm sizeof(struct sockaddr_storage), M_NFSDEVINFO, M_WAITOK); NFSBCOPY(deviceid, ndi->nfsdi_deviceid, NFSX_V4DEVICEID); + ndi->nfsdi_refcnt = 0; ndi->nfsdi_stripecnt = stripecnt; ndi->nfsdi_addrcnt = addrcnt; /* Fill in the stripe indices. */ @@ -4877,3 +4897,43 @@ nfsmout: return (error); } +/* + * Called from nfsrpc_open() to acquire a layout and associated device + * info. A separate function mostly to avoid excessive indentation in + * nfsrpc_open(). + */ +static int +nfsrpc_getlayout(struct nfsmount *nmp, struct nfsfh *nfhp, int iomode, + uint32_t *notifybitsp, nfsv4stateid_t *stateidp, struct ucred *cred, + NFSPROC_T *p) +{ + struct nfscllayout *lyp; + struct nfsclflayout *flp; + struct nfscldevinfo *dip; + struct nfsclflayouthead flh; + int error = 0, retonclose; + + lyp = nfscl_getlayout(nmp, nfhp->nfh_fh, nfhp->nfh_len); + if (lyp == NULL) { + LIST_INIT(&flh); + error = nfsrpc_layoutget(nmp, nfhp->nfh_fh, nfhp->nfh_len, + iomode, (uint64_t)0, INT64_MAX, (uint64_t)(4 * NFS_MAXDATA), + stateidp, &retonclose, &flh, cred, p, NULL); + if (error == 0) + LIST_FOREACH(flp, &flh, nfsfl_list) { + error = nfsrpc_getdeviceinfo(nmp, + flp->nfsfl_dev, NFSLAYOUT_NFSV4_1_FILES, + notifybitsp, &dip, cred, p); + if (error != 0) + break; + nfscl_adddevinfo(nmp, dip); + } + if (error == 0) + error = nfscl_layout(nmp, nfhp->nfh_fh, nfhp->nfh_len, + stateidp, retonclose, &flh, &lyp, cred, p); + } + if (lyp != NULL) + nfscl_rellayout(lyp); + return (error); +} + Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c ============================================================================== --- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c Fri Jan 13 02:33:55 2012 (r230040) +++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c Fri Jan 13 03:38:08 2012 (r230041) @@ -92,9 +92,11 @@ NFSCLSTATEMUTEX; int nfscl_inited = 0; struct nfsclhead nfsclhead; /* Head of clientid list */ int nfscl_deleghighwater = NFSCLDELEGHIGHWATER; +int nfscl_layouthighwater = NFSCLLAYOUTHIGHWATER; #endif /* !APPLEKEXT */ static int nfscl_delegcnt = 0; +static int nfscl_layoutcnt = 0; static int nfscl_getopen(struct nfsclownerhead *, u_int8_t *, int, u_int8_t *, u_int8_t *, u_int32_t, struct nfscllockowner **, struct nfsclopen **); static void nfscl_clrelease(struct nfsclclient *); @@ -115,6 +117,9 @@ static struct nfsclclient *nfscl_getclnt static struct nfsclclient *nfscl_getclntsess(uint8_t *); static struct nfscldeleg *nfscl_finddeleg(struct nfsclclient *, u_int8_t *, int); +static struct nfscllayout *nfscl_findlayout(struct nfsclclient *, u_int8_t *, + int); +static struct nfscldevinfo *nfscl_finddevinfo(struct nfsclclient *, uint8_t *); static int nfscl_checkconflict(struct nfscllockownerhead *, struct nfscllock *, u_int8_t *, struct nfscllock **); static void nfscl_freealllocks(struct nfscllockownerhead *, int); @@ -148,6 +153,8 @@ static int nfscl_trydelegreturn(struct n struct nfsmount *, NFSPROC_T *); static void nfscl_emptylockowner(struct nfscllockowner *, struct nfscllockownerfhhead *); +static void nfscl_mergeflayouts(struct nfsclflayouthead *, + struct nfsclflayouthead *); static short nfscberr_null[] = { 0, @@ -749,8 +756,14 @@ nfscl_getcl(struct mount *mp, struct ucr clp->nfsc_idlen = idlen; LIST_INIT(&clp->nfsc_owner); TAILQ_INIT(&clp->nfsc_deleg); + TAILQ_INIT(&clp->nfsc_layout); + TAILQ_INIT(&clp->nfsc_devinfo); for (i = 0; i < NFSCLDELEGHASHSIZE; i++) LIST_INIT(&clp->nfsc_deleghash[i]); + for (i = 0; i < NFSCLLAYOUTHASHSIZE; i++) + LIST_INIT(&clp->nfsc_layouthash[i]); + for (i = 0; i < NFSCLDEVINFOHASHSIZE; i++) + LIST_INIT(&clp->nfsc_devinfohash[i]); clp->nfsc_flags = NFSCLFLAGS_INITED; clp->nfsc_clientidrev = 1; clp->nfsc_cbident = nfscl_nextcbident(); @@ -4373,3 +4386,200 @@ nfscl_errmap(struct nfsrv_descript *nd) return (txdr_unsigned(*defaulterrp)); } +/* + * Called to find/add a layout to a client. + */ +APPLESTATIC int +nfscl_layout(struct nfsmount *nmp, u_int8_t *fhp, int fhlen, + nfsv4stateid_t *stateidp, int retonclose, + struct nfsclflayouthead *fhlp, struct nfscllayout **lypp, + struct ucred *cred, NFSPROC_T *p) +{ + struct nfsclclient *clp; + struct nfscllayout *lyp, *tlyp; + + *lypp = NULL; + tlyp = malloc(sizeof(*tlyp) + fhlen - 1, M_NFSLAYOUT, M_WAITOK); + + NFSLOCKCLSTATE(); + clp = nmp->nm_clp; + if (clp == NULL) { + NFSUNLOCKCLSTATE(); + free(tlyp, M_NFSLAYOUT); + return (EPERM); + } + lyp = nfscl_findlayout(clp, fhp, fhlen); + if (lyp == NULL) { + lyp = tlyp; + tlyp = NULL; + lyp->nfsly_stateid.seqid = stateidp->seqid; + lyp->nfsly_stateid.other[0] = stateidp->other[0]; + lyp->nfsly_stateid.other[1] = stateidp->other[1]; + lyp->nfsly_stateid.other[2] = stateidp->other[2]; + LIST_INIT(&lyp->nfsly_flay); + lyp->nfsly_clp = clp; + lyp->nfsly_retonclose = retonclose; + lyp->nfsly_refcnt = 1; /* Return with a reference cnt. */ + lyp->nfsly_fhlen = fhlen; + NFSBCOPY(fhp, lyp->nfsly_fh, fhlen); + TAILQ_INSERT_HEAD(&clp->nfsc_layout, lyp, nfsly_list); + LIST_INSERT_HEAD(NFSCLLAYOUTHASH(clp, fhp, fhlen), lyp, + nfsly_hash); +#ifdef notyet + lyp->nfsly_timestamp = NFSD_MONOSEC + 120; +#endif + nfscl_layoutcnt++; + } else { + lyp->nfsly_refcnt++; + TAILQ_REMOVE(&clp->nfsc_layout, lyp, nfsly_list); + TAILQ_INSERT_HEAD(&clp->nfsc_layout, lyp, nfsly_list); + } + + /* Merge the new list of File Layouts into the list. */ + nfscl_mergeflayouts(&lyp->nfsly_flay, fhlp); + NFSUNLOCKCLSTATE(); + if (tlyp != NULL) + free(tlyp, M_NFSLAYOUT); + *lypp = lyp; + return (0); +} + +/* + * Search for a layout by MDS file handle. If one is found, lock it it and + * return a pointer to it. + */ +struct nfscllayout * +nfscl_getlayout(struct nfsmount *nmp, uint8_t *fhp, int fhlen) +{ + struct nfsclclient *clp; + struct nfscllayout *lyp; + + NFSLOCKCLSTATE(); + clp = nmp->nm_clp; + if (clp == NULL) { + NFSUNLOCKCLSTATE(); + return (NULL); + } + lyp = nfscl_findlayout(clp, fhp, fhlen); + if (lyp != NULL) { + lyp->nfsly_refcnt++; + TAILQ_REMOVE(&clp->nfsc_layout, lyp, nfsly_list); + TAILQ_INSERT_HEAD(&clp->nfsc_layout, lyp, nfsly_list); + } + NFSUNLOCKCLSTATE(); + return (lyp); +} + +/* + * Dereference a layout. + */ +void +nfscl_rellayout(struct nfscllayout *lyp) +{ + + NFSLOCKCLSTATE(); + lyp->nfsly_refcnt--; + if (lyp->nfsly_refcnt == 0) + wakeup(&lyp->nfsly_refcnt); + NFSUNLOCKCLSTATE(); +} + +/* + * Dereference a devinfo structure. + */ +void +nfscl_reldevinfo(struct nfscldevinfo *dip) +{ + + NFSLOCKCLSTATE(); + dip->nfsdi_refcnt--; + if (dip->nfsdi_refcnt == 0) + wakeup(&dip->nfsdi_refcnt); + NFSUNLOCKCLSTATE(); +} + +/* + * Find a layout for this file handle. Return NULL upon failure. + */ +static struct nfscllayout * +nfscl_findlayout(struct nfsclclient *clp, u_int8_t *fhp, int fhlen) +{ + struct nfscllayout *lyp; + + LIST_FOREACH(lyp, NFSCLLAYOUTHASH(clp, fhp, fhlen), nfsly_hash) + if (lyp->nfsly_fhlen == fhlen && + !NFSBCMP(lyp->nfsly_fh, fhp, fhlen)) + break; + return (lyp); +} + +/* + * Find a devinfo for this deviceid. Return NULL upon failure. + */ +static struct nfscldevinfo * +nfscl_finddevinfo(struct nfsclclient *clp, uint8_t *deviceid) +{ + struct nfscldevinfo *dip; + + LIST_FOREACH(dip, NFSCLDEVINFOHASH(clp, deviceid), nfsdi_hash) + if (NFSBCMP(dip->nfsdi_deviceid, deviceid, NFSX_V4DEVICEID) + == 0) + break; + return (dip); +} + +/* + * Merge the new file layout list into the main one, maintaining it in + * increasing offset order. + */ +static void +nfscl_mergeflayouts(struct nfsclflayouthead *fhlp, + struct nfsclflayouthead *newfhlp) +{ + struct nfsclflayout *flp, *nflp, *prevflp, *tflp; + + flp = LIST_FIRST(fhlp); + prevflp = NULL; + LIST_FOREACH_SAFE(nflp, newfhlp, nfsfl_list, tflp) { + while (flp != NULL && flp->nfsfl_off < nflp->nfsfl_off) { + prevflp = flp; + flp = LIST_NEXT(flp, nfsfl_list); + } + if (prevflp == NULL) + LIST_INSERT_HEAD(fhlp, nflp, nfsfl_list); + else + LIST_INSERT_AFTER(prevflp, nflp, nfsfl_list); + prevflp = nflp; + } +} + +/* + * Add this nfscldevinfo to the client, if it doesn't already exist. + * This function consumes the structure pointed at by dip. + */ +APPLESTATIC void +nfscl_adddevinfo(struct nfsmount *nmp, struct nfscldevinfo *dip) +{ + struct nfsclclient *clp; + struct nfscldevinfo *tdip; + + NFSLOCKCLSTATE(); + clp = nmp->nm_clp; + if (clp == NULL) { + NFSUNLOCKCLSTATE(); + free(dip, M_NFSDEVINFO); + return; + } + tdip = nfscl_finddevinfo(clp, dip->nfsdi_deviceid); + if (tdip != NULL) { + nfscl_reldevinfo(tdip); + NFSUNLOCKCLSTATE(); + free(dip, M_NFSDEVINFO); + return; + } + TAILQ_INSERT_HEAD(&clp->nfsc_devinfo, dip, nfsdi_list); + LIST_INSERT_HEAD(NFSCLDEVINFOHASH(clp, dip->nfsdi_deviceid), dip, + nfsdi_hash); + NFSUNLOCKCLSTATE(); +} +
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201201130338.q0D3c9dE039573>