Page MenuHomeFreeBSD

D21762.1790428874.diff
No OneTemporary

Size
12 KB
Referenced Files
None
Subscribers
None

D21762.1790428874.diff

Index: fs/nfsclient/nfs_clbio.c
===================================================================
--- fs/nfsclient/nfs_clbio.c
+++ fs/nfsclient/nfs_clbio.c
@@ -101,9 +101,9 @@
int biosize, bcount;
np = VTONFS(vp);
- mtx_lock(&np->n_mtx);
+ sx_xlock(&np->n_slock);
nsize = np->n_size;
- mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
biosize = vp->v_bufobj.bo_bsize;
bcount = biosize;
@@ -301,6 +301,7 @@
} else
mtx_unlock(&nmp->nm_mtx);
+ sx_xlock(&np->n_slock);
mtx_lock(&np->n_mtx);
if (newnfs_directio_enable && !newnfs_directio_allow_mmap &&
(np->n_flag & NNONCACHE) && (vp->v_type == VREG)) {
@@ -317,6 +318,7 @@
count = 0;
}
mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
for (i = 0; i < npages; i++)
rtvals[i] = VM_PAGER_ERROR;
@@ -474,9 +476,9 @@
do {
u_quad_t nsize;
- mtx_lock(&np->n_mtx);
+ sx_xlock(&np->n_slock);
nsize = np->n_size;
- mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
switch (vp->v_type) {
case VREG:
@@ -929,9 +931,9 @@
}
orig_resid = uio->uio_resid;
- mtx_lock(&np->n_mtx);
+ sx_xlock(&np->n_slock);
orig_size = np->n_size;
- mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
/*
* If IO_APPEND then load uio_offset. We restart here if we cannot
@@ -943,9 +945,9 @@
error = VOP_GETATTR(vp, &vattr, cred);
if (error)
return (error);
- mtx_lock(&np->n_mtx);
+ sx_xlock(&np->n_slock);
uio->uio_offset = np->n_size;
- mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
}
if (uio->uio_offset < 0)
@@ -1018,6 +1020,7 @@
* Handle direct append and file extension cases, calculate
* unaligned buffer size.
*/
+ sx_xlock(&np->n_slock);
mtx_lock(&np->n_mtx);
if ((np->n_flag & NHASBEENLOCKED) == 0 &&
(nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0)
@@ -1029,6 +1032,7 @@
lbn == (np->n_size / biosize) &&
uio->uio_offset + n > np->n_size)) && n) {
mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
/*
* Get the buffer (in its pre-append state to maintain
* B_CACHE if it was previously set). Resize the
@@ -1041,11 +1045,13 @@
if (bp != NULL) {
long save;
+ sx_xlock(&np->n_slock);
mtx_lock(&np->n_mtx);
np->n_size = uio->uio_offset + n;
np->n_flag |= NMODIFIED;
- vnode_pager_setsize(vp, np->n_size);
mtx_unlock(&np->n_mtx);
+ vnode_pager_setsize(vp, np->n_size);
+ sx_xunlock(&np->n_slock);
save = bp->b_flags & B_CACHE;
bcount = on + n;
@@ -1068,14 +1074,18 @@
bcount = np->n_size - (off_t)lbn * biosize;
}
mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
bp = nfs_getcacheblk(vp, lbn, bcount, td);
+ sx_xlock(&np->n_slock);
mtx_lock(&np->n_mtx);
if (uio->uio_offset + n > np->n_size) {
np->n_size = uio->uio_offset + n;
np->n_flag |= NMODIFIED;
+ mtx_unlock(&np->n_mtx);
vnode_pager_setsize(vp, np->n_size);
- }
- mtx_unlock(&np->n_mtx);
+ } else
+ mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
}
if (!bp) {
@@ -1706,10 +1716,10 @@
/*
* Setup for actual write
*/
- mtx_lock(&np->n_mtx);
+ sx_xlock(&np->n_slock);
if ((off_t)bp->b_blkno * DEV_BSIZE + bp->b_dirtyend > np->n_size)
bp->b_dirtyend = np->n_size - (off_t)bp->b_blkno * DEV_BSIZE;
- mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
if (bp->b_dirtyend > bp->b_dirtyoff) {
io.iov_len = uiop->uio_resid = bp->b_dirtyend
@@ -1839,10 +1849,10 @@
int biosize = vp->v_bufobj.bo_bsize;
int error = 0;
- mtx_lock(&np->n_mtx);
+ sx_xlock(&np->n_slock);
tsize = np->n_size;
np->n_size = nsize;
- mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
if (nsize < tsize) {
struct buf *bp;
Index: fs/nfsclient/nfs_clnode.c
===================================================================
--- fs/nfsclient/nfs_clnode.c
+++ fs/nfsclient/nfs_clnode.c
@@ -143,6 +143,7 @@
* happened to return an error no special casing is needed).
*/
mtx_init(&np->n_mtx, "NEWNFSnode lock", NULL, MTX_DEF | MTX_DUPOK);
+ sx_init(&np->n_slock, "NEWNFSnode slock");
lockinit(&np->n_excl, PVFS, "nfsupg", VLKTIMEOUT, LK_NOSHARE |
LK_CANRECURSE);
@@ -172,6 +173,7 @@
*npp = NULL;
free(np->n_fhp, M_NFSFH);
mtx_destroy(&np->n_mtx);
+ sx_destroy(&np->n_slock);
lockdestroy(&np->n_excl);
uma_zfree(newnfsnode_zone, np);
return (error);
@@ -333,6 +335,7 @@
if (np->n_v4 != NULL)
free(np->n_v4, M_NFSV4NODE);
mtx_destroy(&np->n_mtx);
+ sx_destroy(&np->n_slock);
lockdestroy(&np->n_excl);
uma_zfree(newnfsnode_zone, vp->v_data);
vp->v_data = NULL;
Index: fs/nfsclient/nfs_clport.c
===================================================================
--- fs/nfsclient/nfs_clport.c
+++ fs/nfsclient/nfs_clport.c
@@ -233,6 +233,7 @@
* happened to return an error no special casing is needed).
*/
mtx_init(&np->n_mtx, "NEWNFSnode lock", NULL, MTX_DEF | MTX_DUPOK);
+ sx_init(&np->n_slock, "NEWNFSnode slock");
lockinit(&np->n_excl, PVFS, "nfsupg", VLKTIMEOUT, LK_NOSHARE |
LK_CANRECURSE);
@@ -276,6 +277,7 @@
if (error != 0) {
*npp = NULL;
mtx_destroy(&np->n_mtx);
+ sx_destroy(&np->n_slock);
lockdestroy(&np->n_excl);
free(nfhp, M_NFSFH);
if (np->n_v4 != NULL)
@@ -414,10 +416,8 @@
struct nfsnode *np;
struct nfsmount *nmp;
struct timespec mtime_save;
- vm_object_t object;
- u_quad_t nsize;
int error, force_fid_err;
- bool setnsize;
+ bool unlocked;
error = 0;
@@ -429,7 +429,8 @@
* information.
*/
np = VTONFS(vp);
- NFSLOCKNODE(np);
+ sx_xlock(&np->n_slock);
+ mtx_lock(&np->n_mtx);
if (vp->v_type != nvap->va_type) {
vp->v_type = nvap->va_type;
if (vp->v_type == VFIFO)
@@ -503,6 +504,7 @@
} else
vn_fsid(vp, vap);
np->n_attrstamp = time_second;
+ unlocked = false;
if (vap->va_size != np->n_size) {
if (vap->va_type == VREG) {
if (dontshrink && vap->va_size < np->n_size) {
@@ -513,7 +515,10 @@
*/
vap->va_size = np->n_size;
np->n_attrstamp = 0;
+ unlocked = true;
+ mtx_unlock(&np->n_mtx);
KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
+ vnode_pager_setsize(vp, np->n_size);
} else if (np->n_flag & NMODIFIED) {
/*
* We've modified the file: Use the larger
@@ -525,14 +530,22 @@
np->n_size = vap->va_size;
np->n_flag |= NSIZECHANGED;
}
+ unlocked = true;
+ mtx_unlock(&np->n_mtx);
+ vnode_pager_setsize(vp, np->n_size);
} else {
np->n_size = vap->va_size;
np->n_flag |= NSIZECHANGED;
+ unlocked = true;
+ mtx_unlock(&np->n_mtx);
+ vnode_pager_setsize(vp, np->n_size);
}
} else {
np->n_size = vap->va_size;
}
}
+ if (unlocked)
+ mtx_lock(&np->n_mtx);
/*
* The following checks are added to prevent a race between (say)
* a READDIR+ and a WRITE.
@@ -565,26 +578,8 @@
if (np->n_attrstamp != 0)
KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, vap, error);
#endif
- nsize = vap->va_size;
- object = vp->v_object;
- setnsize = false;
- if (object != NULL) {
- if (OFF_TO_IDX(nsize + PAGE_MASK) < object->size) {
- /*
- * When shrinking the size, the call to
- * vnode_pager_setsize() cannot be done with
- * the mutex held, because we might need to
- * wait for a busy page. Delay it until after
- * the node is unlocked.
- */
- setnsize = true;
- } else {
- vnode_pager_setsize(vp, nsize);
- }
- }
- NFSUNLOCKNODE(np);
- if (setnsize)
- vnode_pager_setsize(vp, nsize);
+ mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
return (error);
}
Index: fs/nfsclient/nfs_clrpcops.c
===================================================================
--- fs/nfsclient/nfs_clrpcops.c
+++ fs/nfsclient/nfs_clrpcops.c
@@ -1440,12 +1440,12 @@
* more link data than it should?
*/
if (len == NFS_MAXPATHLEN) {
- NFSLOCKNODE(np);
+ sx_xlock(&np->n_slock);
if (np->n_size > 0 && np->n_size < NFS_MAXPATHLEN) {
len = np->n_size;
cangetattr = 0;
}
- NFSUNLOCKNODE(np);
+ sx_xunlock(&np->n_slock);
}
error = nfsm_mbufuio(nd, uiop, len);
if ((nd->nd_flag & ND_NFSV4) && !error && cangetattr)
Index: fs/nfsclient/nfs_clstate.c
===================================================================
--- fs/nfsclient/nfs_clstate.c
+++ fs/nfsclient/nfs_clstate.c
@@ -1357,7 +1357,9 @@
off = fl->l_start;
break;
case SEEK_END:
+ sx_xlock(&np->n_slock);
off = np->n_size + fl->l_start;
+ sx_xunlock(&np->n_slock);
break;
default:
return (1);
Index: fs/nfsclient/nfs_clsubs.c
===================================================================
--- fs/nfsclient/nfs_clsubs.c
+++ fs/nfsclient/nfs_clsubs.c
@@ -185,11 +185,13 @@
struct vattr *vap;
struct nfsmount *nmp;
int timeo, mustflush;
+ bool unlocked;
np = VTONFS(vp);
vap = &np->n_vattr.na_vattr;
nmp = VFSTONFS(vp->v_mount);
mustflush = nfscl_mustflush(vp); /* must be before mtx_lock() */
+ sx_xlock(&np->n_slock);
mtx_lock(&np->n_mtx);
/* XXX n_mtime doesn't seem to be updated on a miss-and-reload */
timeo = (time_second - np->n_mtime.tv_sec) / 10;
@@ -226,10 +228,12 @@
(mustflush != 0 || np->n_attrstamp == 0)) {
nfsstatsv1.attrcache_misses++;
mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
KDTRACE_NFS_ATTRCACHE_GET_MISS(vp);
return( ENOENT);
}
nfsstatsv1.attrcache_hits++;
+ unlocked = false;
if (vap->va_size != np->n_size) {
if (vap->va_type == VREG) {
if (np->n_flag & NMODIFIED) {
@@ -240,11 +244,15 @@
} else {
np->n_size = vap->va_size;
}
+ unlocked = true;
+ mtx_unlock(&np->n_mtx);
vnode_pager_setsize(vp, np->n_size);
} else {
np->n_size = vap->va_size;
}
}
+ if (unlocked)
+ mtx_lock(&np->n_mtx);
bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
if (np->n_flag & NCHG) {
if (np->n_flag & NACC)
@@ -253,6 +261,7 @@
vaper->va_mtime = np->n_mtim;
}
mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap);
return (0);
}
Index: fs/nfsclient/nfs_clvnops.c
===================================================================
--- fs/nfsclient/nfs_clvnops.c
+++ fs/nfsclient/nfs_clvnops.c
@@ -465,14 +465,14 @@
* After calling nfsspec_access, we should have the correct
* file size cached.
*/
- mtx_lock(&np->n_mtx);
+ sx_xlock(&np->n_slock);
if (ap->a_cred->cr_uid == 0 && (ap->a_accmode & VREAD)
&& VTONFS(vp)->n_size > 0) {
struct iovec aiov;
struct uio auio;
char buf[1];
- mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
aiov.iov_base = buf;
aiov.iov_len = 1;
auio.uio_iov = &aiov;
@@ -498,7 +498,7 @@
else
error = EACCES;
} else
- mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
return (error);
}
}
@@ -976,14 +976,16 @@
* V_SAVE races that might setsize a lower
* value.
*/
- mtx_lock(&np->n_mtx);
+ sx_xlock(&np->n_slock);
tsize = np->n_size;
- mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
error = ncl_meta_setsize(vp, td, vap->va_size);
+ sx_xlock(&np->n_slock);
mtx_lock(&np->n_mtx);
if (np->n_flag & NMODIFIED) {
tsize = np->n_size;
mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
error = ncl_vinvalbuf(vp, vap->va_size == 0 ?
0 : V_SAVE, td, 1);
if (error != 0) {
@@ -995,17 +997,19 @@
* locally, as required.
*/
nfscl_delegmodtime(vp);
- } else
+ } else {
mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
+ }
/*
* np->n_size has already been set to vap->va_size
* in ncl_meta_setsize(). We must set it again since
* nfs_loadattrcache() could be called through
* ncl_meta_setsize() and could modify np->n_size.
*/
- mtx_lock(&np->n_mtx);
+ sx_xlock(&np->n_slock);
np->n_vattr.na_size = np->n_size = vap->va_size;
- mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
}
} else {
mtx_lock(&np->n_mtx);
@@ -1020,10 +1024,10 @@
}
error = nfs_setattrrpc(vp, vap, ap->a_cred, td);
if (error && vap->va_size != VNOVAL) {
- mtx_lock(&np->n_mtx);
+ sx_xlock(&np->n_slock);
np->n_size = np->n_vattr.na_size = tsize;
vnode_pager_setsize(vp, tsize);
- mtx_unlock(&np->n_mtx);
+ sx_xunlock(&np->n_slock);
}
return (error);
}
Index: fs/nfsclient/nfsnode.h
===================================================================
--- fs/nfsclient/nfsnode.h
+++ fs/nfsclient/nfsnode.h
@@ -91,9 +91,13 @@
* changing the definition in nfsproto.h of NFS_SMALLFH.)
* NB: Hopefully the current order of the fields is such that everything will
* be well aligned and, therefore, tightly packed.
+ * n_mtx - is used to protect all fields except n_size.
+ * n_slock - is used to protect the n_size field. This is done so that
+ * functions such as vnode_pager_setsize() may be called with this lock.
*/
struct nfsnode {
- struct mtx n_mtx; /* Protects all of these members */
+ struct mtx n_mtx; /* Protects all except n_size */
+ struct sx n_slock; /* Protects n_size */
struct lock n_excl; /* Exclusive helper for shared
vnode lock */
u_quad_t n_size; /* Current size of file */

File Metadata

Mime Type
text/plain
Expires
Sat, Sep 26, 1:21 PM (10 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29933598
Default Alt Text
D21762.1790428874.diff (12 KB)

Event Timeline