From 42cd5131b0bc761c49ab4d67fc5cf88a4c03be8b Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 13 Jul 2009 20:46:45 -0700 Subject: [PATCH] HAMMER - Add MPSAFE suppor for hammer_vop_read(). This is still a bit of a hack. If vfs.read_mpsafe is set HAMMER will run MPSAFE for reads from regular files which are cached in the buffer cache. Data which is not cached will fall-back to getting the MP lock. At the moment enabling this operation will cause atime to not get updated on fully cached files, because the rest of HAMMER is not MPSAFE yet so I cannot modify the internal hammer_inode state. --- sys/vfs/hammer/hammer_inode.c | 6 +++++ sys/vfs/hammer/hammer_vnops.c | 46 ++++++++++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/sys/vfs/hammer/hammer_inode.c b/sys/vfs/hammer/hammer_inode.c index 4a4c306..dbdaaf2 100644 --- a/sys/vfs/hammer/hammer_inode.c +++ b/sys/vfs/hammer/hammer_inode.c @@ -275,6 +275,12 @@ hammer_get_vnode(struct hammer_inode *ip, struct vnode **vpp) case HAMMER_OBJTYPE_FIFO: vp->v_ops = &hmp->mp->mnt_vn_fifo_ops; break; + case HAMMER_OBJTYPE_REGFILE: + /* + * MPSAFE read supported. + */ + vp->v_flag |= VMP_READ; + break; default: break; } diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index b73f67c..00ae528 100644 --- a/sys/vfs/hammer/hammer_vnops.c +++ b/sys/vfs/hammer/hammer_vnops.c @@ -213,6 +213,8 @@ hammer_vop_fsync(struct vop_fsync_args *ap) /* * hammer_vop_read { vp, uio, ioflag, cred } + * + * MPALMOSTSAFE */ static int @@ -228,6 +230,7 @@ hammer_vop_read(struct vop_read_args *ap) int seqcount; int ioseqcount; int blksize; + int got_mplock = curthread->td_mpcount; if (ap->a_vp->v_type != VREG) return (EINVAL); @@ -244,12 +247,14 @@ hammer_vop_read(struct vop_read_args *ap) if (seqcount < ioseqcount) seqcount = ioseqcount; - hammer_start_transaction(&trans, ip->hmp); - /* * Access the data typically in HAMMER_BUFSIZE blocks via the * buffer cache, but HAMMER may use a variable block size based * on the offset. + * + * XXX Temporary hack, delay the start transaction while we remain + * MPSAFE. NOTE: ino_data.size cannot change while vnode is + * locked-shared. */ while (uio->uio_resid > 0 && uio->uio_offset < ip->ino_data.size) { int64_t base_offset; @@ -259,6 +264,24 @@ hammer_vop_read(struct vop_read_args *ap) offset = (int)uio->uio_offset & (blksize - 1); base_offset = uio->uio_offset - offset; + /* + * MPSAFE + */ + bp = getcacheblk(ap->a_vp, base_offset); + if (bp) { + error = 0; + goto skip; + } + + /* + * MPUNSAFE + */ + if (got_mplock == 0) { + got_mplock = 1; + get_mplock(); + hammer_start_transaction(&trans, ip->hmp); + } + if (hammer_cluster_enable) { /* * Use file_limit to prevent cluster_read() from @@ -282,6 +305,7 @@ hammer_vop_read(struct vop_read_args *ap) brelse(bp); break; } +skip: /* bp->b_flags |= B_CLUSTEROK; temporarily disabled */ n = blksize - offset; @@ -298,12 +322,20 @@ hammer_vop_read(struct vop_read_args *ap) break; hammer_stats_file_read += n; } - if ((ip->flags & HAMMER_INODE_RO) == 0 && - (ip->hmp->mp->mnt_flag & MNT_NOATIME) == 0) { - ip->ino_data.atime = trans.time; - hammer_modify_inode(ip, HAMMER_INODE_ATIME); + + /* + * XXX only update the atime if we had to get the MP lock. + * XXX hack hack hack, fixme. + */ + if (got_mplock) { + if ((ip->flags & HAMMER_INODE_RO) == 0 && + (ip->hmp->mp->mnt_flag & MNT_NOATIME) == 0) { + ip->ino_data.atime = trans.time; + hammer_modify_inode(ip, HAMMER_INODE_ATIME); + } + hammer_done_transaction(&trans); + rel_mplock(); } - hammer_done_transaction(&trans); return (error); } -- 1.7.7.2