Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149544967
D21762.1790428874.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D21762.1790428874.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D21762: Add a sleep lock to the NFS node to protect n_size
Attached
Detach File
Event Timeline
Log In to Comment