Rewrite of the NFS client's reply handling. We now have NFS socket

upcalls which do RPC header parsing and match up the reply with the
request. NFS calls now sleep on the nfsreq structure. This enables
us to eliminate the NFS recvlock.

Submitted by:	Mohan Srinivasan mohans at yahoo-inc dot com
This commit is contained in:
Paul Saab 2004-12-06 21:11:15 +00:00
parent def91cf267
commit 35ec46b7f2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=138496
10 changed files with 575 additions and 420 deletions

View File

@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
#include <sys/signalvar.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>

View File

@ -87,6 +87,7 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/lockmgr.h>
#include <sys/signalvar.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>

View File

@ -90,8 +90,6 @@
#define NFSSTA_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
#define NFSSTA_SNDLOCK 0x01000000 /* Send socket lock */
#define NFSSTA_WANTSND 0x02000000 /* Want above */
#define NFSSTA_RCVLOCK 0x04000000 /* Rcv socket lock */
#define NFSSTA_WANTRCV 0x08000000 /* Want above */
#define NFSSTA_TIMEO 0x10000000 /* Experiencing a timeout */
@ -150,19 +148,6 @@ struct buf;
struct vattr;
struct nameidata;
/*
* The set of signals that interrupt an I/O in progress for NFSMNT_INT mounts.
* What should be in this set is open to debate, but I believe that since
* I/O system calls on ufs are never interrupted by signals the set should
* be minimal. My reasoning is that many current programs that use signals
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
#define NFSINT_SIGMASK(set) \
(SIGISMEMBER(set, SIGINT) || SIGISMEMBER(set, SIGTERM) || \
SIGISMEMBER(set, SIGHUP) || SIGISMEMBER(set, SIGKILL) || \
SIGISMEMBER(set, SIGQUIT))
/*
* Socket errors ignored for connectionless sockets??
* For now, ignore them all
@ -321,6 +306,13 @@ int nfs_fsinfo(struct nfsmount *, struct vnode *, struct ucred *,
int nfs_meta_setsize (struct vnode *, struct ucred *,
struct thread *, u_quad_t);
void nfs_set_sigmask __P((struct thread *td, sigset_t *oldset));
void nfs_restore_sigmask __P((struct thread *td, sigset_t *set));
int nfs_tsleep __P((struct thread *td, void *ident, int priority, char *wmesg,
int timo));
int nfs_msleep __P((struct thread *td, void *ident, struct mtx *mtx, int priority,
char *wmesg, int timo));
#endif /* _KERNEL */
#endif

View File

@ -1036,7 +1036,11 @@ nfs_getcacheblk(struct vnode *vp, daddr_t bn, int size, struct thread *td)
nmp = VFSTONFS(mp);
if (nmp->nm_flag & NFSMNT_INT) {
sigset_t oldset;
nfs_set_sigmask(td, &oldset);
bp = getblk(vp, bn, size, PCATCH, 0, 0);
nfs_restore_sigmask(td, &oldset);
while (bp == NULL) {
if (nfs_sigintr(nmp, NULL, td))
return (NULL);
@ -1208,8 +1212,8 @@ nfs_asyncio(struct nfsmount *nmp, struct buf *bp, struct ucred *cred, struct thr
NFS_DPF(ASYNCIO,
("nfs_asyncio: waiting for mount %p queue to drain\n", nmp));
nmp->nm_bufqwant = TRUE;
error = tsleep(&nmp->nm_bufq, slpflag | PRIBIO,
"nfsaio", slptimeo);
error = nfs_tsleep(td, &nmp->nm_bufq, slpflag | PRIBIO,
"nfsaio", slptimeo);
if (error) {
error2 = nfs_sigintr(nmp, NULL, td);
if (error2)
@ -1511,6 +1515,8 @@ nfs_meta_setsize(struct vnode *vp, struct ucred *cred, struct thread *td, u_quad
lbn = nsize / biosize;
bufsize = nsize & (biosize - 1);
bp = nfs_getcacheblk(vp, lbn, bufsize, td);
if (!bp)
return EINTR;
if (bp->b_dirtyoff > bp->b_bcount)
bp->b_dirtyoff = bp->b_bcount;
if (bp->b_dirtyend > bp->b_bcount)

File diff suppressed because it is too large Load Diff

View File

@ -94,6 +94,8 @@ int nfs_ticks;
int nfs_pbuf_freecnt = -1; /* start out unlimited */
struct nfs_reqq nfs_reqq;
struct mtx nfs_reqq_mtx;
struct mtx nfs_reply_mtx;
struct nfs_bufq nfs_bufq;
/*
@ -412,6 +414,8 @@ nfs_init(struct vfsconf *vfsp)
*/
TAILQ_INIT(&nfs_reqq);
callout_init(&nfs_callout, 0);
mtx_init(&nfs_reqq_mtx, "NFS reqq lock", NULL, MTX_DEF);
mtx_init(&nfs_reply_mtx, "Synch NFS reply posting", NULL, MTX_DEF);
nfs_pbuf_freecnt = nswbuf / 2 + 1;

View File

@ -817,6 +817,10 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
nfs_decode_args(nmp, argp);
if (nmp->nm_sotype == SOCK_STREAM)
mtx_init(&nmp->nm_nfstcpstate.mtx, "NFS/TCP state lock",
NULL, MTX_DEF);
/*
* For Connection based sockets (TCP,...) defer the connect until
* the first request, in case the server is not responding.
@ -862,6 +866,8 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
return (0);
bad:
if (nmp->nm_sotype == SOCK_STREAM)
mtx_destroy(&nmp->nm_nfstcpstate.mtx);
nfs_disconnect(nmp);
uma_zfree(nfsmount_zone, nmp);
FREE(nam, M_SONAME);
@ -903,6 +909,9 @@ nfs_unmount(struct mount *mp, int mntflags, struct thread *td)
nfs_disconnect(nmp);
FREE(nmp->nm_nam, M_SONAME);
if (nmp->nm_sotype == SOCK_STREAM)
mtx_destroy(&nmp->nm_nfstcpstate.mtx);
uma_zfree(nfsmount_zone, nmp);
return (0);
}

View File

@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lockf.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/signalvar.h>
#include <vm/vm.h>
#include <vm/vm_object.h>

View File

@ -134,7 +134,10 @@ do { \
#define nfsm_request(v, t, p, c) \
do { \
sigset_t oldset; \
nfs_set_sigmask(p, &oldset); \
error = nfs_request((v), mreq, (t), (p), (c), &mrep, &md, &dpos); \
nfs_restore_sigmask(p, &oldset); \
if (error != 0) { \
if (error & NFSERR_RETERR) \
error &= ~NFSERR_RETERR; \

View File

@ -36,6 +36,14 @@
#ifndef _NFSCLIENT_NFSMOUNT_H_
#define _NFSCLIENT_NFSMOUNT_H_
struct nfs_tcp_mountstate {
int rpcresid;
#define NFS_TCP_EXPECT_RPCMARKER 0x0001 /* Expect to see a RPC/TCP marker next */
#define NFS_TCP_FORCE_RECONNECT 0x0002 /* Force a TCP reconnect */
int flags;
struct mtx mtx;
};
/*
* Mount structure.
* One allocated on every NFS mount.
@ -79,6 +87,7 @@ struct nfsmount {
struct nfs_rpcops *nm_rpcops;
int nm_tprintf_initial_delay; /* initial delay */
int nm_tprintf_delay; /* interval for messages */
struct nfs_tcp_mountstate nm_nfstcpstate;
/* NFSv4 */
uint64_t nm_clientid;