From e5f751a9b29d8ecbe528c905ae7e4dc126be08d3 Mon Sep 17 00:00:00 2001 From: John Dyson Date: Mon, 24 Apr 1995 05:13:28 +0000 Subject: [PATCH] Changes to get rid of ufslk2 hangs when doing read/write to/from mmap regions that are in the same file as the read/write. --- sys/gnu/ext2fs/ext2_ihash.c | 24 ++++++++++++++------ sys/gnu/ext2fs/inode.h | 6 +++-- sys/gnu/fs/ext2fs/inode.h | 6 +++-- sys/ufs/lfs/lfs_syscalls.c | 4 +++- sys/ufs/ufs/inode.h | 6 +++-- sys/ufs/ufs/ufs_ihash.c | 24 ++++++++++++++------ sys/ufs/ufs/ufs_readwrite.c | 10 ++++++++- sys/ufs/ufs/ufs_vnops.c | 44 +++++++++++++++++++++++-------------- 8 files changed, 85 insertions(+), 39 deletions(-) diff --git a/sys/gnu/ext2fs/ext2_ihash.c b/sys/gnu/ext2fs/ext2_ihash.c index ce5b0f8d8e10..18ac11c40622 100644 --- a/sys/gnu/ext2fs/ext2_ihash.c +++ b/sys/gnu/ext2fs/ext2_ihash.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ufs_ihash.c 8.4 (Berkeley) 12/30/93 - * $Id: ufs_ihash.c,v 1.3 1994/10/06 21:07:01 davidg Exp $ + * $Id: ufs_ihash.c,v 1.4 1994/10/08 06:57:23 phk Exp $ */ #include @@ -99,9 +99,15 @@ ufs_ihashget(device, inum) return (NULL); if (inum == ip->i_number && device == ip->i_dev) { if (ip->i_flag & IN_LOCKED) { - ip->i_flag |= IN_WANTED; - (void) tsleep(ip, PINOD, "uihget", 0); - break; + if( curproc->p_pid != ip->i_lockholder) { + ip->i_flag |= IN_WANTED; + (void) tsleep(ip, PINOD, "uihget", 0); + break; + } else if (ip->i_flag & IN_RECURSE) { + ip->i_lockcount++; + } else { + panic("ufs_ihashget: recursive lock not expected -- pid %d\n", ip->i_lockholder); + } } vp = ITOV(ip); if (!vget(vp, 1)) @@ -128,12 +134,16 @@ ufs_ihashins(ip) ip->i_next = iq; ip->i_prev = ipp; *ipp = ip; - if (ip->i_flag & IN_LOCKED) + if ((ip->i_flag & IN_LOCKED) && + ((ip->i_flag & IN_RECURSE) == 0 || + (!curproc || (curproc && (ip->i_lockholder != curproc->p_pid))))) panic("ufs_ihashins: already locked"); - if (curproc) + if (curproc) { + ip->i_lockcount += 1; ip->i_lockholder = curproc->p_pid; - else + } else { ip->i_lockholder = -1; + } ip->i_flag |= IN_LOCKED; } diff --git a/sys/gnu/ext2fs/inode.h b/sys/gnu/ext2fs/inode.h index 16467926e7fe..f0c729769c8b 100644 --- a/sys/gnu/ext2fs/inode.h +++ b/sys/gnu/ext2fs/inode.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)inode.h 8.4 (Berkeley) 1/21/94 - * $Id: inode.h,v 1.3 1994/08/21 07:16:15 paul Exp $ + * $Id: inode.h,v 1.4 1994/12/27 13:59:14 bde Exp $ */ #ifndef _UFS_UFS_INODE_H_ @@ -91,7 +91,8 @@ struct inode { doff_t i_offset; /* Offset of free space in directory. */ ino_t i_ino; /* Inode number of found directory. */ u_long i_reclen; /* Size of found directory entry. */ - long i_spare[11]; /* Spares to round up to 128 bytes. */ + int i_lockcount; /* Process lock count (recursion) */ + long i_spare[10]; /* Spares to round up to 128 bytes. */ /* * The on-disk dinode itself. */ @@ -125,6 +126,7 @@ struct inode { #define IN_SHLOCK 0x0080 /* File has shared lock. */ #define IN_UPDATE 0x0100 /* Modification time update request. */ #define IN_WANTED 0x0200 /* Inode is wanted by a process. */ +#define IN_RECURSE 0x0400 /* Recursion expected */ #ifdef KERNEL /* diff --git a/sys/gnu/fs/ext2fs/inode.h b/sys/gnu/fs/ext2fs/inode.h index 16467926e7fe..f0c729769c8b 100644 --- a/sys/gnu/fs/ext2fs/inode.h +++ b/sys/gnu/fs/ext2fs/inode.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)inode.h 8.4 (Berkeley) 1/21/94 - * $Id: inode.h,v 1.3 1994/08/21 07:16:15 paul Exp $ + * $Id: inode.h,v 1.4 1994/12/27 13:59:14 bde Exp $ */ #ifndef _UFS_UFS_INODE_H_ @@ -91,7 +91,8 @@ struct inode { doff_t i_offset; /* Offset of free space in directory. */ ino_t i_ino; /* Inode number of found directory. */ u_long i_reclen; /* Size of found directory entry. */ - long i_spare[11]; /* Spares to round up to 128 bytes. */ + int i_lockcount; /* Process lock count (recursion) */ + long i_spare[10]; /* Spares to round up to 128 bytes. */ /* * The on-disk dinode itself. */ @@ -125,6 +126,7 @@ struct inode { #define IN_SHLOCK 0x0080 /* File has shared lock. */ #define IN_UPDATE 0x0100 /* Modification time update request. */ #define IN_WANTED 0x0200 /* Inode is wanted by a process. */ +#define IN_RECURSE 0x0400 /* Recursion expected */ #ifdef KERNEL /* diff --git a/sys/ufs/lfs/lfs_syscalls.c b/sys/ufs/lfs/lfs_syscalls.c index 32e2f029fdcd..33fc873eb231 100644 --- a/sys/ufs/lfs/lfs_syscalls.c +++ b/sys/ufs/lfs/lfs_syscalls.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)lfs_syscalls.c 8.5 (Berkeley) 4/20/94 - * $Id: lfs_syscalls.c,v 1.6 1995/01/09 16:05:23 davidg Exp $ + * $Id: lfs_syscalls.c,v 1.7 1995/03/28 07:58:06 bde Exp $ */ #include @@ -527,6 +527,8 @@ lfs_fastvget(mp, ino, daddr, vpp, dinp) /* Inode was just read from user space or disk, make sure it's locked */ ip->i_flag |= IN_LOCKED; + ip->i_lockholder = curproc->p_pid; + ip->i_lockcount = 1; /* * Initialize the vnode from the inode, check for aliases. In all diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h index 16467926e7fe..f0c729769c8b 100644 --- a/sys/ufs/ufs/inode.h +++ b/sys/ufs/ufs/inode.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)inode.h 8.4 (Berkeley) 1/21/94 - * $Id: inode.h,v 1.3 1994/08/21 07:16:15 paul Exp $ + * $Id: inode.h,v 1.4 1994/12/27 13:59:14 bde Exp $ */ #ifndef _UFS_UFS_INODE_H_ @@ -91,7 +91,8 @@ struct inode { doff_t i_offset; /* Offset of free space in directory. */ ino_t i_ino; /* Inode number of found directory. */ u_long i_reclen; /* Size of found directory entry. */ - long i_spare[11]; /* Spares to round up to 128 bytes. */ + int i_lockcount; /* Process lock count (recursion) */ + long i_spare[10]; /* Spares to round up to 128 bytes. */ /* * The on-disk dinode itself. */ @@ -125,6 +126,7 @@ struct inode { #define IN_SHLOCK 0x0080 /* File has shared lock. */ #define IN_UPDATE 0x0100 /* Modification time update request. */ #define IN_WANTED 0x0200 /* Inode is wanted by a process. */ +#define IN_RECURSE 0x0400 /* Recursion expected */ #ifdef KERNEL /* diff --git a/sys/ufs/ufs/ufs_ihash.c b/sys/ufs/ufs/ufs_ihash.c index ce5b0f8d8e10..18ac11c40622 100644 --- a/sys/ufs/ufs/ufs_ihash.c +++ b/sys/ufs/ufs/ufs_ihash.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ufs_ihash.c 8.4 (Berkeley) 12/30/93 - * $Id: ufs_ihash.c,v 1.3 1994/10/06 21:07:01 davidg Exp $ + * $Id: ufs_ihash.c,v 1.4 1994/10/08 06:57:23 phk Exp $ */ #include @@ -99,9 +99,15 @@ ufs_ihashget(device, inum) return (NULL); if (inum == ip->i_number && device == ip->i_dev) { if (ip->i_flag & IN_LOCKED) { - ip->i_flag |= IN_WANTED; - (void) tsleep(ip, PINOD, "uihget", 0); - break; + if( curproc->p_pid != ip->i_lockholder) { + ip->i_flag |= IN_WANTED; + (void) tsleep(ip, PINOD, "uihget", 0); + break; + } else if (ip->i_flag & IN_RECURSE) { + ip->i_lockcount++; + } else { + panic("ufs_ihashget: recursive lock not expected -- pid %d\n", ip->i_lockholder); + } } vp = ITOV(ip); if (!vget(vp, 1)) @@ -128,12 +134,16 @@ ufs_ihashins(ip) ip->i_next = iq; ip->i_prev = ipp; *ipp = ip; - if (ip->i_flag & IN_LOCKED) + if ((ip->i_flag & IN_LOCKED) && + ((ip->i_flag & IN_RECURSE) == 0 || + (!curproc || (curproc && (ip->i_lockholder != curproc->p_pid))))) panic("ufs_ihashins: already locked"); - if (curproc) + if (curproc) { + ip->i_lockcount += 1; ip->i_lockholder = curproc->p_pid; - else + } else { ip->i_lockholder = -1; + } ip->i_flag |= IN_LOCKED; } diff --git a/sys/ufs/ufs/ufs_readwrite.c b/sys/ufs/ufs/ufs_readwrite.c index 437af5bb533a..5b273bedeb40 100644 --- a/sys/ufs/ufs/ufs_readwrite.c +++ b/sys/ufs/ufs/ufs_readwrite.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ufs_readwrite.c 8.7 (Berkeley) 1/21/94 - * $Id: ufs_readwrite.c,v 1.7 1995/01/24 10:02:00 davidg Exp $ + * $Id: ufs_readwrite.c,v 1.8 1995/04/09 06:03:44 davidg Exp $ */ #ifdef LFS_READWRITE @@ -143,8 +143,12 @@ READ(ap) break; xfersize = size; } + if (uio->uio_segflg != UIO_NOCOPY) + ip->i_flag |= IN_RECURSE; error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio); + if (uio->uio_segflg != UIO_NOCOPY) + ip->i_flag &= ~IN_RECURSE; if (error) break; @@ -258,8 +262,12 @@ WRITE(ap) if (size < xfersize) xfersize = size; + if (uio->uio_segflg != UIO_NOCOPY) + ip->i_flag |= IN_RECURSE; error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio); + if (uio->uio_segflg != UIO_NOCOPY) + ip->i_flag &= ~IN_RECURSE; #ifdef LFS_READWRITE (void)VOP_BWRITE(bp); #else diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 6fd7c1ea78f8..379e2671569a 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)ufs_vnops.c 8.10 (Berkeley) 4/1/94 - * $Id: ufs_vnops.c,v 1.19 1995/03/19 13:44:03 davidg Exp $ + * $Id: ufs_vnops.c,v 1.20 1995/04/09 06:03:45 davidg Exp $ */ #include @@ -1526,9 +1526,7 @@ ufs_lock(ap) struct vnode *a_vp; } */ *ap; { -#ifdef DIAGNOSTIC - struct proc *p = curproc; /* XXX */ -#endif + struct proc *p = curproc; register struct vnode *vp = ap->a_vp; register struct inode *ip; @@ -1541,17 +1539,23 @@ start: return (ENOENT); ip = VTOI(vp); if (ip->i_flag & IN_LOCKED) { - ip->i_flag |= IN_WANTED; + if (p->p_pid == ip->i_lockholder) { + if( ip->i_flag & IN_RECURSE) + ++ip->i_lockcount; + else + panic("ufs_lock: recursive lock not expected, pid: %d\n", + ip->i_lockholder); + } else { + ip->i_flag |= IN_WANTED; #ifdef DIAGNOSTIC - if (p) { - if (p->p_pid == ip->i_lockholder) - panic("locking against myself"); - ip->i_lockwaiter = p->p_pid; - } else - ip->i_lockwaiter = -1; + if (p) + ip->i_lockwaiter = p->p_pid; + else + ip->i_lockwaiter = -1; #endif - (void) tsleep((caddr_t)ip, PINOD, "ufslk2", 0); - goto start; + (void) tsleep((caddr_t)ip, PINOD, "ufslk2", 0); + goto start; + } } #ifdef DIAGNOSTIC ip->i_lockwaiter = 0; @@ -1559,11 +1563,11 @@ start: panic("lockholder (%d) != 0", ip->i_lockholder); if (p && p->p_pid == 0) printf("locking by process 0\n"); +#endif if (p) ip->i_lockholder = p->p_pid; else ip->i_lockholder = -1; -#endif ip->i_flag |= IN_LOCKED; return (0); } @@ -1579,9 +1583,9 @@ ufs_unlock(ap) } */ *ap; { register struct inode *ip = VTOI(ap->a_vp); + struct proc *p = curproc; #ifdef DIAGNOSTIC - struct proc *p = curproc; /* XXX */ if ((ip->i_flag & IN_LOCKED) == 0) { vprint("ufs_unlock: unlocked inode", ap->a_vp); @@ -1591,9 +1595,15 @@ ufs_unlock(ap) ip->i_lockholder > -1 && lockcount++ < 100) panic("unlocker (%d) != lock holder (%d)", p->p_pid, ip->i_lockholder); - ip->i_lockholder = 0; #endif - ip->i_flag &= ~IN_LOCKED; + if (--ip->i_lockcount > 0) { + if ((ip->i_flag & IN_RECURSE) == 0) + panic("ufs_unlock: recursive lock prematurely released, pid=%d\n", + ip->i_lockholder); + return (0); + } + ip->i_lockholder = 0; + ip->i_flag &= ~(IN_LOCKED|IN_RECURSE); if (ip->i_flag & IN_WANTED) { ip->i_flag &= ~IN_WANTED; wakeup((caddr_t)ip);