MFC r198703,r199156,r199157:
r198703: - zfs_zaccess() can handle VAPPEND too, so map V_APPEND to VAPPEND and call zfs_access() instead of vaccess() in this case as well. - If VADMIN is specified with another V* flag (unlikely) call both zfs_access() and vaccess() after spliting V* flags. This fixes "dirtying snapshot!" panic. PR: kern/139806 Reported by: Carl Chave <carl@chave.us> In co-operation with: jh r199156: Avoid passing invalid mountpoint to getnewvnode(). Reported by: rwatson Tested by: rwatson r199157: Be careful which vattr fields are set during setattr replay. Without this fix strange things can appear after unclean shutdown like files with mode set to 07777. Reported by: des
This commit is contained in:
parent
0edddda13b
commit
b469a0b405
@ -57,6 +57,8 @@ typedef struct vop_vector vnodeops_t;
|
||||
|
||||
#define v_count v_usecount
|
||||
|
||||
#define V_APPEND VAPPEND
|
||||
|
||||
static __inline int
|
||||
vn_is_readonly(vnode_t *vp)
|
||||
{
|
||||
|
@ -60,10 +60,14 @@ zfs_init_vattr(vattr_t *vap, uint64_t mask, uint64_t mode,
|
||||
{
|
||||
VATTR_NULL(vap);
|
||||
vap->va_mask = (uint_t)mask;
|
||||
vap->va_type = IFTOVT(mode);
|
||||
vap->va_mode = mode & MODEMASK;
|
||||
vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid;
|
||||
vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid;
|
||||
if (mask & AT_TYPE)
|
||||
vap->va_type = IFTOVT(mode);
|
||||
if (mask & AT_MODE)
|
||||
vap->va_mode = mode & MODEMASK;
|
||||
if (mask & AT_UID)
|
||||
vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid;
|
||||
if (mask & AT_GID)
|
||||
vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid;
|
||||
vap->va_rdev = zfs_cmpldev(rdev);
|
||||
vap->va_nodeid = nodeid;
|
||||
}
|
||||
|
@ -3981,21 +3981,33 @@ zfs_freebsd_access(ap)
|
||||
struct thread *a_td;
|
||||
} */ *ap;
|
||||
{
|
||||
accmode_t accmode;
|
||||
int error = 0;
|
||||
|
||||
/*
|
||||
* ZFS itself only knowns about VREAD, VWRITE and VEXEC, the rest
|
||||
* we have to handle by calling vaccess().
|
||||
* ZFS itself only knowns about VREAD, VWRITE, VEXEC and VAPPEND,
|
||||
*/
|
||||
if ((ap->a_accmode & ~(VREAD|VWRITE|VEXEC)) != 0) {
|
||||
vnode_t *vp = ap->a_vp;
|
||||
znode_t *zp = VTOZ(vp);
|
||||
znode_phys_t *zphys = zp->z_phys;
|
||||
accmode = ap->a_accmode & (VREAD|VWRITE|VEXEC|VAPPEND);
|
||||
if (accmode != 0)
|
||||
error = zfs_access(ap->a_vp, accmode, 0, ap->a_cred, NULL);
|
||||
|
||||
return (vaccess(vp->v_type, zphys->zp_mode, zphys->zp_uid,
|
||||
zphys->zp_gid, ap->a_accmode, ap->a_cred, NULL));
|
||||
/*
|
||||
* VADMIN has to be handled by vaccess().
|
||||
*/
|
||||
if (error == 0) {
|
||||
accmode = ap->a_accmode & ~(VREAD|VWRITE|VEXEC|VAPPEND);
|
||||
if (accmode != 0) {
|
||||
vnode_t *vp = ap->a_vp;
|
||||
znode_t *zp = VTOZ(vp);
|
||||
znode_phys_t *zphys = zp->z_phys;
|
||||
|
||||
error = vaccess(vp->v_type, zphys->zp_mode,
|
||||
zphys->zp_uid, zphys->zp_gid, accmode, ap->a_cred,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (zfs_access(ap->a_vp, ap->a_accmode, 0, ap->a_cred, NULL));
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -143,16 +143,19 @@ zfs_znode_cache_constructor(void *buf, void *arg, int kmflags)
|
||||
|
||||
POINTER_INVALIDATE(&zp->z_zfsvfs);
|
||||
ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
|
||||
ASSERT(vfsp != NULL);
|
||||
|
||||
error = getnewvnode("zfs", vfsp, &zfs_vnodeops, &vp);
|
||||
if (error != 0 && (kmflags & KM_NOSLEEP))
|
||||
return (-1);
|
||||
ASSERT(error == 0);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
zp->z_vnode = vp;
|
||||
vp->v_data = (caddr_t)zp;
|
||||
VN_LOCK_AREC(vp);
|
||||
if (vfsp != NULL) {
|
||||
error = getnewvnode("zfs", vfsp, &zfs_vnodeops, &vp);
|
||||
if (error != 0 && (kmflags & KM_NOSLEEP))
|
||||
return (-1);
|
||||
ASSERT(error == 0);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
zp->z_vnode = vp;
|
||||
vp->v_data = (caddr_t)zp;
|
||||
VN_LOCK_AREC(vp);
|
||||
} else {
|
||||
zp->z_vnode = NULL;
|
||||
}
|
||||
|
||||
list_link_init(&zp->z_link_node);
|
||||
|
||||
@ -1435,7 +1438,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
|
||||
nvpair_t *elem;
|
||||
int error;
|
||||
znode_t *rootzp = NULL;
|
||||
vnode_t *vp;
|
||||
vnode_t vnode;
|
||||
vattr_t vattr;
|
||||
znode_t *zp;
|
||||
|
||||
@ -1504,13 +1507,13 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
|
||||
vattr.va_gid = crgetgid(cr);
|
||||
|
||||
rootzp = kmem_cache_alloc(znode_cache, KM_SLEEP);
|
||||
zfs_znode_cache_constructor(rootzp, &zfsvfs, 0);
|
||||
zfs_znode_cache_constructor(rootzp, NULL, 0);
|
||||
rootzp->z_unlinked = 0;
|
||||
rootzp->z_atime_dirty = 0;
|
||||
|
||||
vp = ZTOV(rootzp);
|
||||
vp->v_type = VDIR;
|
||||
VN_LOCK_ASHARE(vp);
|
||||
vnode.v_type = VDIR;
|
||||
vnode.v_data = rootzp;
|
||||
rootzp->z_vnode = &vnode;
|
||||
|
||||
bzero(&zfsvfs, sizeof (zfsvfs_t));
|
||||
|
||||
@ -1539,16 +1542,10 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
|
||||
ASSERT(error == 0);
|
||||
POINTER_INVALIDATE(&rootzp->z_zfsvfs);
|
||||
|
||||
VI_LOCK(vp);
|
||||
ZTOV(rootzp)->v_data = NULL;
|
||||
ZTOV(rootzp)->v_count = 0;
|
||||
ZTOV(rootzp)->v_holdcnt = 0;
|
||||
rootzp->z_vnode = NULL;
|
||||
VOP_UNLOCK(vp, 0);
|
||||
vdestroy(vp);
|
||||
dmu_buf_rele(rootzp->z_dbuf, NULL);
|
||||
rootzp->z_dbuf = NULL;
|
||||
mutex_destroy(&zfsvfs.z_znodes_lock);
|
||||
rootzp->z_vnode = NULL;
|
||||
kmem_cache_free(znode_cache, rootzp);
|
||||
}
|
||||
|
||||
|
@ -304,7 +304,6 @@ typedef struct xvattr {
|
||||
* VOP_ACCESS flags
|
||||
*/
|
||||
#define V_ACE_MASK 0x1 /* mask represents NFSv4 ACE permissions */
|
||||
#define V_APPEND 0x2 /* want to do append only check */
|
||||
|
||||
/*
|
||||
* Flags for vnode operations.
|
||||
|
Loading…
x
Reference in New Issue
Block a user