Date: Tue, 17 Sep 2019 18:41:40 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r352457 - head/sys/fs/nfsclient Message-ID: <201909171841.x8HIfeUj054292@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Tue Sep 17 18:41:39 2019 New Revision: 352457 URL: https://svnweb.freebsd.org/changeset/base/352457 Log: Further refine r352393, only call vnode_pager_setsize() outside the node lock when shrinking. This is similar to r252528, applied to the above commit. Apparently there is a race which makes necessary at least to keep the n_size and pager size consistent when extending. Current suspect is that iod threads perform vnode_pager_setsize() without taking the vnode lock, which corrupts the file content. Reported and tested by: Masachika ISHIZUKA <ish@amail.plala.or.jp> Discussed with: rmacklem (related issues) Sponsored by: The FreeBSD Foundation MFC after: 1 week Modified: head/sys/fs/nfsclient/nfs_clport.c Modified: head/sys/fs/nfsclient/nfs_clport.c ============================================================================== --- head/sys/fs/nfsclient/nfs_clport.c Tue Sep 17 18:36:29 2019 (r352456) +++ head/sys/fs/nfsclient/nfs_clport.c Tue Sep 17 18:41:39 2019 (r352457) @@ -414,12 +414,12 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvatt struct nfsnode *np; struct nfsmount *nmp; struct timespec mtime_save; + vm_object_t object; u_quad_t nsize; - int setnsize, error, force_fid_err; + int error, force_fid_err; + bool setnsize; error = 0; - setnsize = 0; - nsize = 0; /* * If v_type == VNON it is a new node, so fill in the v_type, @@ -511,8 +511,7 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvatt * zero np->n_attrstamp to indicate that * the attributes are stale. */ - nsize = vap->va_size = np->n_size; - setnsize = 1; + vap->va_size = np->n_size; np->n_attrstamp = 0; KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); } else if (np->n_flag & NMODIFIED) { @@ -526,22 +525,9 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvatt np->n_size = vap->va_size; np->n_flag |= NSIZECHANGED; } - nsize = np->n_size; - setnsize = 1; - } else if (vap->va_size < np->n_size) { - /* - * When shrinking the size, the call to - * vnode_pager_setsize() cannot be done - * with the mutex held, so delay it until - * after the mtx_unlock call. - */ - nsize = np->n_size = vap->va_size; - np->n_flag |= NSIZECHANGED; - setnsize = 1; } else { - nsize = np->n_size = vap->va_size; + np->n_size = vap->va_size; np->n_flag |= NSIZECHANGED; - setnsize = 1; } } else { np->n_size = vap->va_size; @@ -579,6 +565,23 @@ out: 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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201909171841.x8HIfeUj054292>