In namei(), we use a NULL thread for uio_td when doing a VOP_READLINK().
nfs_readlink() calls nfs_bioread() which passes in uio_td as the thread argument to nfs_getcacheblk(). In nfs_getcacheblk() we dereference the thread pointer to get a process pointer to pass to nfs_sigintr(). This obviously results in a panic. :) Rather than change nfs_getcacheblk() to check if the thread pointer is NULL when calling nfs_sigintr() like other callers do, change nfs_sigintr() to take a thread as the last argument instead of a process so none of the callers have to care if the thread is NULL or not.
This commit is contained in:
parent
77f6a083fc
commit
56e9ce41a5
@ -267,7 +267,7 @@ int nfs_nfsiodnew(void);
|
||||
int nfs_asyncio(struct buf *, struct ucred *, struct thread *);
|
||||
int nfs_doio(struct buf *, struct ucred *, struct thread *);
|
||||
int nfs_readlinkrpc(struct vnode *, struct uio *, struct ucred *);
|
||||
int nfs_sigintr(struct nfsmount *, struct nfsreq *, struct proc *);
|
||||
int nfs_sigintr(struct nfsmount *, struct nfsreq *, struct thread *);
|
||||
int nfs_readdirplusrpc(struct vnode *, struct uio *, struct ucred *);
|
||||
int nfs_request(struct vnode *, struct mbuf *, int, struct thread *,
|
||||
struct ucred *, struct mbuf **, struct mbuf **, caddr_t *);
|
||||
|
@ -1026,7 +1026,7 @@ nfs_getcacheblk(struct vnode *vp, daddr_t bn, int size, struct thread *td)
|
||||
if (nmp->nm_flag & NFSMNT_INT) {
|
||||
bp = getblk(vp, bn, size, PCATCH, 0);
|
||||
while (bp == (struct buf *)0) {
|
||||
if (nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc))
|
||||
if (nfs_sigintr(nmp, (struct nfsreq *)0, td))
|
||||
return ((struct buf *)0);
|
||||
bp = getblk(vp, bn, size, 0, 2 * hz);
|
||||
}
|
||||
@ -1076,7 +1076,7 @@ nfs_vinvalbuf(struct vnode *vp, int flags, struct ucred *cred,
|
||||
error = tsleep((caddr_t)&np->n_flag, PRIBIO + 2, "nfsvinval",
|
||||
slptimeo);
|
||||
if (error && intrflg &&
|
||||
nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc))
|
||||
nfs_sigintr(nmp, (struct nfsreq *)0, td))
|
||||
return (EINTR);
|
||||
}
|
||||
|
||||
@ -1087,7 +1087,7 @@ nfs_vinvalbuf(struct vnode *vp, int flags, struct ucred *cred,
|
||||
error = vinvalbuf(vp, flags, cred, td, slpflag, 0);
|
||||
while (error) {
|
||||
if (intrflg &&
|
||||
nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc)) {
|
||||
nfs_sigintr(nmp, (struct nfsreq *)0, td)) {
|
||||
np->n_flag &= ~NFLUSHINPROG;
|
||||
if (np->n_flag & NFLUSHWANT) {
|
||||
np->n_flag &= ~NFLUSHWANT;
|
||||
@ -1200,7 +1200,7 @@ nfs_asyncio(struct buf *bp, struct ucred *cred, struct thread *td)
|
||||
error = tsleep(&nmp->nm_bufq, slpflag | PRIBIO,
|
||||
"nfsaio", slptimeo);
|
||||
if (error) {
|
||||
if (nfs_sigintr(nmp, NULL, td ? td->td_proc : NULL))
|
||||
if (nfs_sigintr(nmp, NULL, td))
|
||||
return (EINTR);
|
||||
if (slpflag == PCATCH) {
|
||||
slpflag = 0;
|
||||
|
@ -235,8 +235,7 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
|
||||
PSOCK, "nfscon", 2 * hz);
|
||||
if ((so->so_state & SS_ISCONNECTING) &&
|
||||
so->so_error == 0 && rep &&
|
||||
(error = nfs_sigintr(nmp, rep,
|
||||
(rep->r_td ? rep->r_td->td_proc : NULL))) != 0){
|
||||
(error = nfs_sigintr(nmp, rep, rep->r_td)) != 0) {
|
||||
so->so_state &= ~SS_ISCONNECTING;
|
||||
splx(s);
|
||||
goto bad;
|
||||
@ -1075,8 +1074,7 @@ nfs_timer(void *arg)
|
||||
nmp = rep->r_nmp;
|
||||
if (rep->r_mrep || (rep->r_flags & R_SOFTTERM))
|
||||
continue;
|
||||
if (nfs_sigintr(nmp, rep,
|
||||
(rep->r_td ? rep->r_td->td_proc : NULL))) {
|
||||
if (nfs_sigintr(nmp, rep, rep->r_td)) {
|
||||
nfs_softterm(rep);
|
||||
continue;
|
||||
}
|
||||
@ -1224,8 +1222,9 @@ nfs_softterm(struct nfsreq *rep)
|
||||
* This is used for NFSMNT_INT mounts.
|
||||
*/
|
||||
int
|
||||
nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct proc *p)
|
||||
nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct thread *td)
|
||||
{
|
||||
struct proc *p;
|
||||
sigset_t tmpset;
|
||||
|
||||
if (rep && (rep->r_flags & R_SOFTTERM))
|
||||
@ -1235,9 +1234,10 @@ nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct proc *p)
|
||||
return (EINTR);
|
||||
if (!(nmp->nm_flag & NFSMNT_INT))
|
||||
return (0);
|
||||
if (p == NULL)
|
||||
if (td == NULL)
|
||||
return (0);
|
||||
|
||||
p = td->td_proc;
|
||||
tmpset = p->p_siglist;
|
||||
SIGSETNAND(tmpset, p->p_sigmask);
|
||||
SIGSETNAND(tmpset, p->p_sigignore);
|
||||
@ -1267,7 +1267,7 @@ nfs_sndlock(struct nfsreq *rep)
|
||||
} else
|
||||
td = (struct thread *)0;
|
||||
while (*statep & NFSSTA_SNDLOCK) {
|
||||
if (nfs_sigintr(rep->r_nmp, rep, td ? td->td_proc : NULL))
|
||||
if (nfs_sigintr(rep->r_nmp, rep, td))
|
||||
return (EINTR);
|
||||
*statep |= NFSSTA_WANTSND;
|
||||
(void) tsleep((caddr_t)statep, slpflag | (PZERO - 1),
|
||||
@ -1309,8 +1309,7 @@ nfs_rcvlock(struct nfsreq *rep)
|
||||
else
|
||||
slpflag = 0;
|
||||
while (*statep & NFSSTA_RCVLOCK) {
|
||||
if (nfs_sigintr(rep->r_nmp, rep,
|
||||
(rep->r_td ? rep->r_td->td_proc : NULL)))
|
||||
if (nfs_sigintr(rep->r_nmp, rep, rep->r_td))
|
||||
return (EINTR);
|
||||
*statep |= NFSSTA_WANTRCV;
|
||||
(void) tsleep((caddr_t)statep, slpflag | (PZERO - 1), "nfsrcvlk",
|
||||
|
@ -2776,7 +2776,7 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td,
|
||||
panic("nfs_fsync: inconsistent lock");
|
||||
if (error == ENOLCK)
|
||||
goto loop;
|
||||
if (nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc)) {
|
||||
if (nfs_sigintr(nmp, (struct nfsreq *)0, td)) {
|
||||
error = EINTR;
|
||||
goto done;
|
||||
}
|
||||
@ -2812,7 +2812,7 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td,
|
||||
error = tsleep((caddr_t)&vp->v_numoutput,
|
||||
slpflag | (PRIBIO + 1), "nfsfsync", slptimeo);
|
||||
if (error) {
|
||||
if (nfs_sigintr(nmp, (struct nfsreq *)0, td->td_proc)) {
|
||||
if (nfs_sigintr(nmp, (struct nfsreq *)0, td)) {
|
||||
error = EINTR;
|
||||
goto done;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user