--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c Wed Oct 24 16:50:08 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c Wed Oct 24 16:54:46 2007 -0700
@@ -83,8 +83,9 @@
* to freed memory. The example below illustrates the following Big Rules:
*
* (1) A check must be made in each zfs thread for a mounted file system.
- * This is done avoiding races using ZFS_ENTER(zfsvfs).
- * A ZFS_EXIT(zfsvfs) is needed before all returns.
+ * This is done avoiding races using ZFS_ENTER(zfsvfs) or
+ * ZFS_ENTER_VERIFY(zfsvfs, zp). A ZFS_EXIT(zfsvfs) is needed before
+ * all returns.
*
* (2) VN_RELE() should always be the last thing except for zil_commit()
* (if necessary) and ZFS_EXIT(). This is for 3 reasons:
@@ -239,6 +240,7 @@
offset_t off;
int error;
zfsvfs_t *zfsvfs;
+ znode_t *zp;
switch (com) {
case _FIOFFS:
@@ -257,8 +259,9 @@
if (ddi_copyin((void *)data, &off, sizeof (off), flag))
return (EFAULT);
- zfsvfs = VTOZ(vp)->z_zfsvfs;
- ZFS_ENTER(zfsvfs);
+ zp = VTOZ(vp);
+ zfsvfs = zp->z_zfsvfs;
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
/* offset parameter is in/out */
error = zfs_holey(vp, com, &off);
@@ -398,12 +401,13 @@
{
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
- objset_t *os = zfsvfs->z_os;
+ objset_t *os;
ssize_t n, nbytes;
int error;
rl_t *rl;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
+ os = zfsvfs->z_os;
/*
* Validate file offset
@@ -568,7 +572,7 @@
uint64_t end_size;
dmu_tx_t *tx;
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
- zilog_t *zilog = zfsvfs->z_log;
+ zilog_t *zilog;
offset_t woff;
ssize_t n, nbytes;
rl_t *rl;
@@ -585,7 +589,8 @@
if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
limit = MAXOFFSET_T;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
+ zilog = zfsvfs->z_log;
/*
* Pre-fault the pages to ensure slow (eg NFS) pages
@@ -906,7 +911,7 @@
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
int error;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
error = zfs_zaccess_rwx(zp, mode, cr);
ZFS_EXIT(zfsvfs);
return (error);
@@ -941,7 +946,7 @@
zfsvfs_t *zfsvfs = zdp->z_zfsvfs;
int error;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zdp);
*vpp = NULL;
@@ -1044,14 +1049,16 @@
{
znode_t *zp, *dzp = VTOZ(dvp);
zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
- zilog_t *zilog = zfsvfs->z_log;
- objset_t *os = zfsvfs->z_os;
+ zilog_t *zilog;
+ objset_t *os;
zfs_dirlock_t *dl;
dmu_tx_t *tx;
int error;
uint64_t zoid;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, dzp);
+ os = zfsvfs->z_os;
+ zilog = zfsvfs->z_log;
top:
*vpp = NULL;
@@ -1221,7 +1228,7 @@
znode_t *xzp = NULL;
vnode_t *vp;
zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
- zilog_t *zilog = zfsvfs->z_log;
+ zilog_t *zilog;
uint64_t acl_obj, xattr_obj;
zfs_dirlock_t *dl;
dmu_tx_t *tx;
@@ -1229,7 +1236,8 @@
boolean_t unlinked;
int error;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, dzp);
+ zilog = zfsvfs->z_log;
top:
/*
@@ -1386,7 +1394,7 @@
{
znode_t *zp, *dzp = VTOZ(dvp);
zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
- zilog_t *zilog = zfsvfs->z_log;
+ zilog_t *zilog;
zfs_dirlock_t *dl;
uint64_t zoid = 0;
dmu_tx_t *tx;
@@ -1394,7 +1402,8 @@
ASSERT(vap->va_type == VDIR);
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, dzp);
+ zilog = zfsvfs->z_log;
if (dzp->z_phys->zp_flags & ZFS_XATTR) {
ZFS_EXIT(zfsvfs);
@@ -1483,12 +1492,13 @@
znode_t *zp;
vnode_t *vp;
zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
- zilog_t *zilog = zfsvfs->z_log;
+ zilog_t *zilog;
zfs_dirlock_t *dl;
dmu_tx_t *tx;
int error;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, dzp);
+ zilog = zfsvfs->z_log;
top:
zp = NULL;
@@ -1613,7 +1623,7 @@
int error;
uint8_t prefetch;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
/*
* If we are not given an eof variable,
@@ -1812,7 +1822,7 @@
(void) tsd_set(zfs_fsyncer_key, (void *)zfs_fsync_sync_cnt);
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id);
ZFS_EXIT(zfsvfs);
return (0);
@@ -1837,11 +1847,12 @@
{
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
- znode_phys_t *pzp = zp->z_phys;
+ znode_phys_t *pzp;
int error;
uint64_t links;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
+ pzp = zp->z_phys;
/*
* Return all attributes. It's cheaper to provide the answer
@@ -1917,10 +1928,10 @@
zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
caller_context_t *ct)
{
- struct znode *zp = VTOZ(vp);
- znode_phys_t *pzp = zp->z_phys;
+ znode_t *zp = VTOZ(vp);
+ znode_phys_t *pzp;
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
- zilog_t *zilog = zfsvfs->z_log;
+ zilog_t *zilog;
dmu_tx_t *tx;
vattr_t oldva;
uint_t mask = vap->va_mask;
@@ -1943,7 +1954,9 @@
if (mask & AT_SIZE && vp->v_type != VREG && vp->v_type != VFIFO)
return (EINVAL);
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
+ pzp = zp->z_phys;
+ zilog = zfsvfs->z_log;
top:
attrzp = NULL;
@@ -2298,14 +2311,15 @@
znode_t *tdzp, *szp, *tzp;
znode_t *sdzp = VTOZ(sdvp);
zfsvfs_t *zfsvfs = sdzp->z_zfsvfs;
- zilog_t *zilog = zfsvfs->z_log;
+ zilog_t *zilog;
vnode_t *realvp;
zfs_dirlock_t *sdl, *tdl;
dmu_tx_t *tx;
zfs_zlock_t *zl;
int cmp, serr, terr, error;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, sdzp);
+ zilog = zfsvfs->z_log;
/*
* Make sure we have the real vp for the target directory.
@@ -2319,6 +2333,10 @@
}
tdzp = VTOZ(tdvp);
+ if (!tdzp->z_dbuf_held) {
+ ZFS_EXIT(zfsvfs);
+ return (EIO);
+ }
top:
szp = NULL;
tzp = NULL;
@@ -2529,14 +2547,15 @@
zfs_dirlock_t *dl;
dmu_tx_t *tx;
zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
- zilog_t *zilog = zfsvfs->z_log;
+ zilog_t *zilog;
uint64_t zoid;
int len = strlen(link);
int error;
ASSERT(vap->va_type == VLNK);
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, dzp);
+ zilog = zfsvfs->z_log;
top:
if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) {
ZFS_EXIT(zfsvfs);
@@ -2650,7 +2669,7 @@
size_t bufsz;
int error;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
bufsz = (size_t)zp->z_phys->zp_size;
if (bufsz + sizeof (znode_phys_t) <= zp->z_dbuf->db_size) {
@@ -2695,7 +2714,7 @@
znode_t *dzp = VTOZ(tdvp);
znode_t *tzp, *szp;
zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
- zilog_t *zilog = zfsvfs->z_log;
+ zilog_t *zilog;
zfs_dirlock_t *dl;
dmu_tx_t *tx;
vnode_t *realvp;
@@ -2703,7 +2722,8 @@
ASSERT(tdvp->v_type == VDIR);
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, dzp);
+ zilog = zfsvfs->z_log;
if (VOP_REALVP(svp, &realvp) == 0)
svp = realvp;
@@ -2714,6 +2734,10 @@
}
szp = VTOZ(svp);
+ if (!szp->z_dbuf_held) {
+ ZFS_EXIT(zfsvfs);
+ return (EIO);
+ }
top:
/*
* We do not support links between attributes and non-attributes
@@ -2947,7 +2971,7 @@
uint64_t filesz;
int error = 0;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
ASSERT(zp->z_dbuf_held && zp->z_phys);
@@ -3005,10 +3029,8 @@
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
int error;
- rw_enter(&zfsvfs->z_unmount_inactive_lock, RW_READER);
- if (zfsvfs->z_unmounted) {
- ASSERT(zp->z_dbuf_held == 0);
-
+ rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_READER);
+ if (zp->z_dbuf_held == 0) {
if (vn_has_cached_data(vp)) {
(void) pvn_vplist_dirty(vp, 0, zfs_null_putapage,
B_INVAL, cr);
@@ -3022,7 +3044,7 @@
} else {
mutex_exit(&zp->z_lock);
}
- rw_exit(&zfsvfs->z_unmount_inactive_lock);
+ rw_exit(&zfsvfs->z_teardown_inactive_lock);
VFS_RELE(zfsvfs->z_vfs);
return;
}
@@ -3053,7 +3075,7 @@
}
zfs_zinactive(zp);
- rw_exit(&zfsvfs->z_unmount_inactive_lock);
+ rw_exit(&zfsvfs->z_teardown_inactive_lock);
}
/*
@@ -3087,7 +3109,7 @@
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
int error;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
/*
* We are following the UFS semantics with respect to mapcnt
@@ -3239,7 +3261,7 @@
int need_unlock = 0, err = 0;
offset_t orig_off;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
if (protp)
*protp = PROT_ALL;
@@ -3371,7 +3393,7 @@
segvn_crargs_t vn_a;
int error;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
if (vp->v_flag & VNOMAP) {
ZFS_EXIT(zfsvfs);
@@ -3507,7 +3529,7 @@
uint64_t off, len;
int error;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
top:
if (cmd != F_FREESP) {
@@ -3542,12 +3564,13 @@
{
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
- uint32_t gen = (uint32_t)zp->z_phys->zp_gen;
+ uint32_t gen;
uint64_t object = zp->z_id;
zfid_short_t *zfid;
int size, i;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
+ gen = (uint32_t)zp->z_gen;
size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN;
if (fidp->fid_len < size) {
@@ -3607,7 +3630,7 @@
case _PC_XATTR_EXISTS:
zp = VTOZ(vp);
zfsvfs = zp->z_zfsvfs;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
*valp = 0;
error = zfs_dirent_lock(&dl, zp, "", &xzp,
ZXATTR | ZEXISTS | ZSHARED);
@@ -3647,7 +3670,7 @@
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
int error;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
error = zfs_getacl(zp, vsecp, cr);
ZFS_EXIT(zfsvfs);
@@ -3662,7 +3685,7 @@
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
int error;
- ZFS_ENTER(zfsvfs);
+ ZFS_ENTER_VERIFY_ZP(zfsvfs, zp);
error = zfs_setacl(zp, vsecp, cr);
ZFS_EXIT(zfsvfs);
return (error);