tech-kern archive

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

Propagating wapbl state through VOP_PUTPAGES



While working on snapshot support for log enabled ffs file systems there
is one problem left with VOP_PUTPAGES() leading to ffs_copyonwrite().

When ffs_copyonwrite() gets called with a buffer from buffercache we are
always inside a wapbl transaction so it is safe to allocate a file system
block to hold the to-be-overwritten data.

When the buffer leading to ffs_copyonwrite() comes via VOP_PUTPAGES()
the situation is more difficult.  Usually we are outside a wapbl transaction
and therefore we could just tag buffers originating from buffercache and
we were done.  Unfortunately the code path  ffs_write() -> VOP_PUTPAGES()  is
an exception.  Here we are inside a wapbl transaction.

One solution is to add ffs_gop_write() as a wrapper around genfs_gop_write(),
make sure genfs_gop_write() gets always called inside a wapbl transaction and
propagate the wapbl transaction state through a new flag PGO_JOURNALLOCKED.

Comments, other ideas or objections?

-- 
Juergen Hannken-Illjes - hannken%eis.cs.tu-bs.de@localhost - TU Braunschweig 
(Germany)

Index: sys/uvm/uvm_pager.h
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_pager.h,v
retrieving revision 1.37
diff -p -u -4 -r1.37 uvm_pager.h
--- sys/uvm/uvm_pager.h 25 Oct 2007 13:03:06 -0000      1.37
+++ sys/uvm/uvm_pager.h 16 Aug 2008 07:48:45 -0000
@@ -155,8 +155,9 @@ struct uvm_pagerops {
 #define PGO_FREE       0x008   /* free flushed pages */
 /* if PGO_FREE is not set then the pages stay where they are. */
 
 #define PGO_ALLPAGES   0x010   /* flush whole object/get all pages */
+#define PGO_JOURNALLOCKED 0x20 /* journal is already locked */
 #define PGO_LOCKED     0x040   /* fault data structures are locked [get] */
 #define PGO_BUSYFAIL   0x080   /* fail if a page is busy [put] */
 #define PGO_OVERWRITE  0x200   /* pages will be overwritten before unlocked */
 #define PGO_PASTEOF    0x400   /* allow allocation of pages past EOF */
Index: sys/ufs/ffs/ffs_extern.h
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_extern.h,v
retrieving revision 1.68
diff -p -u -4 -r1.68 ffs_extern.h
--- sys/ufs/ffs/ffs_extern.h    12 Aug 2008 10:14:37 -0000      1.68
+++ sys/ufs/ffs/ffs_extern.h    16 Aug 2008 07:48:44 -0000
@@ -127,8 +127,9 @@ int ffs_write(void *);
 int    ffs_fsync(void *);
 int    ffs_reclaim(void *);
 int    ffs_getpages(void *);
 void   ffs_gop_size(struct vnode *, off_t, off_t *, int);
+int    ffs_gop_write(struct vnode *, struct vm_page **, int, int);
 int    ffs_openextattr(void *);
 int    ffs_closeextattr(void *);
 int    ffs_getextattr(void *);
 int    ffs_setextattr(void *);
Index: sys/ufs/ffs/ffs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.233
diff -p -u -4 -r1.233 ffs_vfsops.c
--- sys/ufs/ffs/ffs_vfsops.c    15 Aug 2008 17:32:32 -0000      1.233
+++ sys/ufs/ffs/ffs_vfsops.c    16 Aug 2008 07:48:44 -0000
@@ -159,9 +159,9 @@ struct vfsops ffs_vfsops = {
 
 static const struct genfs_ops ffs_genfsops = {
        .gop_size = ffs_gop_size,
        .gop_alloc = ufs_gop_alloc,
-       .gop_write = genfs_gop_write,
+       .gop_write = ffs_gop_write,
        .gop_markupdate = ufs_gop_markupdate,
 };
 
 static const struct ufs_ops ffs_ufsops = {
Index: sys/ufs/ffs/ffs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_vnops.c,v
retrieving revision 1.102
diff -p -u -4 -r1.102 ffs_vnops.c
--- sys/ufs/ffs/ffs_vnops.c     12 Aug 2008 10:14:37 -0000      1.102
+++ sys/ufs/ffs/ffs_vnops.c     16 Aug 2008 07:48:45 -0000
@@ -692,8 +692,26 @@ ffs_gop_size(struct vnode *vp, off_t siz
        }
 }
 
 int
+ffs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags)
+{
+       int error;
+       const bool need_wapbl = (curlwp != uvm.pagedaemon_lwp &&
+           vp->v_mount->mnt_wapbl && (flags & PGO_JOURNALLOCKED) == 0);
+
+       if (need_wapbl) {
+               error = UFS_WAPBL_BEGIN(vp->v_mount);
+               if (error)
+                       return error;
+       }
+       error = genfs_gop_write(vp, pgs, npages, flags);
+       if (need_wapbl)
+               UFS_WAPBL_END(vp->v_mount);
+       return error;
+}
+
+int
 ffs_openextattr(void *v)
 {
        struct vop_openextattr_args /* {
                struct vnode *a_vp;
Index: sys/ufs/ufs/ufs_readwrite.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ufs/ufs_readwrite.c,v
retrieving revision 1.90
diff -p -u -4 -r1.90 ufs_readwrite.c
--- sys/ufs/ufs/ufs_readwrite.c 12 Aug 2008 10:14:38 -0000      1.90
+++ sys/ufs/ufs/ufs_readwrite.c 16 Aug 2008 07:48:45 -0000
@@ -336,9 +336,10 @@ WRITE(void *v)
                        goto out;
                if (flags & B_SYNC) {
                        mutex_enter(&vp->v_interlock);
                        VOP_PUTPAGES(vp, trunc_page(osize & fs->fs_bmask),
-                           round_page(eob), PGO_CLEANIT | PGO_SYNCIO);
+                           round_page(eob),
+                           PGO_CLEANIT | PGO_SYNCIO | PGO_JOURNALLOCKED);
                }
        }
 
        while (uio->uio_resid > 0) {
@@ -431,9 +432,10 @@ WRITE(void *v)
 #ifndef LFS_READWRITE
                if (!async && oldoff >> 16 != uio->uio_offset >> 16) {
                        mutex_enter(&vp->v_interlock);
                        error = VOP_PUTPAGES(vp, (oldoff >> 16) << 16,
-                           (uio->uio_offset >> 16) << 16, PGO_CLEANIT);
+                           (uio->uio_offset >> 16) << 16,
+                           PGO_CLEANIT | PGO_JOURNALLOCKED);
                        if (error)
                                break;
                }
 #endif
@@ -441,16 +443,16 @@ WRITE(void *v)
        if (error == 0 && ioflag & IO_SYNC) {
                mutex_enter(&vp->v_interlock);
                error = VOP_PUTPAGES(vp, trunc_page(origoff & fs->fs_bmask),
                    round_page(blkroundup(fs, uio->uio_offset)),
-                   PGO_CLEANIT | PGO_SYNCIO);
+                   PGO_CLEANIT | PGO_SYNCIO | PGO_JOURNALLOCKED);
        }
        goto out;
 
  bcache:
        mutex_enter(&vp->v_interlock);
        VOP_PUTPAGES(vp, trunc_page(origoff), round_page(origoff + resid),
-           PGO_CLEANIT | PGO_FREE | PGO_SYNCIO);
+           PGO_CLEANIT | PGO_FREE | PGO_SYNCIO | PGO_JOURNALLOCKED);
        while (uio->uio_resid > 0) {
                lbn = lblkno(fs, uio->uio_offset);
                blkoffset = blkoff(fs, uio->uio_offset);
                xfersize = MIN(fs->fs_bsize - blkoffset, uio->uio_resid);


Home | Main Index | Thread Index | Old Index