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