/*
* hammer_vop_read { vp, uio, ioflag, cred }
+ *
+ * MPALMOSTSAFE
*/
static
int
int seqcount;
int ioseqcount;
int blksize;
+ int got_mplock = curthread->td_mpcount;
if (ap->a_vp->v_type != VREG)
return (EINVAL);
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;
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
brelse(bp);
break;
}
+skip:
/* bp->b_flags |= B_CLUSTEROK; temporarily disabled */
n = blksize - offset;
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);
}