Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_cache.c
Show First 20 Lines • Show All 3,648 Lines • ▼ Show 20 Lines | |||||
vn_fullpath_hardlink(struct vnode *vp, struct vnode *dvp, | vn_fullpath_hardlink(struct vnode *vp, struct vnode *dvp, | ||||
const char *hrdl_name, size_t hrdl_name_length, | const char *hrdl_name, size_t hrdl_name_length, | ||||
char **retbuf, char **freebuf, size_t *buflen) | char **retbuf, char **freebuf, size_t *buflen) | ||||
{ | { | ||||
char *buf, *tmpbuf; | char *buf, *tmpbuf; | ||||
struct pwd *pwd; | struct pwd *pwd; | ||||
size_t addend; | size_t addend; | ||||
int error; | int error; | ||||
enum vtype type; | __enum_uint8(vtype) type; | ||||
if (*buflen < 2) | if (*buflen < 2) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (*buflen > MAXPATHLEN) | if (*buflen > MAXPATHLEN) | ||||
*buflen = MAXPATHLEN; | *buflen = MAXPATHLEN; | ||||
buf = malloc(*buflen, M_TEMP, M_WAITOK); | buf = malloc(*buflen, M_TEMP, M_WAITOK); | ||||
addend = 0; | addend = 0; | ||||
/* | /* | ||||
* Check for VBAD to work around the vp_crossmp bug in lookup(). | * Check for VBAD to work around the vp_crossmp bug in lookup(). | ||||
* | * | ||||
* For example consider tmpfs on /tmp and realpath /tmp. ni_vp will be | * For example consider tmpfs on /tmp and realpath /tmp. ni_vp will be | ||||
* set to mount point's root vnode while ni_dvp will be vp_crossmp. | * set to mount point's root vnode while ni_dvp will be vp_crossmp. | ||||
* If the type is VDIR (like in this very case) we can skip looking | * If the type is VDIR (like in this very case) we can skip looking | ||||
* at ni_dvp in the first place. However, since vnodes get passed here | * at ni_dvp in the first place. However, since vnodes get passed here | ||||
* unlocked the target may transition to doomed state (type == VBAD) | * unlocked the target may transition to doomed state (type == VBAD) | ||||
* before we get to evaluate the condition. If this happens, we will | * before we get to evaluate the condition. If this happens, we will | ||||
* populate part of the buffer and descend to vn_fullpath_dir with | * populate part of the buffer and descend to vn_fullpath_dir with | ||||
* vp == vp_crossmp. Prevent the problem by checking for VBAD. | * vp == vp_crossmp. Prevent the problem by checking for VBAD. | ||||
* | |||||
* This should be atomic_load(&vp->v_type) but it is illegal to take | |||||
* an address of a bit field, even if said field is sized to char. | |||||
* Work around the problem by reading the value into a full-sized enum | |||||
* and then re-reading it with atomic_load which will still prevent | |||||
* the compiler from re-reading down the road. | |||||
*/ | */ | ||||
type = vp->v_type; | type = atomic_load_8(&type); | ||||
mjg: i think it is time for atomic_load which figures out the size btw | |||||
Not Done Inline ActionsOr, for the sake of this commit, add atomic_load_enum_uint8 kib: Or, for the sake of this commit, add `atomic_load_enum_uint8` | |||||
type = atomic_load_int(&type); | |||||
if (type == VBAD) { | if (type == VBAD) { | ||||
error = ENOENT; | error = ENOENT; | ||||
goto out_bad; | goto out_bad; | ||||
} | } | ||||
if (type != VDIR) { | if (type != VDIR) { | ||||
addend = hrdl_name_length + 2; | addend = hrdl_name_length + 2; | ||||
if (*buflen < addend) { | if (*buflen < addend) { | ||||
error = ENOMEM; | error = ENOMEM; | ||||
▲ Show 20 Lines • Show All 2,587 Lines • Show Last 20 Lines |
i think it is time for atomic_load which figures out the size btw