Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/nfs fix a page locking deadlock problem for nfs.
details: https://anonhg.NetBSD.org/src/rev/8a6d30e076cf
branches: trunk
changeset: 538466:8a6d30e076cf
user: yamt <yamt%NetBSD.org@localhost>
date: Mon Oct 21 12:52:32 2002 +0000
description:
fix a page locking deadlock problem for nfs.
add a flag that specify if the file can be truncated safely or not
to nfsm_loadattr and friends. when it isn't safe, just mark the nfsnode
as "should be truncated later".
ok'ed by Frank van der Linden and Chuck Silvers.
close kern/18036.
diffstat:
sys/nfs/nfs_bio.c | 12 +++++-
sys/nfs/nfs_nqlease.c | 6 +-
sys/nfs/nfs_subs.c | 36 +++++++++++++++---
sys/nfs/nfs_var.h | 10 +++-
sys/nfs/nfs_vfsops.c | 8 ++--
sys/nfs/nfs_vnops.c | 99 +++++++++++++++++++++++++++++---------------------
sys/nfs/nfsm_subs.h | 17 ++++----
sys/nfs/nfsnode.h | 5 +-
8 files changed, 124 insertions(+), 69 deletions(-)
diffs (truncated from 626 to 300 lines):
diff -r 6c98ed59d707 -r 8a6d30e076cf sys/nfs/nfs_bio.c
--- a/sys/nfs/nfs_bio.c Mon Oct 21 11:57:25 2002 +0000
+++ b/sys/nfs/nfs_bio.c Mon Oct 21 12:52:32 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_bio.c,v 1.82 2002/09/01 10:39:38 bouyer Exp $ */
+/* $NetBSD: nfs_bio.c,v 1.83 2002/10/21 12:52:32 yamt Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.82 2002/09/01 10:39:38 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.83 2002/10/21 12:52:32 yamt Exp $");
#include "opt_nfs.h"
#include "opt_ddb.h"
@@ -1134,6 +1134,14 @@
crhold(np->n_rcred);
/*
+ * if we have delayed truncation and it's safe, do it now.
+ */
+
+ if (ap->a_flags & PGO_SYNCIO) {
+ nfs_delayedtruncate(vp);
+ }
+
+ /*
* call the genfs code to get the pages. `pgs' may be NULL
* when doing read-ahead.
*/
diff -r 6c98ed59d707 -r 8a6d30e076cf sys/nfs/nfs_nqlease.c
--- a/sys/nfs/nfs_nqlease.c Mon Oct 21 11:57:25 2002 +0000
+++ b/sys/nfs/nfs_nqlease.c Mon Oct 21 12:52:32 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_nqlease.c,v 1.40 2002/05/12 23:04:35 matt Exp $ */
+/* $NetBSD: nfs_nqlease.c,v 1.41 2002/10/21 12:52:33 yamt Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -53,7 +53,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_nqlease.c,v 1.40 2002/05/12 23:04:35 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_nqlease.c,v 1.41 2002/10/21 12:52:33 yamt Exp $");
#include "fs_nfs.h"
#include "opt_nfs.h"
@@ -880,7 +880,7 @@
if (reqtime > time.tv_sec) {
frev = fxdr_hyper(tl);
nqnfs_clientlease(nmp, np, rwflag, cachable, reqtime, frev);
- nfsm_loadattr(vp, (struct vattr *)0);
+ nfsm_loadattr(vp, (struct vattr *)0, 0);
} else
error = NQNFS_EXPIRED;
nfsm_reqdone;
diff -r 6c98ed59d707 -r 8a6d30e076cf sys/nfs/nfs_subs.c
--- a/sys/nfs/nfs_subs.c Mon Oct 21 11:57:25 2002 +0000
+++ b/sys/nfs/nfs_subs.c Mon Oct 21 12:52:32 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_subs.c,v 1.104 2002/08/23 05:38:51 enami Exp $ */
+/* $NetBSD: nfs_subs.c,v 1.105 2002/10/21 12:52:33 yamt Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -74,7 +74,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_subs.c,v 1.104 2002/08/23 05:38:51 enami Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_subs.c,v 1.105 2002/10/21 12:52:33 yamt Exp $");
#include "fs_nfs.h"
#include "opt_nfs.h"
@@ -1527,11 +1527,12 @@
* copy the attributes to *vaper
*/
int
-nfsm_loadattrcache(vpp, mdp, dposp, vaper)
+nfsm_loadattrcache(vpp, mdp, dposp, vaper, flags)
struct vnode **vpp;
struct mbuf **mdp;
caddr_t *dposp;
struct vattr *vaper;
+ int flags;
{
int32_t t1;
caddr_t cp2;
@@ -1544,14 +1545,15 @@
error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2);
if (error)
return (error);
- return nfs_loadattrcache(vpp, (struct nfs_fattr *)cp2, vaper);
+ return nfs_loadattrcache(vpp, (struct nfs_fattr *)cp2, vaper, flags);
}
int
-nfs_loadattrcache(vpp, fp, vaper)
+nfs_loadattrcache(vpp, fp, vaper, flags)
struct vnode **vpp;
struct nfs_fattr *fp;
struct vattr *vaper;
+ int flags;
{
struct vnode *vp = *vpp;
struct vattr *vap;
@@ -1699,7 +1701,17 @@
} else {
np->n_size = vap->va_size;
if (vap->va_type == VREG) {
- uvm_vnp_setsize(vp, np->n_size);
+ if ((flags & NAC_NOTRUNC)
+ && np->n_size < vp->v_size) {
+ /*
+ * we can't free pages now because
+ * the pages can be owned by ourselves.
+ */
+ np->n_flag |= NTRUNCDELAYED;
+ }
+ else {
+ uvm_vnp_setsize(vp, np->n_size);
+ }
}
}
}
@@ -1758,6 +1770,18 @@
return (0);
}
+void
+nfs_delayedtruncate(vp)
+ struct vnode *vp;
+{
+ struct nfsnode *np = VTONFS(vp);
+
+ if (np->n_flag & NTRUNCDELAYED) {
+ np->n_flag &= ~NTRUNCDELAYED;
+ uvm_vnp_setsize(vp, np->n_size);
+ }
+}
+
/*
* Heuristic to see if the server XDR encodes directory cookies or not.
* it is not supposed to, but a lot of servers may do this. Also, since
diff -r 6c98ed59d707 -r 8a6d30e076cf sys/nfs/nfs_var.h
--- a/sys/nfs/nfs_var.h Mon Oct 21 11:57:25 2002 +0000
+++ b/sys/nfs/nfs_var.h Mon Oct 21 12:52:32 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_var.h,v 1.23 2002/03/17 22:22:40 christos Exp $ */
+/* $NetBSD: nfs_var.h,v 1.24 2002/10/21 12:52:34 yamt Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -243,10 +243,11 @@
void nfs_invaldircache __P((struct vnode *, int));
void nfs_init __P((void));
int nfsm_loadattrcache __P((struct vnode **, struct mbuf **, caddr_t *,
- struct vattr *));
+ struct vattr *, int flags));
int nfs_loadattrcache __P((struct vnode **, struct nfs_fattr *,
- struct vattr *));
+ struct vattr *, int flags));
int nfs_getattrcache __P((struct vnode *, struct vattr *));
+void nfs_delayedtruncate __P((struct vnode *));
int nfs_namei __P((struct nameidata *, fhandle_t *, int, struct nfssvc_sock *,
struct mbuf *, struct mbuf **, caddr_t *, struct vnode **,
struct proc *, int, int));
@@ -264,6 +265,9 @@
int nfs_ispublicfh __P((fhandle_t *));
int netaddr_match __P((int, union nethostaddr *, struct mbuf *));
+/* flags for nfs_loadattrcache and friends */
+#define NAC_NOTRUNC 1 /* don't truncate file size */
+
void nfs_clearcommit __P((struct mount *));
void nfs_merge_commit_ranges __P((struct vnode *));
int nfs_in_committed_range __P((struct vnode *, off_t, off_t));
diff -r 6c98ed59d707 -r 8a6d30e076cf sys/nfs/nfs_vfsops.c
--- a/sys/nfs/nfs_vfsops.c Mon Oct 21 11:57:25 2002 +0000
+++ b/sys/nfs/nfs_vfsops.c Mon Oct 21 12:52:32 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_vfsops.c,v 1.118 2002/10/21 03:58:07 enami Exp $ */
+/* $NetBSD: nfs_vfsops.c,v 1.119 2002/10/21 12:52:34 yamt Exp $ */
/*
* Copyright (c) 1989, 1993, 1995
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_vfsops.c,v 1.118 2002/10/21 03:58:07 enami Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_vfsops.c,v 1.119 2002/10/21 12:52:34 yamt Exp $");
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
@@ -169,7 +169,7 @@
nfsm_fhtom(vp, v3);
nfsm_request(vp, NFSPROC_FSSTAT, p, cred);
if (v3)
- nfsm_postop_attr(vp, retattr);
+ nfsm_postop_attr(vp, retattr, 0);
if (error) {
if (mrep != NULL)
m_free(mrep);
@@ -237,7 +237,7 @@
nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
nfsm_fhtom(vp, 1);
nfsm_request(vp, NFSPROC_FSINFO, p, cred);
- nfsm_postop_attr(vp, retattr);
+ nfsm_postop_attr(vp, retattr, 0);
if (!error) {
nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
diff -r 6c98ed59d707 -r 8a6d30e076cf sys/nfs/nfs_vnops.c
--- a/sys/nfs/nfs_vnops.c Mon Oct 21 11:57:25 2002 +0000
+++ b/sys/nfs/nfs_vnops.c Mon Oct 21 12:52:32 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_vnops.c,v 1.152 2002/10/18 19:08:15 thorpej Exp $ */
+/* $NetBSD: nfs_vnops.c,v 1.153 2002/10/21 12:52:35 yamt Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -43,7 +43,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.152 2002/10/18 19:08:15 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.153 2002/10/21 12:52:35 yamt Exp $");
#include "opt_nfs.h"
#include "opt_uvmhist.h"
@@ -364,7 +364,7 @@
}
*tl = txdr_unsigned(mode);
nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred);
- nfsm_postop_attr(vp, attrflag);
+ nfsm_postop_attr(vp, attrflag, 0);
if (!error) {
nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
rmode = fxdr_unsigned(u_int32_t, *tl);
@@ -628,7 +628,7 @@
nfsm_fhtom(vp, v3);
nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred);
if (!error) {
- nfsm_loadattr(vp, ap->a_vap);
+ nfsm_loadattr(vp, ap->a_vap, 0);
if (vp->v_type == VDIR &&
ap->a_vap->va_blocksize < NFS_DIRFRAGSIZ)
ap->a_vap->va_blocksize = NFS_DIRFRAGSIZ;
@@ -769,9 +769,9 @@
}
nfsm_request(vp, NFSPROC_SETATTR, procp, cred);
if (v3) {
- nfsm_wcc_data(vp, wccflag);
+ nfsm_wcc_data(vp, wccflag, 0);
} else
- nfsm_loadattr(vp, (struct vattr *)0);
+ nfsm_loadattr(vp, (struct vattr *)0, 0);
nfsm_reqdone;
return (error);
}
@@ -910,7 +910,7 @@
nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred);
if (error) {
- nfsm_postop_attr(dvp, attrflag);
+ nfsm_postop_attr(dvp, attrflag, 0);
m_freem(mrep);
goto nfsmout;
}
@@ -931,10 +931,10 @@
}
newvp = NFSTOV(np);
if (v3) {
- nfsm_postop_attr(newvp, attrflag);
- nfsm_postop_attr(dvp, attrflag);
+ nfsm_postop_attr(newvp, attrflag, 0);
+ nfsm_postop_attr(dvp, attrflag, 0);
} else
- nfsm_loadattr(newvp, (struct vattr *)0);
+ nfsm_loadattr(newvp, (struct vattr *)0, 0);
*vpp = newvp;
m_freem(mrep);
cnp->cn_flags |= SAVENAME;
@@ -958,10 +958,10 @@
VREF(dvp);
newvp = dvp;
if (v3) {
- nfsm_postop_attr(newvp, attrflag);
- nfsm_postop_attr(dvp, attrflag);
+ nfsm_postop_attr(newvp, attrflag, 0);
+ nfsm_postop_attr(dvp, attrflag, 0);
} else
- nfsm_loadattr(newvp, (struct vattr *)0);
+ nfsm_loadattr(newvp, (struct vattr *)0, 0);
} else if (flags & ISDOTDOT) {
Home |
Main Index |
Thread Index |
Old Index