The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=cf523f4beb8ff148828694485ab56f2c1f8f0159
commit cf523f4beb8ff148828694485ab56f2c1f8f0159 Author: Rick Macklem <[email protected]> AuthorDate: 2026-06-23 01:21:08 +0000 Commit: Rick Macklem <[email protected]> CommitDate: 2026-06-23 01:21:08 +0000 nfscl: Add support for flexible file layout striping Commit 72e57bc26417 added support for striping to the pNFS server configuration. This patch adds support for striping to the NFS client. For striped flexible file layouts, an extra structure must be malloc()d for each stripe, since the number of stripe servers can vary from one mirror to another. This new structure is called nfsffs and a single one of these structures is in the nfsffm structure so that the non-striped layouts can avoid the additional malloc()'s. This patch only affects NFSv4.1/4.2 mounts that use the "pnfs" mount option against servers that support the flexible file layout. --- sys/fs/nfs/nfs_var.h | 2 +- sys/fs/nfs/nfsclstate.h | 10 +- sys/fs/nfsclient/nfs_clrpcops.c | 305 ++++++++++++++++++++++++++-------------- sys/fs/nfsclient/nfs_clstate.c | 36 +++-- 4 files changed, 234 insertions(+), 119 deletions(-) diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index 00ed32ae705e..525f573b5167 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -661,7 +661,7 @@ void nfscl_rellayout(struct nfscllayout *, int); struct nfscldevinfo *nfscl_getdevinfo(struct nfsclclient *, uint8_t *, struct nfscldevinfo *); void nfscl_reldevinfo(struct nfscldevinfo *); -int nfscl_adddevinfo(struct nfsmount *, struct nfscldevinfo *, int, +int nfscl_adddevinfo(struct nfsmount *, struct nfscldevinfo *, int, int, struct nfsclflayout *); void nfscl_freelayout(struct nfscllayout *); void nfscl_freeflayout(struct nfsclflayout *); diff --git a/sys/fs/nfs/nfsclstate.h b/sys/fs/nfs/nfsclstate.h index 92669ff8d1aa..860a2bd1d4c3 100644 --- a/sys/fs/nfs/nfsclstate.h +++ b/sys/fs/nfs/nfsclstate.h @@ -281,17 +281,23 @@ struct nfscllayout { /* * Flex file layout mirror specific stuff for nfsclflayout. */ -struct nfsffm { +struct nfsffs { nfsv4stateid_t st; struct nfscldevinfo *devp; + struct nfsfh *fh[NFSDEV_MAXVERS]; char dev[NFSX_V4DEVICEID]; uint32_t eff; uid_t user; gid_t group; - struct nfsfh *fh[NFSDEV_MAXVERS]; uint16_t fhcnt; }; +struct nfsffm { + struct nfsffs nonstriped; + struct nfsffs *stripep; + uint16_t stripecnt; +}; + /* * MALLOC'd to the correct length to accommodate the file handle list for File * layout and the list of mirrors for the Flex File Layout. diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c index 812bb5279e07..fedfc7259197 100644 --- a/sys/fs/nfsclient/nfs_clrpcops.c +++ b/sys/fs/nfsclient/nfs_clrpcops.c @@ -158,12 +158,16 @@ static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_in *, struct sockaddr_in6 *, sa_family_t, int, int, struct nfsclds **, NFSPROC_T *); static void nfscl_initsessionslots(struct nfsclsession *); +static struct nfscldevinfo **nfscl_getdevlist(struct nfsclclient *, + struct nfsclflayout *, int); +static void nfscl_reldevlist(struct nfscldevinfo **, struct nfsclflayout *, + int); static int nfscl_doflayoutio(vnode_t, struct uio *, int *, int *, int *, nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *, struct nfsclflayout *, uint64_t, uint64_t, int, struct ucred *, NFSPROC_T *); static int nfscl_dofflayoutio(vnode_t, struct uio *, int *, int *, int *, - nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *, + nfsv4stateid_t *, int, struct nfscldevinfo **, struct nfscllayout *, struct nfsclflayout *, uint64_t, uint64_t, int, int, struct mbuf *, struct nfsclwritedsdorpc *, struct ucred *, NFSPROC_T *); static int nfsrpc_readds(vnode_t, struct uio *, nfsv4stateid_t *, int *, @@ -6552,7 +6556,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit, struct nfsnode *np = VTONFS(vp); struct nfsmount *nmp = VFSTONFS(vp->v_mount); struct nfscllayout *layp; - struct nfscldevinfo *dip; + struct nfscldevinfo *dip, **dpp; struct nfsclflayout *rflp; struct mbuf *m, *m2; struct nfsclwritedsdorpc *drpc, *tdrpc; @@ -6683,34 +6687,37 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit, m = NULL; } if ((layp->nfsly_flags & NFSLY_FLEXFILE) != 0) { - dev = rflp->nfsfl_ffm[i].dev; - dip = nfscl_getdevinfo(nmp->nm_clp, dev, - rflp->nfsfl_ffm[i].devp); - } else { - dev = rflp->nfsfl_dev; - dip = nfscl_getdevinfo(nmp->nm_clp, dev, - rflp->nfsfl_devp); - } - if (dip != NULL) { - if ((rflp->nfsfl_flags & NFSFL_FLEXFILE) - != 0) + dpp = nfscl_getdevlist(nmp->nm_clp, + rflp, i); + if (dpp != NULL) { error = nfscl_dofflayoutio(vp, uiop, iomode, must_commit, &eof, &stateid, rwaccess, - dip, layp, rflp, off, xfer, + dpp, layp, rflp, off, xfer, i, docommit, m2, tdrpc, newcred, p); - else + nfscl_reldevlist(dpp, rflp, i); + } else { + if (m2 != NULL) + m_freem(m2); + error = EIO; + } + } else { + dev = rflp->nfsfl_dev; + dip = nfscl_getdevinfo(nmp->nm_clp, dev, + rflp->nfsfl_devp); + if (dip != NULL) { error = nfscl_doflayoutio(vp, uiop, iomode, must_commit, &eof, &stateid, rwaccess, dip, layp, rflp, off, xfer, docommit, newcred, p); - nfscl_reldevinfo(dip); - } else { - if (m2 != NULL) - m_freem(m2); - error = EIO; + nfscl_reldevinfo(dip); + } else { + if (m2 != NULL) + m_freem(m2); + error = EIO; + } } tdrpc++; } @@ -6794,6 +6801,52 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit, return (error); } +/* + * Get the list of device structures for a mirror for a flex file layout. + * (If any stripe entry is missing, return NULL, since the mirror cannot + * be used.) + */ +static struct nfscldevinfo ** +nfscl_getdevlist(struct nfsclclient *clp, struct nfsclflayout *flp, int mirror) +{ + struct nfscldevinfo **dpp, **tdpp; + struct nfsffs *sp; + int i, j; + + dpp = tdpp = malloc(sizeof(*dpp) * flp->nfsfl_ffm[mirror].stripecnt, + M_TEMP, M_WAITOK); + sp = flp->nfsfl_ffm[mirror].stripep; + for (i = 0; i < flp->nfsfl_ffm[mirror].stripecnt; i++, sp++, tdpp++) { + *tdpp = nfscl_getdevinfo(clp, sp->dev, sp->devp); + if (*tdpp == NULL) { + tdpp = dpp; + for (j = 0; j < i; j++, tdpp++) + nfscl_reldevinfo(*tdpp); + free(dpp, M_TEMP); + return (NULL); + } + } + return (dpp); +} + +/* + * Release a device list for a flex file mirror. + */ +static void +nfscl_reldevlist(struct nfscldevinfo **dpp, struct nfsclflayout *flp, + int mirror) +{ + struct nfscldevinfo **tdpp; + int i; + + tdpp = dpp; + for (i = 0; i < flp->nfsfl_ffm[mirror].stripecnt; i++, tdpp++) { + KASSERT(*tdpp != NULL, ("nfscl_reldevlist: NULL devinfo")); + nfscl_reldevinfo(*tdpp); + } + free(dpp, M_TEMP); +} + /* * Find a file layout that will handle the first bytes of the requested * range and return the information from it needed to the I/O operation. @@ -6944,16 +6997,18 @@ nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit, */ static int nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit, - int *eofp, nfsv4stateid_t *stateidp, int rwflag, struct nfscldevinfo *dp, + int *eofp, nfsv4stateid_t *stateidp, int rwflag, struct nfscldevinfo **dpp, struct nfscllayout *lyp, struct nfsclflayout *flp, uint64_t off, uint64_t len, int mirror, int docommit, struct mbuf *mp, struct nfsclwritedsdorpc *drpc, struct ucred *cred, NFSPROC_T *p) { - uint64_t xfer; - int error; + uint64_t xfer, transfer; + int error, stripe_pos; struct nfsnode *np; struct nfsfh *fhp; struct nfsclds **dspp; + struct nfscldevinfo *dp; + struct nfsffs *sp; struct ucred *tcred; struct mbuf *m, *m2; uint32_t copylen; @@ -6964,15 +7019,37 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit, (uintmax_t)len); /* Loop around, doing I/O for each stripe unit. */ while (len > 0 && error == 0) { + if (flp->nfsfl_stripeunit > 0 && + flp->nfsfl_ffm[mirror].stripecnt > 1) { + stripe_pos = (off / flp->nfsfl_stripeunit) % + flp->nfsfl_ffm[mirror].stripecnt; + transfer = flp->nfsfl_stripeunit - + (off % flp->nfsfl_stripeunit); + transfer = (len < transfer) ? len : transfer; + } else { + /* Only one stripe. */ + if (flp->nfsfl_ffm[mirror].stripecnt != 1) { + printf("nfscl_dofflayoutio: stripecnt=%d\n", + flp->nfsfl_ffm[mirror].stripecnt); + error = EIO; + break; + } + stripe_pos = 0; + transfer = len; + } + dp = dpp[stripe_pos]; dspp = nfsfldi_addr(dp, 0); - fhp = flp->nfsfl_ffm[mirror].fh[dp->nfsdi_versindex]; - stateidp = &flp->nfsfl_ffm[mirror].st; - NFSCL_DEBUG(4, "mirror=%d vind=%d fhlen=%d st.seqid=0x%x\n", - mirror, dp->nfsdi_versindex, fhp->nfh_len, stateidp->seqid); + sp = flp->nfsfl_ffm[mirror].stripep; + sp += stripe_pos; + fhp = sp->fh[dp->nfsdi_versindex]; + stateidp = &sp->st; + NFSCL_DEBUG(4, "mirror=%d stripe=%d vind=%d fhlen=%d " + "st.seqid=0x%x\n", mirror, stripe_pos, + dp->nfsdi_versindex, fhp->nfh_len, stateidp->seqid); if ((dp->nfsdi_flags & NFSDI_TIGHTCOUPLED) == 0) { tcred = NFSNEWCRED(cred); - tcred->cr_uid = flp->nfsfl_ffm[mirror].user; - tcred->cr_gid = flp->nfsfl_ffm[mirror].group; + tcred->cr_uid = sp->user; + tcred->cr_gid = sp->group; tcred->cr_ngroups = 0; } else tcred = cred; @@ -6980,7 +7057,7 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit, copylen = dp->nfsdi_rsize; else { copylen = dp->nfsdi_wsize; - if (len > copylen && mp != NULL) { + if (transfer > copylen && mp != NULL) { /* * When a mirrored configuration needs to do * multiple writes to each mirror, all writes @@ -7000,10 +7077,10 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit, NFSLOCKNODE(np); np->n_flag |= NDSCOMMIT; NFSUNLOCKNODE(np); - if (len > copylen && docommit == 0) + if (transfer > copylen && docommit == 0) xfer = copylen; else - xfer = len; + xfer = transfer; if (docommit != 0) { if (error == 0) { /* @@ -7990,6 +8067,7 @@ nfsrv_parselayoutget(struct nfsmount *nmp, struct nfsrv_descript *nd, { uint32_t *tl; struct nfsclflayout *flp, *prevflp, *tflp; + struct nfsffs *sp; int cnt, error, fhcnt, gotiomode, i, iomode, j, k, l, laytype, nfhlen; int m, mirrorcnt; uint64_t retlen, off; @@ -8104,7 +8182,7 @@ nfsrv_parselayoutget(struct nfsmount *nmp, struct nfsrv_descript *nd, flp->nfsfl_flags = NFSFL_FLEXFILE; flp->nfsfl_mirrorcnt = mirrorcnt; for (j = 0; j < mirrorcnt; j++) - flp->nfsfl_ffm[j].devp = NULL; + flp->nfsfl_ffm[j].stripep = NULL; flp->nfsfl_off = off; if (flp->nfsfl_off + retlen < flp->nfsfl_off) flp->nfsfl_end = UINT64_MAX - flp->nfsfl_off; @@ -8119,43 +8197,45 @@ nfsrv_parselayoutget(struct nfsmount *nmp, struct nfsrv_descript *nd, for (j = 0; j < mirrorcnt; j++) { NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); k = fxdr_unsigned(int, *tl); - if (k < 1 || k > 128) { + if (k < 1 || k > NFSDEV_MAXSTRIPE || + (k != 1 && flp->nfsfl_stripeunit == 0)) { error = NFSERR_BADXDR; goto nfsmout; } - NFSCL_DEBUG(4, "servercnt=%d\n", k); - for (l = 0; l < k; l++) { + NFSCL_DEBUG(4, "stripecnt=%d\n", k); + flp->nfsfl_ffm[j].stripecnt = k; + if (k > 1) + flp->nfsfl_ffm[j].stripep = sp = + malloc(k * sizeof(*sp), + M_NFSFLAYOUT, M_WAITOK); + else + flp->nfsfl_ffm[j].stripep = sp = + &flp->nfsfl_ffm[j].nonstriped; + for (l = 0; l < k; l++, sp++) { + sp->devp = NULL; + sp->fhcnt = 0; + for (m = 0; m < NFSDEV_MAXVERS; m++) + sp->fh[m] = NULL; + } + sp = flp->nfsfl_ffm[j].stripep; + for (l = 0; l < k; l++, sp++) { NFSM_DISSECT(tl, uint32_t *, NFSX_V4DEVICEID + NFSX_STATEID + 2 * NFSX_UNSIGNED); - if (l == 0) { - /* Just use the first server. */ - NFSBCOPY(tl, - flp->nfsfl_ffm[j].dev, - NFSX_V4DEVICEID); - tl += (NFSX_V4DEVICEID / - NFSX_UNSIGNED); - tl++; - flp->nfsfl_ffm[j].st.seqid = - *tl++; - flp->nfsfl_ffm[j].st.other[0] = - *tl++; - flp->nfsfl_ffm[j].st.other[1] = - *tl++; - flp->nfsfl_ffm[j].st.other[2] = - *tl++; - NFSCL_DEBUG(4, "st.seqid=%u " - "st.o0=0x%x st.o1=0x%x " - "st.o2=0x%x\n", - flp->nfsfl_ffm[j].st.seqid, - flp->nfsfl_ffm[j].st.other[0], - flp->nfsfl_ffm[j].st.other[1], - flp->nfsfl_ffm[j].st.other[2]); - } else - tl += ((NFSX_V4DEVICEID + - NFSX_STATEID + - NFSX_UNSIGNED) / - NFSX_UNSIGNED); + NFSBCOPY(tl, sp->dev, NFSX_V4DEVICEID); + tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED); + tl++; + sp->st.seqid = *tl++; + sp->st.other[0] = *tl++; + sp->st.other[1] = *tl++; + sp->st.other[2] = *tl++; + NFSCL_DEBUG(4, "st.seqid=%u " + "st.o0=0x%x st.o1=0x%x " + "st.o2=0x%x\n", + sp->st.seqid, + sp->st.other[0], + sp->st.other[1], + sp->st.other[2]); fhcnt = fxdr_unsigned(int, *tl); NFSCL_DEBUG(4, "fhcnt=%d\n", fhcnt); if (fhcnt < 1 || @@ -8177,22 +8257,15 @@ nfsrv_parselayoutget(struct nfsmount *nmp, struct nfsrv_descript *nd, } NFSM_DISSECT(cp, uint8_t *, NFSM_RNDUP(nfhlen)); - if (l == 0) { - flp->nfsfl_ffm[j].fhcnt - = fhcnt; - nfhp = malloc( - sizeof(*nfhp) + - nfhlen - 1, M_NFSFH, - M_WAITOK); - flp->nfsfl_ffm[j].fh[m] - = nfhp; - nfhp->nfh_len = nfhlen; - NFSBCOPY(cp, - nfhp->nfh_fh, - nfhlen); - NFSCL_DEBUG(4, - "got fh\n"); - } + nfhp = malloc(sizeof(*nfhp) + + nfhlen - 1, M_NFSFH, + M_WAITOK); + sp->fh[m] = nfhp; + sp->fhcnt++; + nfhp->nfh_len = nfhlen; + NFSBCOPY(cp, nfhp->nfh_fh, + nfhlen); + NFSCL_DEBUG(4, "got fh\n"); } /* Now, get the ffsd_user/ffds_group. */ error = nfsrv_parseug(nd, 0, &user, @@ -8208,13 +8281,10 @@ nfsrv_parselayoutget(struct nfsmount *nmp, struct nfsrv_descript *nd, goto nfsmout; NFSCL_DEBUG(4, "user=%d group=%d\n", user, grp); - if (l == 0) { - flp->nfsfl_ffm[j].user = user; - flp->nfsfl_ffm[j].group = grp; - NFSCL_DEBUG(4, - "usr=%d grp=%d\n", user, - grp); - } + sp->user = user; + sp->group = grp; + NFSCL_DEBUG(4, "usr=%d grp=%d\n", user, + grp); } } NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); @@ -8905,8 +8975,8 @@ nfsrpc_layoutgetres(struct nfsmount *nmp, vnode_t vp, uint8_t *newfhp, { struct nfsclflayout *tflp; struct nfscldevinfo *dip; - uint8_t *dev; - int i, mirrorcnt; + struct nfsffs *sp; + int i, j; if (laystat == NFSERR_UNKNLAYOUTTYPE) { NFSLOCKMNT(nmp); @@ -8923,27 +8993,54 @@ nfsrpc_layoutgetres(struct nfsmount *nmp, vnode_t vp, uint8_t *newfhp, if (laystat == 0) { NFSCL_DEBUG(4, "nfsrpc_layoutgetres at FOREACH\n"); LIST_FOREACH(tflp, flhp, nfsfl_list) { - if (layouttype == NFSLAYOUT_FLEXFILE) - mirrorcnt = tflp->nfsfl_mirrorcnt; - else - mirrorcnt = 1; - for (i = 0; i < mirrorcnt; i++) { - laystat = nfscl_adddevinfo(nmp, NULL, i, tflp); + if (layouttype == NFSLAYOUT_FLEXFILE) { + for (i = 0; i < tflp->nfsfl_mirrorcnt; i++) { + sp = tflp->nfsfl_ffm[i].stripep; + for (j = 0; sp != NULL && j < + tflp->nfsfl_ffm[i].stripecnt; j++, + sp++) { + laystat = nfscl_adddevinfo(nmp, + NULL, i, j, tflp); + NFSCL_DEBUG(4, "aft adddev=%d" + "\n", laystat); + if (laystat != 0) { + laystat = + nfsrpc_getdeviceinfo( + nmp, sp->dev, + layouttype, notifybit, + &dip, cred, p); + NFSCL_DEBUG(4, + "aft nfsrpc_gdi=%d\n", + laystat); + if (laystat != 0) + goto out; + laystat = + nfscl_adddevinfo( + nmp, dip, i, j, + tflp); + if (laystat != 0) + printf("nfsrpc" + "_layoutget" + "resout" + ": cannot " + "add\n"); + } + } + } + } else { + laystat = nfscl_adddevinfo(nmp, NULL, 0, 0, + tflp); NFSCL_DEBUG(4, "aft adddev=%d\n", laystat); if (laystat != 0) { - if (layouttype == NFSLAYOUT_FLEXFILE) - dev = tflp->nfsfl_ffm[i].dev; - else - dev = tflp->nfsfl_dev; - laystat = nfsrpc_getdeviceinfo(nmp, dev, - layouttype, notifybit, &dip, cred, - p); + laystat = nfsrpc_getdeviceinfo(nmp, + tflp->nfsfl_dev, layouttype, + notifybit, &dip, cred, p); NFSCL_DEBUG(4, "aft nfsrpc_gdi=%d\n", laystat); if (laystat != 0) goto out; - laystat = nfscl_adddevinfo(nmp, dip, i, - tflp); + laystat = nfscl_adddevinfo(nmp, dip, 0, + 0, tflp); if (laystat != 0) printf("nfsrpc_layoutgetresout" ": cannot add\n"); diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c index a511c31d5202..1931964ed62e 100644 --- a/sys/fs/nfsclient/nfs_clstate.c +++ b/sys/fs/nfsclient/nfs_clstate.c @@ -5667,11 +5667,12 @@ nfscl_mergeflayouts(struct nfsclflayouthead *fhlp, * This function consumes the structure pointed at by dip, if not NULL. */ int -nfscl_adddevinfo(struct nfsmount *nmp, struct nfscldevinfo *dip, int ind, - struct nfsclflayout *flp) +nfscl_adddevinfo(struct nfsmount *nmp, struct nfscldevinfo *dip, int mirror, + int stripe, struct nfsclflayout *flp) { struct nfsclclient *clp; struct nfscldevinfo *tdip; + struct nfsffs *sp; uint8_t *dev; NFSLOCKCLSTATE(); @@ -5684,15 +5685,18 @@ nfscl_adddevinfo(struct nfsmount *nmp, struct nfscldevinfo *dip, int ind, } if ((flp->nfsfl_flags & NFSFL_FILE) != 0) dev = flp->nfsfl_dev; - else - dev = flp->nfsfl_ffm[ind].dev; + else { + sp = flp->nfsfl_ffm[mirror].stripep; + sp += stripe; + dev = sp->dev; + } tdip = nfscl_finddevinfo(clp, dev); if (tdip != NULL) { tdip->nfsdi_layoutrefs++; if ((flp->nfsfl_flags & NFSFL_FILE) != 0) flp->nfsfl_devp = tdip; else - flp->nfsfl_ffm[ind].devp = tdip; + sp->devp = tdip; nfscl_reldevinfo_locked(tdip); NFSUNLOCKCLSTATE(); if (dip != NULL) @@ -5705,7 +5709,7 @@ nfscl_adddevinfo(struct nfsmount *nmp, struct nfscldevinfo *dip, int ind, if ((flp->nfsfl_flags & NFSFL_FILE) != 0) flp->nfsfl_devp = dip; else - flp->nfsfl_ffm[ind].devp = dip; + sp->devp = dip; } NFSUNLOCKCLSTATE(); if (dip == NULL) @@ -5745,7 +5749,8 @@ nfscl_freelayout(struct nfscllayout *layp) void nfscl_freeflayout(struct nfsclflayout *flp) { - int i, j; + struct nfsffs *sp; + int i, j, k; if ((flp->nfsfl_flags & NFSFL_FILE) != 0) { for (i = 0; i < flp->nfsfl_fhcnt; i++) @@ -5753,13 +5758,20 @@ nfscl_freeflayout(struct nfsclflayout *flp) if (flp->nfsfl_devp != NULL) flp->nfsfl_devp->nfsdi_layoutrefs--; } - if ((flp->nfsfl_flags & NFSFL_FLEXFILE) != 0) + if ((flp->nfsfl_flags & NFSFL_FLEXFILE) != 0) { for (i = 0; i < flp->nfsfl_mirrorcnt; i++) { - for (j = 0; j < flp->nfsfl_ffm[i].fhcnt; j++) - free(flp->nfsfl_ffm[i].fh[j], M_NFSFH); - if (flp->nfsfl_ffm[i].devp != NULL) - flp->nfsfl_ffm[i].devp->nfsdi_layoutrefs--; + sp = flp->nfsfl_ffm[i].stripep; + for (j = 0; j < flp->nfsfl_ffm[i].stripecnt && + sp != NULL; j++, sp++) { + for (k = 0; k < sp->fhcnt; k++) + free(sp->fh[k], M_NFSFH); + if (sp->devp != NULL) + sp->devp->nfsdi_layoutrefs--; + } + if (flp->nfsfl_ffm[i].stripecnt > 1) + free(flp->nfsfl_ffm[i].stripep, M_NFSFLAYOUT); } + } free(flp, M_NFSFLAYOUT); }
