Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/tmpfs/tmpfs_vnops.c
Show First 20 Lines • Show All 311 Lines • ▼ Show 20 Lines | tmpfs_close(struct vop_close_args *v) | ||||
struct vnode *vp = v->a_vp; | struct vnode *vp = v->a_vp; | ||||
/* Update node times. */ | /* Update node times. */ | ||||
tmpfs_update(vp); | tmpfs_update(vp); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | |||||
* VOP_FPLOOKUP_VEXEC routines are subject to special circumstances, see | |||||
* the comment above cache_fplookup for details. | |||||
*/ | |||||
int | int | ||||
tmpfs_fplookup_vexec(struct vop_fplookup_vexec_args *v) | |||||
{ | |||||
struct vnode *vp; | |||||
struct tmpfs_node *node; | |||||
struct ucred *cred; | |||||
mode_t all_x, mode; | |||||
vp = v->a_vp; | |||||
node = VP_TO_TMPFS_NODE_SMR(vp); | |||||
if (__predict_false(node == NULL)) | |||||
return (EAGAIN); | |||||
all_x = S_IXUSR | S_IXGRP | S_IXOTH; | |||||
mode = atomic_load_int(&node->tn_mode); | |||||
if (__predict_true((mode & all_x) == all_x)) | |||||
return (0); | |||||
cred = v->a_cred; | |||||
return (vaccess_vexec_smr(mode, node->tn_uid, node->tn_gid, cred)); | |||||
} | |||||
int | |||||
tmpfs_access(struct vop_access_args *v) | tmpfs_access(struct vop_access_args *v) | ||||
{ | { | ||||
struct vnode *vp = v->a_vp; | struct vnode *vp = v->a_vp; | ||||
accmode_t accmode = v->a_accmode; | accmode_t accmode = v->a_accmode; | ||||
struct ucred *cred = v->a_cred; | struct ucred *cred = v->a_cred; | ||||
mode_t all_x = S_IXUSR | S_IXGRP | S_IXOTH; | mode_t all_x = S_IXUSR | S_IXGRP | S_IXOTH; | ||||
int error; | int error; | ||||
struct tmpfs_node *node; | struct tmpfs_node *node; | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | tmpfs_setattr(struct vop_setattr_args *v) | ||||
struct vattr *vap = v->a_vap; | struct vattr *vap = v->a_vap; | ||||
struct ucred *cred = v->a_cred; | struct ucred *cred = v->a_cred; | ||||
struct thread *td = curthread; | struct thread *td = curthread; | ||||
int error; | int error; | ||||
MPASS(VOP_ISLOCKED(vp)); | MPASS(VOP_ISLOCKED(vp)); | ||||
vn_seqc_write_begin(vp); | |||||
error = 0; | error = 0; | ||||
/* Abort if any unsettable attribute is given. */ | /* Abort if any unsettable attribute is given. */ | ||||
if (vap->va_type != VNON || | if (vap->va_type != VNON || | ||||
vap->va_nlink != VNOVAL || | vap->va_nlink != VNOVAL || | ||||
vap->va_fsid != VNOVAL || | vap->va_fsid != VNOVAL || | ||||
vap->va_fileid != VNOVAL || | vap->va_fileid != VNOVAL || | ||||
vap->va_blocksize != VNOVAL || | vap->va_blocksize != VNOVAL || | ||||
Show All 22 Lines | if (error == 0 && ((vap->va_atime.tv_sec != VNOVAL && | ||||
vap->va_birthtime.tv_nsec != VNOVAL))) | vap->va_birthtime.tv_nsec != VNOVAL))) | ||||
error = tmpfs_chtimes(vp, vap, cred, td); | error = tmpfs_chtimes(vp, vap, cred, td); | ||||
/* Update the node times. We give preference to the error codes | /* Update the node times. We give preference to the error codes | ||||
* generated by this function rather than the ones that may arise | * generated by this function rather than the ones that may arise | ||||
* from tmpfs_update. */ | * from tmpfs_update. */ | ||||
tmpfs_update(vp); | tmpfs_update(vp); | ||||
vn_seqc_write_end(vp); | |||||
MPASS(VOP_ISLOCKED(vp)); | MPASS(VOP_ISLOCKED(vp)); | ||||
return error; | return error; | ||||
} | } | ||||
static int | static int | ||||
tmpfs_read(struct vop_read_args *v) | tmpfs_read(struct vop_read_args *v) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 324 Lines • ▼ Show 20 Lines | tmpfs_rename(struct vop_rename_args *v) | ||||
char *newname; | char *newname; | ||||
struct tmpfs_dirent *de; | struct tmpfs_dirent *de; | ||||
struct tmpfs_mount *tmp; | struct tmpfs_mount *tmp; | ||||
struct tmpfs_node *fdnode; | struct tmpfs_node *fdnode; | ||||
struct tmpfs_node *fnode; | struct tmpfs_node *fnode; | ||||
struct tmpfs_node *tnode; | struct tmpfs_node *tnode; | ||||
struct tmpfs_node *tdnode; | struct tmpfs_node *tdnode; | ||||
int error; | int error; | ||||
bool want_seqc_end; | |||||
MPASS(VOP_ISLOCKED(tdvp)); | MPASS(VOP_ISLOCKED(tdvp)); | ||||
MPASS(IMPLIES(tvp != NULL, VOP_ISLOCKED(tvp))); | MPASS(IMPLIES(tvp != NULL, VOP_ISLOCKED(tvp))); | ||||
MPASS(fcnp->cn_flags & HASBUF); | MPASS(fcnp->cn_flags & HASBUF); | ||||
MPASS(tcnp->cn_flags & HASBUF); | MPASS(tcnp->cn_flags & HASBUF); | ||||
want_seqc_end = false; | |||||
/* | /* | ||||
* Disallow cross-device renames. | * Disallow cross-device renames. | ||||
* XXX Why isn't this done by the caller? | * XXX Why isn't this done by the caller? | ||||
*/ | */ | ||||
if (fvp->v_mount != tdvp->v_mount || | if (fvp->v_mount != tdvp->v_mount || | ||||
(tvp != NULL && fvp->v_mount != tvp->v_mount)) { | (tvp != NULL && fvp->v_mount != tvp->v_mount)) { | ||||
error = EXDEV; | error = EXDEV; | ||||
goto out; | goto out; | ||||
Show All 24 Lines | if (vn_lock(fdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) { | ||||
"tmpfs_rename: tvp not locked"); | "tmpfs_rename: tvp not locked"); | ||||
if (fvp == tvp) { | if (fvp == tvp) { | ||||
error = 0; | error = 0; | ||||
goto out_locked; | goto out_locked; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (tvp != NULL) | |||||
vn_seqc_write_begin(tvp); | |||||
vn_seqc_write_begin(tdvp); | |||||
vn_seqc_write_begin(fvp); | |||||
vn_seqc_write_begin(fdvp); | |||||
want_seqc_end = true; | |||||
tmp = VFS_TO_TMPFS(tdvp->v_mount); | tmp = VFS_TO_TMPFS(tdvp->v_mount); | ||||
tdnode = VP_TO_TMPFS_DIR(tdvp); | tdnode = VP_TO_TMPFS_DIR(tdvp); | ||||
tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp); | tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp); | ||||
fdnode = VP_TO_TMPFS_DIR(fdvp); | fdnode = VP_TO_TMPFS_DIR(fdvp); | ||||
fnode = VP_TO_TMPFS_NODE(fvp); | fnode = VP_TO_TMPFS_NODE(fvp); | ||||
de = tmpfs_dir_lookup(fdnode, fnode, fcnp); | de = tmpfs_dir_lookup(fdnode, fnode, fcnp); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 197 Lines • ▼ Show 20 Lines | tmpfs_rename(struct vop_rename_args *v) | ||||
error = 0; | error = 0; | ||||
out_locked: | out_locked: | ||||
if (fdvp != tdvp && fdvp != tvp) | if (fdvp != tdvp && fdvp != tvp) | ||||
VOP_UNLOCK(fdvp); | VOP_UNLOCK(fdvp); | ||||
out: | out: | ||||
if (want_seqc_end) { | |||||
if (tvp != NULL) | |||||
vn_seqc_write_end(tvp); | |||||
vn_seqc_write_end(tdvp); | |||||
vn_seqc_write_end(fvp); | |||||
vn_seqc_write_end(fdvp); | |||||
} | |||||
/* | /* | ||||
* Release target nodes. | * Release target nodes. | ||||
* XXX: I don't understand when tdvp can be the same as tvp, but | * XXX: I don't understand when tdvp can be the same as tvp, but | ||||
* other code takes care of this... | * other code takes care of this... | ||||
*/ | */ | ||||
if (tdvp == tvp) | if (tdvp == tvp) | ||||
vrele(tdvp); | vrele(tdvp); | ||||
else | else | ||||
▲ Show 20 Lines • Show All 540 Lines • ▼ Show 20 Lines | |||||
struct vop_vector tmpfs_vnodeop_entries = { | struct vop_vector tmpfs_vnodeop_entries = { | ||||
.vop_default = &default_vnodeops, | .vop_default = &default_vnodeops, | ||||
.vop_lookup = vfs_cache_lookup, | .vop_lookup = vfs_cache_lookup, | ||||
.vop_cachedlookup = tmpfs_cached_lookup, | .vop_cachedlookup = tmpfs_cached_lookup, | ||||
.vop_create = tmpfs_create, | .vop_create = tmpfs_create, | ||||
.vop_mknod = tmpfs_mknod, | .vop_mknod = tmpfs_mknod, | ||||
.vop_open = tmpfs_open, | .vop_open = tmpfs_open, | ||||
.vop_close = tmpfs_close, | .vop_close = tmpfs_close, | ||||
.vop_fplookup_vexec = tmpfs_fplookup_vexec, | |||||
.vop_access = tmpfs_access, | .vop_access = tmpfs_access, | ||||
.vop_getattr = tmpfs_getattr, | .vop_getattr = tmpfs_getattr, | ||||
.vop_setattr = tmpfs_setattr, | .vop_setattr = tmpfs_setattr, | ||||
.vop_read = tmpfs_read, | .vop_read = tmpfs_read, | ||||
.vop_write = tmpfs_write, | .vop_write = tmpfs_write, | ||||
.vop_fsync = tmpfs_fsync, | .vop_fsync = tmpfs_fsync, | ||||
.vop_remove = tmpfs_remove, | .vop_remove = tmpfs_remove, | ||||
.vop_link = tmpfs_link, | .vop_link = tmpfs_link, | ||||
Show All 29 Lines |