in remove, unlock parent directory first to avoid deadlock with
removal of silly rename file on final vrele;
map ENOENT on rename, and EEXIST on link, symlink, and mkdir to zero
as they would have been detected on lookup, so come about because
of non-idempotency on retries
SCCS-vsn: sys/nfs/nfs_vnops.c 7.26
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#)nfs_vnops.c 7.25 (Berkeley) %G%
+ * @(#)nfs_vnops.c 7.26 (Berkeley) %G%
extern u_long nfs_procids[NFS_NPROCS];
extern u_long nfs_prog, nfs_vers;
extern char nfsiobuf[MAXPHYS+NBPG];
extern u_long nfs_procids[NFS_NPROCS];
extern u_long nfs_prog, nfs_vers;
extern char nfsiobuf[MAXPHYS+NBPG];
+extern int nonidempotent[NFS_NPROCS];
struct map nfsmap[NFS_MSIZ];
enum vtype v_type[NFLNK+1];
struct buf nfs_bqueue; /* Queue head for nfsiod's */
struct map nfsmap[NFS_MSIZ];
enum vtype v_type[NFLNK+1];
struct buf nfs_bqueue; /* Queue head for nfsiod's */
struct mbuf *mreq, *mrep, *md, *mb;
nfsm_reqhead(nfs_procids[NFSPROC_NULL], cred, 0);
struct mbuf *mreq, *mrep, *md, *mb;
nfsm_reqhead(nfs_procids[NFSPROC_NULL], cred, 0);
+ nfsm_request(vp, nonidempotent[NFSPROC_NULL]);
nfsm_reqdone;
return (error);
}
nfsm_reqdone;
return (error);
}
nfsstats.rpccnt[NFSPROC_GETATTR]++;
nfsm_reqhead(nfs_procids[NFSPROC_GETATTR], cred, NFSX_FH);
nfsm_fhtom(vp);
nfsstats.rpccnt[NFSPROC_GETATTR]++;
nfsm_reqhead(nfs_procids[NFSPROC_GETATTR], cred, NFSX_FH);
nfsm_fhtom(vp);
+ nfsm_request(vp, nonidempotent[NFSPROC_GETATTR]);
nfsm_loadattr(vp, vap);
nfsm_reqdone;
return (error);
nfsm_loadattr(vp, vap);
nfsm_reqdone;
return (error);
sp->sa_atime.tv_sec = txdr_unsigned(vap->va_atime.tv_sec);
sp->sa_atime.tv_usec = txdr_unsigned(vap->va_flags);
txdr_time(&vap->va_mtime, &sp->sa_mtime);
sp->sa_atime.tv_sec = txdr_unsigned(vap->va_atime.tv_sec);
sp->sa_atime.tv_usec = txdr_unsigned(vap->va_flags);
txdr_time(&vap->va_mtime, &sp->sa_mtime);
+ nfsm_request(vp, nonidempotent[NFSPROC_SETATTR]);
nfsm_loadattr(vp, (struct vattr *)0);
/* should we fill in any vap fields ?? */
nfsm_reqdone;
nfsm_loadattr(vp, (struct vattr *)0);
/* should we fill in any vap fields ?? */
nfsm_reqdone;
nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
nfsm_fhtom(vp);
nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
nfsm_fhtom(vp);
nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
+ nfsm_request(vp, nonidempotent[NFSPROC_LOOKUP]);
nfsmout:
if (error) {
if (lockparent || (flag != CREATE && flag != RENAME) ||
nfsmout:
if (error) {
if (lockparent || (flag != CREATE && flag != RENAME) ||
nfsstats.rpccnt[NFSPROC_READLINK]++;
nfsm_reqhead(nfs_procids[NFSPROC_READLINK], cred, NFSX_FH);
nfsm_fhtom(vp);
nfsstats.rpccnt[NFSPROC_READLINK]++;
nfsm_reqhead(nfs_procids[NFSPROC_READLINK], cred, NFSX_FH);
nfsm_fhtom(vp);
+ nfsm_request(vp, nonidempotent[NFSPROC_READLINK]);
nfsm_strsiz(len, NFS_MAXPATHLEN);
nfsm_mtouio(uiop, len);
nfsm_reqdone;
nfsm_strsiz(len, NFS_MAXPATHLEN);
nfsm_mtouio(uiop, len);
nfsm_reqdone;
*p++ = txdr_unsigned(uiop->uio_offset);
*p++ = txdr_unsigned(len);
*p = 0;
*p++ = txdr_unsigned(uiop->uio_offset);
*p++ = txdr_unsigned(len);
*p = 0;
+ nfsm_request(vp, nonidempotent[NFSPROC_READ]);
nfsm_loadattr(vp, (struct vattr *)0);
nfsm_strsiz(retlen, nmp->nm_rsize);
nfsm_mtouio(uiop, retlen);
nfsm_loadattr(vp, (struct vattr *)0);
nfsm_strsiz(retlen, nmp->nm_rsize);
nfsm_mtouio(uiop, retlen);
*(p+1) = txdr_unsigned(uiop->uio_offset);
*(p+3) = txdr_unsigned(len);
nfsm_uiotom(uiop, len);
*(p+1) = txdr_unsigned(uiop->uio_offset);
*(p+3) = txdr_unsigned(len);
nfsm_uiotom(uiop, len);
+ nfsm_request(vp, nonidempotent[NFSPROC_WRITE]);
nfsm_loadattr(vp, (struct vattr *)0);
m_freem(mrep);
tsiz -= len;
nfsm_loadattr(vp, (struct vattr *)0);
m_freem(mrep);
tsiz -= len;
/* or should these be VNOVAL ?? */
txdr_time(&vap->va_atime, &sp->sa_atime);
txdr_time(&vap->va_mtime, &sp->sa_mtime);
/* or should these be VNOVAL ?? */
txdr_time(&vap->va_atime, &sp->sa_atime);
txdr_time(&vap->va_mtime, &sp->sa_mtime);
- nfsm_request(ndp->ni_dvp);
+ nfsm_request(ndp->ni_dvp, nonidempotent[NFSPROC_CREATE]);
nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
nfsm_reqdone;
nfs_nput(ndp->ni_dvp);
nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
nfsm_reqdone;
nfs_nput(ndp->ni_dvp);
NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
nfsm_fhtom(ndp->ni_dvp);
nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
nfsm_fhtom(ndp->ni_dvp);
nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
- nfsm_request(ndp->ni_dvp);
+ nfsm_request(ndp->ni_dvp, nonidempotent[NFSPROC_REMOVE]);
nfsm_reqdone;
/*
* Kludge City: If the first reply to the remove rpc is lost..
nfsm_reqdone;
/*
* Kludge City: If the first reply to the remove rpc is lost..
error = 0;
}
np->n_attrstamp = 0;
error = 0;
}
np->n_attrstamp = 0;
- if (ndp->ni_dvp == ndp->ni_vp)
- vrele(ndp->ni_vp);
+ if (ndp->ni_dvp == vp)
+ vrele(vp);
- nfs_nput(ndp->ni_vp);
- nfs_nput(ndp->ni_dvp);
+ nfs_nput(ndp->ni_dvp);
+ nfs_nput(vp);
NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
nfsm_fhtom(ndp->ni_dvp);
nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
nfsm_fhtom(ndp->ni_dvp);
nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
- nfsm_request(ndp->ni_dvp);
+ nfsm_request(ndp->ni_dvp, nonidempotent[NFSPROC_REMOVE]);
nfsm_reqdone;
return (error);
}
nfsm_reqdone;
return (error);
}
nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
nfsm_fhtom(tndp->ni_dvp);
nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
nfsm_fhtom(tndp->ni_dvp);
nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
- nfsm_request(sndp->ni_dvp);
+ nfsm_request(sndp->ni_dvp, nonidempotent[NFSPROC_RENAME]);
nfsm_reqdone;
if (sndp->ni_vp->v_type == VDIR) {
if (tndp->ni_vp != NULL && tndp->ni_vp->v_type == VDIR)
nfsm_reqdone;
if (sndp->ni_vp->v_type == VDIR) {
if (tndp->ni_vp != NULL && tndp->ni_vp->v_type == VDIR)
}
nfs_abortop(sndp);
nfs_abortop(tndp);
}
nfs_abortop(sndp);
nfs_abortop(tndp);
+ /*
+ * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
+ */
+ if (error == ENOENT)
+ error = 0;
nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
nfsm_fhtom(tndp->ni_dvp);
nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
nfsm_fhtom(tndp->ni_dvp);
nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
- nfsm_request(sndp->ni_dvp);
+ nfsm_request(sndp->ni_dvp, nonidempotent[NFSPROC_RENAME]);
nfsm_reqdone;
return (error);
}
nfsm_reqdone;
return (error);
}
nfsm_fhtom(vp);
nfsm_fhtom(ndp->ni_dvp);
nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
nfsm_fhtom(vp);
nfsm_fhtom(ndp->ni_dvp);
nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
+ nfsm_request(vp, nonidempotent[NFSPROC_LINK]);
nfsm_reqdone;
VTONFS(vp)->n_attrstamp = 0;
if (ndp->ni_dvp != vp)
nfs_unlock(vp);
nfs_nput(ndp->ni_dvp);
nfsm_reqdone;
VTONFS(vp)->n_attrstamp = 0;
if (ndp->ni_dvp != vp)
nfs_unlock(vp);
nfs_nput(ndp->ni_dvp);
+ /*
+ * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
+ */
+ if (error == EEXIST)
+ error = 0;
sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
sp->sa_size = txdr_unsigned(VNOVAL);
sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
sp->sa_size = txdr_unsigned(VNOVAL);
- txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */
+ txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */
txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */
txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */
- nfsm_request(ndp->ni_dvp);
+ nfsm_request(ndp->ni_dvp, nonidempotent[NFSPROC_SYMLINK]);
nfsm_reqdone;
nfs_nput(ndp->ni_dvp);
nfsm_reqdone;
nfs_nput(ndp->ni_dvp);
+ /*
+ * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
+ */
+ if (error == EEXIST)
+ error = 0;
sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
sp->sa_size = txdr_unsigned(VNOVAL);
sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
sp->sa_size = txdr_unsigned(VNOVAL);
- txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */
+ txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */
txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */
txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */
- nfsm_request(ndp->ni_dvp);
+ nfsm_request(ndp->ni_dvp, nonidempotent[NFSPROC_MKDIR]);
nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
nfsm_reqdone;
nfs_nput(ndp->ni_dvp);
nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
nfsm_reqdone;
nfs_nput(ndp->ni_dvp);
+ /*
+ * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry.
+ */
+ if (error == EEXIST)
+ error = 0;
NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
nfsm_fhtom(ndp->ni_dvp);
nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
nfsm_fhtom(ndp->ni_dvp);
nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
- nfsm_request(ndp->ni_dvp);
+ nfsm_request(ndp->ni_dvp, nonidempotent[NFSPROC_RMDIR]);
nfsm_reqdone;
cache_purge(ndp->ni_dvp);
cache_purge(ndp->ni_vp);
nfs_nput(ndp->ni_vp);
nfs_nput(ndp->ni_dvp);
nfsm_reqdone;
cache_purge(ndp->ni_dvp);
cache_purge(ndp->ni_vp);
nfs_nput(ndp->ni_vp);
nfs_nput(ndp->ni_dvp);
+ /*
+ * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
+ */
+ if (error == ENOENT)
+ error = 0;
nfsm_build(p, u_long *, 2*NFSX_UNSIGNED);
*p++ = txdr_unsigned(uiop->uio_offset);
*p = txdr_unsigned(uiop->uio_resid);
nfsm_build(p, u_long *, 2*NFSX_UNSIGNED);
*p++ = txdr_unsigned(uiop->uio_offset);
*p = txdr_unsigned(uiop->uio_resid);
+ nfsm_request(vp, nonidempotent[NFSPROC_READDIR]);
siz = 0;
nfsm_disect(p, u_long *, NFSX_UNSIGNED);
more_dirs = fxdr_unsigned(int, *p);
siz = 0;
nfsm_disect(p, u_long *, NFSX_UNSIGNED);
more_dirs = fxdr_unsigned(int, *p);
cred->cr_ngroups = 1;
nfsm_reqhead(nfs_procids[NFSPROC_STATFS], cred, NFSX_FH);
nfsm_fhtom(vp);
cred->cr_ngroups = 1;
nfsm_reqhead(nfs_procids[NFSPROC_STATFS], cred, NFSX_FH);
nfsm_fhtom(vp);
+ nfsm_request(vp, nonidempotent[NFSPROC_STATFS]);
nfsm_disect(sfp, struct nfsv2_statfs *, NFSX_STATFS);
sbp->f_type = MOUNT_NFS;
sbp->f_flags = nmp->nm_flag;
nfsm_disect(sfp, struct nfsv2_statfs *, NFSX_STATFS);
sbp->f_type = MOUNT_NFS;
sbp->f_flags = nmp->nm_flag;
nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
nfsm_fhtom(vp);
nfsm_strtom(ndp->ni_dent.d_name, len, NFS_MAXNAMLEN);
nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
nfsm_fhtom(vp);
nfsm_strtom(ndp->ni_dent.d_name, len, NFS_MAXNAMLEN);
+ nfsm_request(vp, nonidempotent[NFSPROC_LOOKUP]);
if (fhp != NULL) {
nfsm_disect(cp, caddr_t, NFSX_FH);
bcopy(cp, (caddr_t)fhp, NFSX_FH);
if (fhp != NULL) {
nfsm_disect(cp, caddr_t, NFSX_FH);
bcopy(cp, (caddr_t)fhp, NFSX_FH);