Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/ufs Prevent dirops from getting around lfs_check and wed...



details:   https://anonhg.NetBSD.org/src/rev/f2dc1a284345
branches:  trunk
changeset: 486626:f2dc1a284345
user:      perseant <perseant%NetBSD.org@localhost>
date:      Sat May 27 00:19:52 2000 +0000

description:
Prevent dirops from getting around lfs_check and wedging the buffer cache.
All the dirop vnops now mark the inodes with a new flag, IN_ADIROP, which
is removed as soon as the dirop is done (as opposed to VDIROP which stays
until the file is written).  To address one issue raised in PR#9357.

diffstat:

 sys/ufs/lfs/lfs.h           |    3 +-
 sys/ufs/lfs/lfs_alloc.c     |    6 +-
 sys/ufs/lfs/lfs_bio.c       |   39 ++++++++++----
 sys/ufs/lfs/lfs_segment.c   |   10 +---
 sys/ufs/lfs/lfs_vfsops.c    |    3 +-
 sys/ufs/lfs/lfs_vnops.c     |  115 ++++++++++++++++++++++++++++---------------
 sys/ufs/ufs/inode.h         |    3 +-
 sys/ufs/ufs/ufs_readwrite.c |    9 +++-
 8 files changed, 122 insertions(+), 66 deletions(-)

diffs (truncated from 474 to 300 lines):

diff -r f8e8643874ed -r f2dc1a284345 sys/ufs/lfs/lfs.h
--- a/sys/ufs/lfs/lfs.h Sat May 27 00:11:12 2000 +0000
+++ b/sys/ufs/lfs/lfs.h Sat May 27 00:19:52 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs.h,v 1.22 2000/05/13 23:43:14 perseant Exp $        */
+/*     $NetBSD: lfs.h,v 1.23 2000/05/27 00:19:52 perseant Exp $        */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -300,6 +300,7 @@
        struct vnode *lfs_unlockvp;     /* being inactivated in lfs_segunlock */
        u_int32_t lfs_diropwait;        /* # procs waiting on dirop flush */
        struct lock lfs_freelock;
+       int       lfs_nadirop;          /* number of active dirop nodes */
 };
 
 /*
diff -r f8e8643874ed -r f2dc1a284345 sys/ufs/lfs/lfs_alloc.c
--- a/sys/ufs/lfs/lfs_alloc.c   Sat May 27 00:11:12 2000 +0000
+++ b/sys/ufs/lfs/lfs_alloc.c   Sat May 27 00:19:52 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_alloc.c,v 1.31 2000/01/19 00:03:04 perseant Exp $  */
+/*     $NetBSD: lfs_alloc.c,v 1.32 2000/05/27 00:19:52 perseant Exp $  */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -230,6 +230,10 @@
        vp->v_flag |= VDIROP;
        VREF(ip->i_devvp);
        
+       if(!(ip->i_flag & IN_ADIROP))
+               ++fs->lfs_nadirop;
+       ip->i_flag |= IN_ADIROP;
+
        /* Set superblock modified bit and increment file count. */
        fs->lfs_fmod = 1;
        ++fs->lfs_nfiles;
diff -r f8e8643874ed -r f2dc1a284345 sys/ufs/lfs/lfs_bio.c
--- a/sys/ufs/lfs/lfs_bio.c     Sat May 27 00:11:12 2000 +0000
+++ b/sys/ufs/lfs/lfs_bio.c     Sat May 27 00:19:52 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_bio.c,v 1.19 2000/05/19 04:34:44 thorpej Exp $     */
+/*     $NetBSD: lfs_bio.c,v 1.20 2000/05/27 00:19:52 perseant Exp $    */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -358,24 +358,39 @@
 {
        int error;
        struct lfs *fs;
+       struct inode *ip;
        extern int lfs_dirvcount;
 
        error = 0;
+       ip = VTOI(vp);
        
        /* If out of buffers, wait on writer */
        /* XXX KS - if it's the Ifile, we're probably the cleaner! */
-       if (VTOI(vp)->i_number == LFS_IFILE_INUM)
+       if (ip->i_number == LFS_IFILE_INUM)
+               return 0;
+       /* If we're being called from inside a dirop, don't sleep */
+       if (ip->i_flag & IN_ADIROP)
                return 0;
 
-       /* If dirops are active, can't flush.  Wait for SET_ENDOP */
-       fs = VTOI(vp)->i_lfs;
-       if (fs->lfs_dirops)
-               return 0;
+       fs = ip->i_lfs;
 
-       if (locked_queue_count > LFS_MAX_BUFS
-           || locked_queue_bytes > LFS_MAX_BYTES
-           || lfs_dirvcount > LFS_MAXDIROP
-           || fs->lfs_diropwait > 0)
+       /*
+        * If we would flush below, but dirops are active, sleep.
+        * Note that a dirop cannot ever reach this code!
+        */
+       while (fs->lfs_dirops > 0 &&
+              (locked_queue_count > LFS_MAX_BUFS ||
+                locked_queue_bytes > LFS_MAX_BYTES ||
+                lfs_dirvcount > LFS_MAXDIROP || fs->lfs_diropwait > 0))
+       {
+               ++fs->lfs_diropwait;
+               tsleep(&fs->lfs_writer, PRIBIO+1, "bufdirop", 0);
+               --fs->lfs_diropwait;
+       }
+
+       if (locked_queue_count > LFS_MAX_BUFS ||
+           locked_queue_bytes > LFS_MAX_BYTES ||
+           lfs_dirvcount > LFS_MAXDIROP || fs->lfs_diropwait > 0)
        {
                ++fs->lfs_writer;
                lfs_flush(fs, flags);
@@ -399,8 +414,8 @@
                 * inodes were locked.  Try flushing again to keep us from
                 * blocking indefinitely.
                 */
-               if (locked_queue_count > LFS_MAX_BUFS
-                   || locked_queue_bytes > LFS_MAX_BYTES)
+               if (locked_queue_count > LFS_MAX_BUFS ||
+                   locked_queue_bytes > LFS_MAX_BYTES)
                {
                        ++fs->lfs_writer;
                        lfs_flush(fs, flags);
diff -r f8e8643874ed -r f2dc1a284345 sys/ufs/lfs/lfs_segment.c
--- a/sys/ufs/lfs/lfs_segment.c Sat May 27 00:11:12 2000 +0000
+++ b/sys/ufs/lfs/lfs_segment.c Sat May 27 00:19:52 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_segment.c,v 1.45 2000/05/19 04:34:44 thorpej Exp $ */
+/*     $NetBSD: lfs_segment.c,v 1.46 2000/05/27 00:19:53 perseant Exp $        */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -419,7 +419,7 @@
                                lfs_vunref(vp);
                                continue;
                        }
-               } else {
+               } else if (vp != fs->lfs_ivnode) {
                        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                        needs_unlock = 1;
                }
@@ -1025,8 +1025,6 @@
                        if(vp != fs->lfs_ivnode && (ooff == 0 || ooff == UNASSIGNED)) {
 #ifdef DEBUG_LFS
                                printf("lfs_updatemeta[1]: warning: writing ino %d lbn %d at 0x%x, was 0x%x\n", ip->i_number, lbn, off, ooff);
-#else
-                               ;
 #endif
                        } else
                                ip->i_ffs_db[lbn] = off;
@@ -1036,8 +1034,6 @@
                        if(vp != fs->lfs_ivnode && (ooff == 0 || ooff == UNASSIGNED)) {
 #ifdef DEBUG_LFS
                                printf("lfs_updatemeta[2]: warning: writing ino %d lbn %d at 0x%x, was 0x%x\n", ip->i_number, lbn, off, ooff);
-#else
-                               ;
 #endif
                        } else
                                ip->i_ffs_ib[a[0].in_off] = off;
@@ -1082,8 +1078,6 @@
                        if(vp != fs->lfs_ivnode && (ooff == 0 || ooff == UNASSIGNED)) {
 #ifdef DEBUG_LFS
                                printf("lfs_updatemeta[3]: warning: writing ino %d lbn %d at 0x%x, was 0x%x\n", ip->i_number, lbn, off, ooff);
-#else
-                               ;
 #endif
                                brelse(bp);
                        } else {
diff -r f8e8643874ed -r f2dc1a284345 sys/ufs/lfs/lfs_vfsops.c
--- a/sys/ufs/lfs/lfs_vfsops.c  Sat May 27 00:11:12 2000 +0000
+++ b/sys/ufs/lfs/lfs_vfsops.c  Sat May 27 00:19:52 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_vfsops.c,v 1.51 2000/05/19 04:34:45 thorpej Exp $  */
+/*     $NetBSD: lfs_vfsops.c,v 1.52 2000/05/27 00:19:53 perseant Exp $ */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -434,6 +434,7 @@
        fs->lfs_doifile = 0;
        fs->lfs_writer = 0;
        fs->lfs_dirops = 0;
+       fs->lfs_nadirop = 0;
        fs->lfs_seglock = 0;
        lockinit(&fs->lfs_freelock, PINOD, "lfs_freelock", 0, 0);
 
diff -r f8e8643874ed -r f2dc1a284345 sys/ufs/lfs/lfs_vnops.c
--- a/sys/ufs/lfs/lfs_vnops.c   Sat May 27 00:11:12 2000 +0000
+++ b/sys/ufs/lfs/lfs_vnops.c   Sat May 27 00:19:52 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_vnops.c,v 1.36 2000/05/13 23:43:15 perseant Exp $  */
+/*     $NetBSD: lfs_vnops.c,v 1.37 2000/05/27 00:19:54 perseant Exp $  */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -277,7 +277,7 @@
        } */ *ap = v;
        
        return (VOP_UPDATE(ap->a_vp, NULL, NULL,
-                          (ap->a_flags & FSYNC_WAIT) != 0 ? UPDATE_WAIT : 0)); /* XXX */
+                          (ap->a_flags & FSYNC_WAIT) != 0 ? UPDATE_WAIT : 0));
 }
 
 /*
@@ -315,7 +315,7 @@
 #ifdef DEBUG_LFS
                        printf("lfs_set_dirop: sleeping with dirops=%d, dirvcount=%d\n",fs->lfs_dirops,lfs_dirvcount); 
 #endif
-                       if((error=tsleep(&lfs_dirvcount, PCATCH|PUSER, "lfs_maxdirop", 0))!=0)
+                       if((error = tsleep(&lfs_dirvcount, PCATCH|PUSER, "lfs_maxdirop", 0)) !=0)
                                return error;
                }                                                       
        }                                                               
@@ -328,17 +328,30 @@
 #define        SET_ENDOP(fs,vp,str) {                                          \
        --(fs)->lfs_dirops;                                             \
        if (!(fs)->lfs_dirops) {                                        \
+               if ((fs)->lfs_nadirop)                                  \
+                       panic("no dirops but nadirop=%d\n", (fs)->lfs_nadirop);\
                wakeup(&(fs)->lfs_writer);                              \
                lfs_check((vp),LFS_UNUSED_LBN,0);                       \
        }                                                               \
 }
 
 #define        MARK_VNODE(dvp)  do {                                           \
-        if(!((dvp)->v_flag & VDIROP)) {                                        \
+        if (!((dvp)->v_flag & VDIROP)) {                               \
                 lfs_vref(dvp);                                         \
                ++lfs_dirvcount;                                        \
        }                                                               \
         (dvp)->v_flag |= VDIROP;                                       \
+       if (!(VTOI(dvp)->i_flag & IN_ADIROP)) {                         \
+               ++VTOI(dvp)->i_lfs->lfs_nadirop;                        \
+       }                                                               \
+       VTOI(dvp)->i_flag |= IN_ADIROP;                                 \
+} while(0)
+
+#define UNMARK_VNODE(vp) do {                                          \
+       if (VTOI(vp)->i_flag & IN_ADIROP) {                             \
+               --VTOI(vp)->i_lfs->lfs_nadirop;                         \
+       }                                                               \
+       VTOI(vp)->i_flag &= ~IN_ADIROP;                                 \
 } while(0)
 
 int
@@ -352,16 +365,19 @@
                struct vattr *a_vap;
                char *a_target;
        } */ *ap = v;
-       int ret;
+       int error;
 
-       if((ret=SET_DIROP(VTOI(ap->a_dvp)->i_lfs))!=0) {
+       if ((error = SET_DIROP(VTOI(ap->a_dvp)->i_lfs)) != 0) {
                vput(ap->a_dvp);
-               return ret;
+               return error;
        }
        MARK_VNODE(ap->a_dvp);
-       ret = ufs_symlink(ap);
-       SET_ENDOP(VTOI(ap->a_dvp)->i_lfs,ap->a_dvp,"symilnk");
-       return (ret);
+       error = ufs_symlink(ap);
+       UNMARK_VNODE(ap->a_dvp);
+       if (error == 0)
+               UNMARK_VNODE(*(ap->a_vpp));
+       SET_ENDOP(VTOI(ap->a_dvp)->i_lfs,ap->a_dvp,"symlink");
+       return (error);
 }
 
 int
@@ -379,13 +395,16 @@
         struct inode *ip;
         int error;
 
-       if((error=SET_DIROP(VTOI(ap->a_dvp)->i_lfs))!=0) {
+       if ((error = SET_DIROP(VTOI(ap->a_dvp)->i_lfs)) != 0) {
                vput(ap->a_dvp);
                return error;
        }
        MARK_VNODE(ap->a_dvp);
        error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
             ap->a_dvp, vpp, ap->a_cnp);
+       UNMARK_VNODE(ap->a_dvp);
+        if (error == 0)
+                UNMARK_VNODE(*(ap->a_vpp));
 
        /* Either way we're done with the dirop at this point */
        SET_ENDOP(VTOI(ap->a_dvp)->i_lfs,ap->a_dvp,"mknod");
@@ -441,16 +460,19 @@
                struct componentname *a_cnp;
                struct vattr *a_vap;
        } */ *ap = v;
-       int ret;
+       int error;
 
-       if((ret=SET_DIROP(VTOI(ap->a_dvp)->i_lfs))!=0) {
+       if((error = SET_DIROP(VTOI(ap->a_dvp)->i_lfs)) != 0) {
                vput(ap->a_dvp);
-               return ret;
+               return error;
        }
        MARK_VNODE(ap->a_dvp);
-       ret = ufs_create(ap);
+       error = ufs_create(ap);
+       UNMARK_VNODE(ap->a_dvp);
+        if (error == 0)
+                UNMARK_VNODE(*(ap->a_vpp));
        SET_ENDOP(VTOI(ap->a_dvp)->i_lfs,ap->a_dvp,"create");
-       return (ret);
+       return (error);
 }
 
 int
@@ -462,15 +484,16 @@
                struct componentname *a_cnp;
                int a_flags;
        } */ *ap = v;



Home | Main Index | Thread Index | Old Index