Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/tmpfs/tmpfs_vnops.c
Show First 20 Lines • Show All 1,437 Lines • ▼ Show 20 Lines | tmpfs_readlink(struct vop_readlink_args *v) | ||||
int error; | int error; | ||||
struct tmpfs_node *node; | struct tmpfs_node *node; | ||||
MPASS(uio->uio_offset == 0); | MPASS(uio->uio_offset == 0); | ||||
MPASS(vp->v_type == VLNK); | MPASS(vp->v_type == VLNK); | ||||
node = VP_TO_TMPFS_NODE(vp); | node = VP_TO_TMPFS_NODE(vp); | ||||
error = uiomove(node->tn_link, MIN(node->tn_size, uio->uio_resid), | error = uiomove(node->tn_link_target, MIN(node->tn_size, uio->uio_resid), | ||||
uio); | uio); | ||||
tmpfs_set_accessed(VFS_TO_TMPFS(vp->v_mount), node); | tmpfs_set_accessed(VFS_TO_TMPFS(vp->v_mount), node); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | |||||
* VOP_FPLOOKUP_SYMLINK routines are subject to special circumstances, see | |||||
* the comment above cache_fplookup for details. | |||||
* | |||||
* Check tmpfs_alloc_node for tmpfs-specific synchronisation notes. | |||||
*/ | |||||
static int | static int | ||||
tmpfs_fplookup_symlink(struct vop_fplookup_symlink_args *v) | |||||
{ | |||||
struct vnode *vp; | |||||
struct tmpfs_node *node; | |||||
char *symlink; | |||||
vp = v->a_vp; | |||||
kib: ... but then this load should be acquire and testing of tn_link_smr done only after load… | |||||
Done Inline Actionstn_link_smr only goes one way (false -> true), so possible pairs are: smr buffer + flag false ; fine transient failure non-smr buffer + flag true can't happen. Thus I don't think fences are needed here, but extra commentary probably would not hurt. I'm going to convert tn_link_smr accesses to use atomic_* though. mjg: tn_link_smr only goes one way (false -> true), so possible pairs are:
smr buffer + flag false… | |||||
node = VP_TO_TMPFS_NODE_SMR(vp); | |||||
if (__predict_false(node == NULL)) | |||||
return (EAGAIN); | |||||
if (!atomic_load_char(&node->tn_link_smr)) | |||||
return (EAGAIN); | |||||
symlink = atomic_load_ptr(&node->tn_link_target); | |||||
if (symlink == NULL) | |||||
return (EAGAIN); | |||||
return (cache_symlink_resolve(v->a_fpl, symlink, node->tn_size)); | |||||
} | |||||
static int | |||||
tmpfs_inactive(struct vop_inactive_args *v) | tmpfs_inactive(struct vop_inactive_args *v) | ||||
{ | { | ||||
struct vnode *vp; | struct vnode *vp; | ||||
struct tmpfs_node *node; | struct tmpfs_node *node; | ||||
vp = v->a_vp; | vp = v->a_vp; | ||||
node = VP_TO_TMPFS_NODE(vp); | node = VP_TO_TMPFS_NODE(vp); | ||||
if (node->tn_links == 0) | if (node->tn_links == 0) | ||||
▲ Show 20 Lines • Show All 314 Lines • ▼ Show 20 Lines | 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_fplookup_vexec = tmpfs_fplookup_vexec, | ||||
.vop_fplookup_symlink = tmpfs_fplookup_symlink, | |||||
.vop_access = tmpfs_access, | .vop_access = tmpfs_access, | ||||
.vop_stat = tmpfs_stat, | .vop_stat = tmpfs_stat, | ||||
.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_read_pgcache = tmpfs_read_pgcache, | .vop_read_pgcache = tmpfs_read_pgcache, | ||||
.vop_write = tmpfs_write, | .vop_write = tmpfs_write, | ||||
.vop_fsync = tmpfs_fsync, | .vop_fsync = tmpfs_fsync, | ||||
Show All 31 Lines |
... but then this load should be acquire and testing of tn_link_smr done only after load provided non-NULL value.