aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2018-06-29 12:41:36 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2018-06-29 12:41:36 +0000
commit1aabf3fd5e0330b7caed230473ce3d0a9ac2d59b (patch)
tree627fbac23263e0c2d710fadadb75c4daf22d2a66 /sys
parenta08232301d3194101aea82e7ff4a5762e036574c (diff)
downloadsrc-1aabf3fd5e0330b7caed230473ce3d0a9ac2d59b.tar.gz
src-1aabf3fd5e0330b7caed230473ce3d0a9ac2d59b.zip
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.
Notes
Notes: svn path=/head/; revision=335794
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index cf4d4b9218f4..541b8121e814 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -3859,8 +3859,8 @@ nfsrv_pnfscreate(struct vnode *vp, struct vattr *vap, struct ucred *cred,
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, struct ucred *cred,
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, struct ucred *cred,
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",