svn commit: r216691 - head/sys/fs/nfsserver

2010-12-24 Thread Rick Macklem
Author: rmacklem
Date: Fri Dec 24 18:46:44 2010
New Revision: 216691
URL: http://svn.freebsd.org/changeset/base/216691

Log:
  Since VOP_READDIR() for ZFS does not return monotonically
  increasing directory offset cookies, disable the UFS related
  loop that skips over directory entries at the beginning of
  the block for the experimental NFS server. This loop is
  required for UFS since it always returns directory entries
  starting at the beginning of the block that
  the requested directory offset is in. In discussion with pjd@
  and mckusick@ it seems that this behaviour of UFS should maybe
  change, with this fix being an interim patch until then.
  This patch only fixes the experimental server, since pjd@ is
  working on a patch for the regular server.
  
  Discussed with:   pjd, mckusick
  MFC after:5 days

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

Modified: head/sys/fs/nfsserver/nfs_nfsdport.c
==
--- head/sys/fs/nfsserver/nfs_nfsdport.cFri Dec 24 15:36:12 2010
(r216690)
+++ head/sys/fs/nfsserver/nfs_nfsdport.cFri Dec 24 18:46:44 2010
(r216691)
@@ -1432,6 +1432,7 @@ nfsrvd_readdir(struct nfsrv_descript *nd
u_long *cookies = NULL, *cookiep;
struct uio io;
struct iovec iv;
+   int not_zfs;
 
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &at);
@@ -1484,6 +1485,7 @@ nfsrvd_readdir(struct nfsrv_descript *nd
nfsrv_postopattr(nd, getret, &at);
return (0);
}
+   not_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs");
NFSVOPUNLOCK(vp, 0, p);
MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
 again:
@@ -1566,10 +1568,12 @@ again:
 * skip over the records that precede the requested offset. This
 * requires the assumption that file offset cookies monotonically
 * increase.
+* Since the offset cookies don't monotonically increase for ZFS,
+* this is not done when ZFS is the file system.
 */
while (cpos < cend && ncookies > 0 &&
(dp->d_fileno == 0 || dp->d_type == DT_WHT ||
-((u_quad_t)(*cookiep)) <= toff)) {
+(not_zfs != 0 && ((u_quad_t)(*cookiep)) <= toff))) {
cpos += dp->d_reclen;
dp = (struct dirent *)cpos;
cookiep++;
@@ -1678,6 +1682,7 @@ nfsrvd_readdirplus(struct nfsrv_descript
struct uio io;
struct iovec iv;
struct componentname cn;
+   int not_zfs;
 
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &at);
@@ -1755,6 +1760,7 @@ nfsrvd_readdirplus(struct nfsrv_descript
nfsrv_postopattr(nd, getret, &at);
return (0);
}
+   not_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs");
 
MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
 again:
@@ -1827,10 +1833,12 @@ again:
 * skip over the records that precede the requested offset. This
 * requires the assumption that file offset cookies monotonically
 * increase.
+* Since the offset cookies don't monotonically increase for ZFS,
+* this is not done when ZFS is the file system.
 */
while (cpos < cend && ncookies > 0 &&
  (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
-  ((u_quad_t)(*cookiep)) <= toff ||
+  (not_zfs != 0 && ((u_quad_t)(*cookiep)) <= toff) ||
   ((nd->nd_flag & ND_NFSV4) &&
((dp->d_namlen == 1 && dp->d_name[0] == '.') ||
 (dp->d_namlen==2 && dp->d_name[0]=='.' && dp->d_name[1]=='.') {
___
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"


svn commit: r216692 - head/sys/fs/nfsserver

2010-12-24 Thread Rick Macklem
Author: rmacklem
Date: Fri Dec 24 20:24:07 2010
New Revision: 216692
URL: http://svn.freebsd.org/changeset/base/216692

Log:
  Simplify vnode locking in the expeimental NFS server's
  readdir functions. In particular, get rid of two bogus
  VOP_ISLOCKED() calls. Removing the VOP_ISLOCKED() calls
  is the only actual bug fixed by this patch.
  
  Reviewed by:  kib
  MFC after:2 weeks

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

Modified: head/sys/fs/nfsserver/nfs_nfsdport.c
==
--- head/sys/fs/nfsserver/nfs_nfsdport.cFri Dec 24 18:46:44 2010
(r216691)
+++ head/sys/fs/nfsserver/nfs_nfsdport.cFri Dec 24 20:24:07 2010
(r216692)
@@ -1486,7 +1486,6 @@ nfsrvd_readdir(struct nfsrv_descript *nd
return (0);
}
not_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs");
-   NFSVOPUNLOCK(vp, 0, p);
MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
 again:
eofflag = 0;
@@ -1504,10 +1503,8 @@ again:
io.uio_segflg = UIO_SYSSPACE;
io.uio_rw = UIO_READ;
io.uio_td = NULL;
-   NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p);
nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, &ncookies,
&cookies);
-   NFSVOPUNLOCK(vp, 0, p);
off = (u_int64_t)io.uio_offset;
if (io.uio_resid)
siz -= io.uio_resid;
@@ -1524,7 +1521,7 @@ again:
 * Handles the failed cases. nd->nd_repstat == 0 past here.
 */
if (nd->nd_repstat) {
-   vrele(vp);
+   vput(vp);
free((caddr_t)rbuf, M_TEMP);
if (cookies)
free((caddr_t)cookies, M_TEMP);
@@ -1537,7 +1534,7 @@ again:
 * rpc reply
 */
if (siz == 0) {
-   vrele(vp);
+   vput(vp);
if (nd->nd_flag & ND_NFSV2) {
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
} else {
@@ -1584,6 +1581,7 @@ again:
toff = off;
goto again;
}
+   vput(vp);
 
/*
 * dirlen is the size of the reply, including all XDR and must
@@ -1642,7 +1640,6 @@ again:
}
if (cpos < cend)
eofflag = 0;
-   vrele(vp);
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
*tl++ = newnfs_false;
if (eofflag)
@@ -1852,7 +1849,7 @@ again:
toff = off;
goto again;
}
-   NFSVOPUNLOCK(vp, 0, p);
+   VOP_UNLOCK(vp, 0);
 
/*
 * Save this position, in case there is an error before one entry
@@ -1938,10 +1935,11 @@ again:
dp->d_name[1] == '.')
cn.cn_flags |=
ISDOTDOT;
-   if (!VOP_ISLOCKED(vp))
-   vn_lock(vp,
-   LK_EXCLUSIVE |
-   LK_RETRY);
+   if (vn_lock(vp, LK_EXCLUSIVE)
+   != 0) {
+   nd->nd_repstat = EPERM;
+   break;
+   }
if ((vp->v_vflag & VV_ROOT) != 0
&& (cn.cn_flags & ISDOTDOT)
!= 0) {
@@ -2000,7 +1998,7 @@ again:
*tl = txdr_unsigned(*cookiep);
dirlen += nfsm_strtom(nd, dp->d_name, nlen);
if (nvp != NULL)
-   NFSVOPUNLOCK(nvp, 0, p);
+   VOP_UNLOCK(nvp, 0);
if (refp != NULL) {
dirlen += nfsrv_putreferralattr(nd,
&savbits, refp, 0,
@@ -2031,10 +2029,7 @@ again:
cookiep++;
ncookies--;
}
-   if (!usevget && VOP_ISLOCKED(vp))
-   vput(vp);
-   else
-   vrele(vp);
+   vrele(vp);
 
/*
 * If dirlen > cnt, we must strip off the last entry. If that
___
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"


svn commit: r216693 - in head/sys/fs: nfs nfsserver

2010-12-24 Thread Rick Macklem
Author: rmacklem
Date: Fri Dec 24 21:31:18 2010
New Revision: 216693
URL: http://svn.freebsd.org/changeset/base/216693

Log:
  Add an argument to nfsvno_getattr() in the experimental
  NFS server, so that it can avoid calling VOP_ISLOCKED()
  when the vnode is known to be locked. This will allow
  LK_SHARED to be used for these cases, which happen to
  be all the cases that can use LK_SHARED. This does not
  fix any bug, but it reduces the number of calls to
  VOP_ISLOCKED() and prepares the code so that it can be
  switched to using LK_SHARED in a future patch.
  
  Reviewed by:  kib
  MFC after:2 weeks

Modified:
  head/sys/fs/nfs/nfs_var.h
  head/sys/fs/nfsserver/nfs_nfsdport.c
  head/sys/fs/nfsserver/nfs_nfsdserv.c

Modified: head/sys/fs/nfs/nfs_var.h
==
--- head/sys/fs/nfs/nfs_var.h   Fri Dec 24 20:24:07 2010(r216692)
+++ head/sys/fs/nfs/nfs_var.h   Fri Dec 24 21:31:18 2010(r216693)
@@ -510,7 +510,7 @@ void ncl_invalcaches(vnode_t);
 
 /* nfs_nfsdport.c */
 int nfsvno_getattr(vnode_t, struct nfsvattr *, struct ucred *,
-NFSPROC_T *);
+NFSPROC_T *, int);
 int nfsvno_setattr(vnode_t, struct nfsvattr *, struct ucred *,
 NFSPROC_T *, struct nfsexstuff *);
 int nfsvno_getfh(vnode_t, fhandle_t *, NFSPROC_T *);

Modified: head/sys/fs/nfsserver/nfs_nfsdport.c
==
--- head/sys/fs/nfsserver/nfs_nfsdport.cFri Dec 24 20:24:07 2010
(r216692)
+++ head/sys/fs/nfsserver/nfs_nfsdport.cFri Dec 24 21:31:18 2010
(r216693)
@@ -100,18 +100,24 @@ static struct nfsheur {
  */
 int
 nfsvno_getattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred,
-struct thread *p)
+struct thread *p, int vpislocked)
 {
int error, lockedit = 0;
 
-   /* Since FreeBSD insists the vnode be locked... */
-   if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) {
-   lockedit = 1;
-   NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p);
+   if (vpislocked == 0) {
+   /*
+* When vpislocked == 0, the vnode is either exclusively
+* locked by this thread or not locked by this thread.
+* As such, shared lock it, if not exclusively locked.
+*/
+   if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) {
+   lockedit = 1;
+   vn_lock(vp, LK_SHARED | LK_RETRY);
+   }
}
error = VOP_GETATTR(vp, &nvap->na_vattr, cred);
-   if (lockedit)
-   NFSVOPUNLOCK(vp, 0, p);
+   if (lockedit != 0)
+   VOP_UNLOCK(vp, 0);
return (error);
 }
 
@@ -1375,7 +1381,7 @@ nfsvno_updfilerev(struct vnode *vp, stru
VATTR_NULL(&va);
getnanotime(&va.va_mtime);
(void) VOP_SETATTR(vp, &va, cred);
-   (void) nfsvno_getattr(vp, nvap, cred, p);
+   (void) nfsvno_getattr(vp, nvap, cred, p, 1);
 }
 
 /*
@@ -1456,7 +1462,7 @@ nfsrvd_readdir(struct nfsrv_descript *nd
fullsiz = siz;
if (nd->nd_flag & ND_NFSV3) {
nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd->nd_cred,
-   p);
+   p, 1);
 #if 0
/*
 * va_filerev is not sufficient as a cookie verifier,
@@ -1512,7 +1518,7 @@ again:
if (!cookies && !nd->nd_repstat)
nd->nd_repstat = NFSERR_PERM;
if (nd->nd_flag & ND_NFSV3) {
-   getret = nfsvno_getattr(vp, &at, nd->nd_cred, p);
+   getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1);
if (!nd->nd_repstat)
nd->nd_repstat = getret;
}
@@ -1723,7 +1729,7 @@ nfsrvd_readdirplus(struct nfsrv_descript
NFSZERO_ATTRBIT(&attrbits);
}
fullsiz = siz;
-   nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd->nd_cred, p);
+   nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1);
if (!nd->nd_repstat) {
if (off && verf != at.na_filerev) {
/*
@@ -1782,7 +1788,7 @@ again:
if (io.uio_resid)
siz -= io.uio_resid;
 
-   getret = nfsvno_getattr(vp, &at, nd->nd_cred, p);
+   getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1);
 
if (!cookies && !nd->nd_repstat)
nd->nd_repstat = NFSERR_PERM;
@@ -1958,7 +1964,7 @@ again:
r = nfsvno_getfh(nvp, &nfh, p);
if (!r)
r = nfsvno_getattr(nvp, nvap,
-   nd->nd_cred, p);
+   nd->nd_cred, p, 1);
}
} else {
nvp = NULL;

Modified: head/sys/fs/nfsserver/nfs_nfsdserv.c
===