Author: rmacklem
Date: Fri Jun 29 12:41:36 2018
New Revision: 335794
URL: https://svnweb.freebsd.org/changeset/base/335794

Log:
  Fix the pNFS server for a case where mirror level equals number of DSs.
  
  If a pNFS service was set up where the number of DSs equals the mirror level
  and then a DS was disabled, the service would create files with duplicate
  entries for the same DS. This bug occurred because I didn't realize that
  TAILQ_FOREACH_FROM() would start at the beginning of the list when the
  inital value of the variable was NULL.
  This patch also changes the pNFS server DS file creation code so that it
  creates entrie(s) with 0.0.0.0 IP address when it cannot create mirror level
  files due to lack of DSs.
  The patch only affects the pNFS service and only when it was created with
  a number of DSs equal to the mirror level and mirroring is enabled.

Modified:
  head/sys/fs/nfsserver/nfs_nfsdport.c

Modified: head/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdport.c        Fri Jun 29 10:55:42 2018        
(r335793)
+++ head/sys/fs/nfsserver/nfs_nfsdport.c        Fri Jun 29 12:41:36 2018        
(r335794)
@@ -3859,8 +3859,8 @@ nfsrv_pnfscreate(struct vnode *vp, struct vattr *vap, 
        i = dsdir[0] = ds->nfsdev_nextdir;
        ds->nfsdev_nextdir = (ds->nfsdev_nextdir + 1) % nfsrv_dsdirsize;
        dvp[0] = ds->nfsdev_dsdir[i];
-       if (nfsrv_maxpnfsmirror > 1) {
-               mds = TAILQ_NEXT(ds, nfsdev_list);
+       mds = TAILQ_NEXT(ds, nfsdev_list);
+       if (nfsrv_maxpnfsmirror > 1 && mds != NULL) {
                TAILQ_FOREACH_FROM(mds, &nfsrv_devidhead, nfsdev_list) {
                        if (mds->nfsdev_nmp != NULL) {
                                dsdir[mirrorcnt] = i;
@@ -3879,7 +3879,8 @@ nfsrv_pnfscreate(struct vnode *vp, struct vattr *vap, 
        if (mirrorcnt > 1)
                tdsc = dsc = malloc(sizeof(*dsc) * (mirrorcnt - 1), M_TEMP,
                    M_WAITOK | M_ZERO);
-       tpf = pf = malloc(sizeof(*pf) * mirrorcnt, M_TEMP, M_WAITOK | M_ZERO);
+       tpf = pf = malloc(sizeof(*pf) * nfsrv_maxpnfsmirror, M_TEMP, M_WAITOK |
+           M_ZERO);
 
        error = nfsvno_getfh(vp, &fh, p);
        if (error == 0)
@@ -3987,11 +3988,27 @@ nfsrv_pnfscreate(struct vnode *vp, struct vattr *vap, 
        NFSFREECRED(tcred);
        if (error == 0) {
                ASSERT_VOP_ELOCKED(vp, "nfsrv_pnfscreate vp");
+
+               NFSD_DEBUG(4, "nfsrv_pnfscreate: mirrorcnt=%d maxmirror=%d\n",
+                   mirrorcnt, nfsrv_maxpnfsmirror);
+               /*
+                * For all mirrors that couldn't be created, fill in the
+                * *pf structure, but with an IP address == 0.0.0.0.
+                */
+               tpf = pf + mirrorcnt;
+               for (i = mirrorcnt; i < nfsrv_maxpnfsmirror; i++, tpf++) {
+                       *tpf = *pf;
+                       tpf->dsf_sin.sin_family = AF_INET;
+                       tpf->dsf_sin.sin_len = sizeof(struct sockaddr_in);
+                       tpf->dsf_sin.sin_addr.s_addr = 0;
+                       tpf->dsf_sin.sin_port = 0;
+               }
+
                error = vn_start_write(vp, &mp, V_WAIT);
                if (error == 0) {
                        error = vn_extattr_set(vp, IO_NODELOCKED,
                            EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsfile",
-                           sizeof(*pf) * mirrorcnt, (char *)pf, p);
+                           sizeof(*pf) * nfsrv_maxpnfsmirror, (char *)pf, p);
                        if (error == 0)
                                error = vn_extattr_set(vp, IO_NODELOCKED,
                                    EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsattr",
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to