Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
Show First 20 Lines • Show All 512 Lines • ▼ Show 20 Lines | |||||
* ZFS to populate a range of page cache pages with data. | * ZFS to populate a range of page cache pages with data. | ||||
* | * | ||||
* NOTE: this function could be optimized to pre-allocate | * NOTE: this function could be optimized to pre-allocate | ||||
* all pages in advance, drain exclusive busy on all of them, | * all pages in advance, drain exclusive busy on all of them, | ||||
* map them into contiguous KVA region and populate them | * map them into contiguous KVA region and populate them | ||||
* in one single dmu_read() call. | * in one single dmu_read() call. | ||||
*/ | */ | ||||
int | int | ||||
mappedread_sf(znode_t *zp, int nbytes, uio_t *uio) | mappedread_sf(znode_t *zp, int nbytes, zfs_uio_t *uio) | ||||
{ | { | ||||
vnode_t *vp = ZTOV(zp); | vnode_t *vp = ZTOV(zp); | ||||
objset_t *os = zp->z_zfsvfs->z_os; | objset_t *os = zp->z_zfsvfs->z_os; | ||||
struct sf_buf *sf; | struct sf_buf *sf; | ||||
vm_object_t obj; | vm_object_t obj; | ||||
vm_page_t pp; | vm_page_t pp; | ||||
int64_t start; | int64_t start; | ||||
caddr_t va; | caddr_t va; | ||||
int len = nbytes; | int len = nbytes; | ||||
int error = 0; | int error = 0; | ||||
ASSERT(uio->uio_segflg == UIO_NOCOPY); | ASSERT(zfs_uio_segflg(uio) == UIO_NOCOPY); | ||||
ASSERT(vp->v_mount != NULL); | ASSERT(vp->v_mount != NULL); | ||||
obj = vp->v_object; | obj = vp->v_object; | ||||
ASSERT(obj != NULL); | ASSERT(obj != NULL); | ||||
ASSERT((uio->uio_loffset & PAGEOFFSET) == 0); | ASSERT((zfs_uio_offset(uio) & PAGEOFFSET) == 0); | ||||
zfs_vmobject_wlock_12(obj); | zfs_vmobject_wlock_12(obj); | ||||
for (start = uio->uio_loffset; len > 0; start += PAGESIZE) { | for (start = zfs_uio_offset(uio); len > 0; start += PAGESIZE) { | ||||
int bytes = MIN(PAGESIZE, len); | int bytes = MIN(PAGESIZE, len); | ||||
pp = vm_page_grab_unlocked(obj, OFF_TO_IDX(start), | pp = vm_page_grab_unlocked(obj, OFF_TO_IDX(start), | ||||
VM_ALLOC_SBUSY | VM_ALLOC_NORMAL | VM_ALLOC_IGN_SBUSY); | VM_ALLOC_SBUSY | VM_ALLOC_NORMAL | VM_ALLOC_IGN_SBUSY); | ||||
if (vm_page_none_valid(pp)) { | if (vm_page_none_valid(pp)) { | ||||
zfs_vmobject_wunlock_12(obj); | zfs_vmobject_wunlock_12(obj); | ||||
va = zfs_map_page(pp, &sf); | va = zfs_map_page(pp, &sf); | ||||
error = dmu_read(os, zp->z_id, start, bytes, va, | error = dmu_read(os, zp->z_id, start, bytes, va, | ||||
Show All 30 Lines | #else | ||||
vm_page_unlock(pp); | vm_page_unlock(pp); | ||||
#endif | #endif | ||||
} else { | } else { | ||||
ASSERT3U(pp->valid, ==, VM_PAGE_BITS_ALL); | ASSERT3U(pp->valid, ==, VM_PAGE_BITS_ALL); | ||||
vm_page_do_sunbusy(pp); | vm_page_do_sunbusy(pp); | ||||
} | } | ||||
if (error) | if (error) | ||||
break; | break; | ||||
uio->uio_resid -= bytes; | zfs_uio_advance(uio, bytes); | ||||
uio->uio_offset += bytes; | |||||
len -= bytes; | len -= bytes; | ||||
} | } | ||||
zfs_vmobject_wunlock_12(obj); | zfs_vmobject_wunlock_12(obj); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* When a file is memory mapped, we must keep the IO data synchronized | * When a file is memory mapped, we must keep the IO data synchronized | ||||
* between the DMU cache and the memory mapped pages. What this means: | * between the DMU cache and the memory mapped pages. What this means: | ||||
* | * | ||||
* On Read: We "read" preferentially from memory mapped pages, | * On Read: We "read" preferentially from memory mapped pages, | ||||
* else we default from the dmu buffer. | * else we default from the dmu buffer. | ||||
* | * | ||||
* NOTE: We will always "break up" the IO into PAGESIZE uiomoves when | * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when | ||||
* the file is memory mapped. | * the file is memory mapped. | ||||
*/ | */ | ||||
int | int | ||||
mappedread(znode_t *zp, int nbytes, uio_t *uio) | mappedread(znode_t *zp, int nbytes, zfs_uio_t *uio) | ||||
{ | { | ||||
vnode_t *vp = ZTOV(zp); | vnode_t *vp = ZTOV(zp); | ||||
vm_object_t obj; | vm_object_t obj; | ||||
int64_t start; | int64_t start; | ||||
int len = nbytes; | int len = nbytes; | ||||
int off; | int off; | ||||
int error = 0; | int error = 0; | ||||
ASSERT(vp->v_mount != NULL); | ASSERT(vp->v_mount != NULL); | ||||
obj = vp->v_object; | obj = vp->v_object; | ||||
ASSERT(obj != NULL); | ASSERT(obj != NULL); | ||||
start = uio->uio_loffset; | start = zfs_uio_offset(uio); | ||||
off = start & PAGEOFFSET; | off = start & PAGEOFFSET; | ||||
zfs_vmobject_wlock_12(obj); | zfs_vmobject_wlock_12(obj); | ||||
for (start &= PAGEMASK; len > 0; start += PAGESIZE) { | for (start &= PAGEMASK; len > 0; start += PAGESIZE) { | ||||
vm_page_t pp; | vm_page_t pp; | ||||
uint64_t bytes = MIN(PAGESIZE - off, len); | uint64_t bytes = MIN(PAGESIZE - off, len); | ||||
if ((pp = page_hold(vp, start))) { | if ((pp = page_hold(vp, start))) { | ||||
struct sf_buf *sf; | struct sf_buf *sf; | ||||
caddr_t va; | caddr_t va; | ||||
zfs_vmobject_wunlock_12(obj); | zfs_vmobject_wunlock_12(obj); | ||||
va = zfs_map_page(pp, &sf); | va = zfs_map_page(pp, &sf); | ||||
error = vn_io_fault_uiomove(va + off, bytes, uio); | error = vn_io_fault_uiomove(va + off, bytes, | ||||
GET_UIO_STRUCT(uio)); | |||||
zfs_unmap_page(sf); | zfs_unmap_page(sf); | ||||
zfs_vmobject_wlock_12(obj); | zfs_vmobject_wlock_12(obj); | ||||
page_unhold(pp); | page_unhold(pp); | ||||
} else { | } else { | ||||
zfs_vmobject_wunlock_12(obj); | zfs_vmobject_wunlock_12(obj); | ||||
error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl), | error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl), | ||||
uio, bytes); | uio, bytes); | ||||
zfs_vmobject_wlock_12(obj); | zfs_vmobject_wlock_12(obj); | ||||
▲ Show 20 Lines • Show All 1,003 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* Note that the low 4 bits of the cookie returned by zap is always zero. | * Note that the low 4 bits of the cookie returned by zap is always zero. | ||||
* This allows us to use the low range for "special" directory entries: | * This allows us to use the low range for "special" directory entries: | ||||
* We use 0 for '.', and 1 for '..'. If this is the root of the filesystem, | * We use 0 for '.', and 1 for '..'. If this is the root of the filesystem, | ||||
* we use the offset 2 for the '.zfs' directory. | * we use the offset 2 for the '.zfs' directory. | ||||
*/ | */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static int | static int | ||||
zfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, | zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp, | ||||
int *ncookies, ulong_t **cookies) | int *ncookies, ulong_t **cookies) | ||||
{ | { | ||||
znode_t *zp = VTOZ(vp); | znode_t *zp = VTOZ(vp); | ||||
iovec_t *iovp; | iovec_t *iovp; | ||||
edirent_t *eodp; | edirent_t *eodp; | ||||
dirent64_t *odp; | dirent64_t *odp; | ||||
zfsvfs_t *zfsvfs = zp->z_zfsvfs; | zfsvfs_t *zfsvfs = zp->z_zfsvfs; | ||||
objset_t *os; | objset_t *os; | ||||
Show All 28 Lines | zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp, | ||||
* use a local one. | * use a local one. | ||||
*/ | */ | ||||
if (eofp == NULL) | if (eofp == NULL) | ||||
eofp = &local_eof; | eofp = &local_eof; | ||||
/* | /* | ||||
* Check for valid iov_len. | * Check for valid iov_len. | ||||
*/ | */ | ||||
if (uio->uio_iov->iov_len <= 0) { | if (GET_UIO_STRUCT(uio)->uio_iov->iov_len <= 0) { | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
return (SET_ERROR(EINVAL)); | return (SET_ERROR(EINVAL)); | ||||
} | } | ||||
/* | /* | ||||
* Quit if directory has been removed (posix) | * Quit if directory has been removed (posix) | ||||
*/ | */ | ||||
if ((*eofp = zp->z_unlinked) != 0) { | if ((*eofp = zp->z_unlinked) != 0) { | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
return (0); | return (0); | ||||
} | } | ||||
error = 0; | error = 0; | ||||
os = zfsvfs->z_os; | os = zfsvfs->z_os; | ||||
offset = uio->uio_loffset; | offset = zfs_uio_offset(uio); | ||||
prefetch = zp->z_zn_prefetch; | prefetch = zp->z_zn_prefetch; | ||||
/* | /* | ||||
* Initialize the iterator cursor. | * Initialize the iterator cursor. | ||||
*/ | */ | ||||
if (offset <= 3) { | if (offset <= 3) { | ||||
/* | /* | ||||
* Start iteration from the beginning of the directory. | * Start iteration from the beginning of the directory. | ||||
*/ | */ | ||||
zap_cursor_init(&zc, os, zp->z_id); | zap_cursor_init(&zc, os, zp->z_id); | ||||
} else { | } else { | ||||
/* | /* | ||||
* The offset is a serialized cursor. | * The offset is a serialized cursor. | ||||
*/ | */ | ||||
zap_cursor_init_serialized(&zc, os, zp->z_id, offset); | zap_cursor_init_serialized(&zc, os, zp->z_id, offset); | ||||
} | } | ||||
/* | /* | ||||
* Get space to change directory entries into fs independent format. | * Get space to change directory entries into fs independent format. | ||||
*/ | */ | ||||
iovp = uio->uio_iov; | iovp = GET_UIO_STRUCT(uio)->uio_iov; | ||||
bytes_wanted = iovp->iov_len; | bytes_wanted = iovp->iov_len; | ||||
if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) { | if (zfs_uio_segflg(uio) != UIO_SYSSPACE || zfs_uio_iovcnt(uio) != 1) { | ||||
bufsize = bytes_wanted; | bufsize = bytes_wanted; | ||||
outbuf = kmem_alloc(bufsize, KM_SLEEP); | outbuf = kmem_alloc(bufsize, KM_SLEEP); | ||||
odp = (struct dirent64 *)outbuf; | odp = (struct dirent64 *)outbuf; | ||||
} else { | } else { | ||||
bufsize = bytes_wanted; | bufsize = bytes_wanted; | ||||
outbuf = NULL; | outbuf = NULL; | ||||
odp = (struct dirent64 *)iovp->iov_base; | odp = (struct dirent64 *)iovp->iov_base; | ||||
} | } | ||||
eodp = (struct edirent *)odp; | eodp = (struct edirent *)odp; | ||||
if (ncookies != NULL) { | if (ncookies != NULL) { | ||||
/* | /* | ||||
* Minimum entry size is dirent size and 1 byte for a file name. | * Minimum entry size is dirent size and 1 byte for a file name. | ||||
*/ | */ | ||||
ncooks = uio->uio_resid / (sizeof (struct dirent) - | ncooks = zfs_uio_resid(uio) / (sizeof (struct dirent) - | ||||
sizeof (((struct dirent *)NULL)->d_name) + 1); | sizeof (((struct dirent *)NULL)->d_name) + 1); | ||||
cooks = malloc(ncooks * sizeof (ulong_t), M_TEMP, M_WAITOK); | cooks = malloc(ncooks * sizeof (ulong_t), M_TEMP, M_WAITOK); | ||||
*cookies = cooks; | *cookies = cooks; | ||||
*ncookies = ncooks; | *ncookies = ncooks; | ||||
} | } | ||||
/* | /* | ||||
* If this VFS supports the system attribute view interface; and | * If this VFS supports the system attribute view interface; and | ||||
* we're looking at an extended attribute directory; and we care | * we're looking at an extended attribute directory; and we care | ||||
▲ Show 20 Lines • Show All 163 Lines • ▼ Show 20 Lines | skip_entry: | ||||
} | } | ||||
} | } | ||||
zp->z_zn_prefetch = B_FALSE; /* a lookup will re-enable pre-fetching */ | zp->z_zn_prefetch = B_FALSE; /* a lookup will re-enable pre-fetching */ | ||||
/* Subtract unused cookies */ | /* Subtract unused cookies */ | ||||
if (ncookies != NULL) | if (ncookies != NULL) | ||||
*ncookies -= ncooks; | *ncookies -= ncooks; | ||||
if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_iovcnt == 1) { | if (zfs_uio_segflg(uio) == UIO_SYSSPACE && zfs_uio_iovcnt(uio) == 1) { | ||||
iovp->iov_base += outcount; | iovp->iov_base += outcount; | ||||
iovp->iov_len -= outcount; | iovp->iov_len -= outcount; | ||||
uio->uio_resid -= outcount; | zfs_uio_resid(uio) -= outcount; | ||||
} else if ((error = uiomove(outbuf, (long)outcount, UIO_READ, uio))) { | } else if ((error = | ||||
zfs_uiomove(outbuf, (long)outcount, UIO_READ, uio))) { | |||||
/* | /* | ||||
* Reset the pointer. | * Reset the pointer. | ||||
*/ | */ | ||||
offset = uio->uio_loffset; | offset = zfs_uio_offset(uio); | ||||
} | } | ||||
update: | update: | ||||
zap_cursor_fini(&zc); | zap_cursor_fini(&zc); | ||||
if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) | if (zfs_uio_segflg(uio) != UIO_SYSSPACE || zfs_uio_iovcnt(uio) != 1) | ||||
kmem_free(outbuf, bufsize); | kmem_free(outbuf, bufsize); | ||||
if (error == ENOENT) | if (error == ENOENT) | ||||
error = 0; | error = 0; | ||||
ZFS_ACCESSTIME_STAMP(zfsvfs, zp); | ZFS_ACCESSTIME_STAMP(zfsvfs, zp); | ||||
uio->uio_loffset = offset; | zfs_uio_setoffset(uio, offset); | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
if (error != 0 && cookies != NULL) { | if (error != 0 && cookies != NULL) { | ||||
free(*cookies, M_TEMP); | free(*cookies, M_TEMP); | ||||
*cookies = NULL; | *cookies = NULL; | ||||
*ncookies = 0; | *ncookies = 0; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,666 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* RETURN: 0 on success, error code on failure. | * RETURN: 0 on success, error code on failure. | ||||
* | * | ||||
* Timestamps: | * Timestamps: | ||||
* vp - atime updated | * vp - atime updated | ||||
*/ | */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static int | static int | ||||
zfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr, caller_context_t *ct) | zfs_readlink(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, caller_context_t *ct) | ||||
{ | { | ||||
znode_t *zp = VTOZ(vp); | znode_t *zp = VTOZ(vp); | ||||
zfsvfs_t *zfsvfs = zp->z_zfsvfs; | zfsvfs_t *zfsvfs = zp->z_zfsvfs; | ||||
int error; | int error; | ||||
ZFS_ENTER(zfsvfs); | ZFS_ENTER(zfsvfs); | ||||
ZFS_VERIFY_ZP(zp); | ZFS_VERIFY_ZP(zp); | ||||
▲ Show 20 Lines • Show All 766 Lines • ▼ Show 20 Lines | struct vop_read_args { | ||||
int a_ioflag; | int a_ioflag; | ||||
struct ucred *a_cred; | struct ucred *a_cred; | ||||
}; | }; | ||||
#endif | #endif | ||||
static int | static int | ||||
zfs_freebsd_read(struct vop_read_args *ap) | zfs_freebsd_read(struct vop_read_args *ap) | ||||
{ | { | ||||
zfs_uio_t uio; | |||||
return (zfs_read(VTOZ(ap->a_vp), ap->a_uio, ioflags(ap->a_ioflag), | zfs_uio_init(&uio, ap->a_uio); | ||||
return (zfs_read(VTOZ(ap->a_vp), &uio, ioflags(ap->a_ioflag), | |||||
ap->a_cred)); | ap->a_cred)); | ||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct vop_write_args { | struct vop_write_args { | ||||
struct vnode *a_vp; | struct vnode *a_vp; | ||||
struct uio *a_uio; | struct uio *a_uio; | ||||
int a_ioflag; | int a_ioflag; | ||||
struct ucred *a_cred; | struct ucred *a_cred; | ||||
}; | }; | ||||
#endif | #endif | ||||
static int | static int | ||||
zfs_freebsd_write(struct vop_write_args *ap) | zfs_freebsd_write(struct vop_write_args *ap) | ||||
{ | { | ||||
zfs_uio_t uio; | |||||
return (zfs_write(VTOZ(ap->a_vp), ap->a_uio, ioflags(ap->a_ioflag), | zfs_uio_init(&uio, ap->a_uio); | ||||
return (zfs_write(VTOZ(ap->a_vp), &uio, ioflags(ap->a_ioflag), | |||||
ap->a_cred)); | ap->a_cred)); | ||||
} | } | ||||
#if __FreeBSD_version >= 1300102 | #if __FreeBSD_version >= 1300102 | ||||
/* | /* | ||||
* VOP_FPLOOKUP_VEXEC routines are subject to special circumstances, see | * VOP_FPLOOKUP_VEXEC routines are subject to special circumstances, see | ||||
* the comment above cache_fplookup for details. | * the comment above cache_fplookup for details. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 255 Lines • ▼ Show 20 Lines | struct vop_readdir_args { | ||||
int *a_ncookies; | int *a_ncookies; | ||||
ulong_t **a_cookies; | ulong_t **a_cookies; | ||||
}; | }; | ||||
#endif | #endif | ||||
static int | static int | ||||
zfs_freebsd_readdir(struct vop_readdir_args *ap) | zfs_freebsd_readdir(struct vop_readdir_args *ap) | ||||
{ | { | ||||
zfs_uio_t uio; | |||||
return (zfs_readdir(ap->a_vp, ap->a_uio, ap->a_cred, ap->a_eofflag, | zfs_uio_init(&uio, ap->a_uio); | ||||
return (zfs_readdir(ap->a_vp, &uio, ap->a_cred, ap->a_eofflag, | |||||
ap->a_ncookies, ap->a_cookies)); | ap->a_ncookies, ap->a_cookies)); | ||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct vop_fsync_args { | struct vop_fsync_args { | ||||
struct vnode *a_vp; | struct vnode *a_vp; | ||||
int a_waitfor; | int a_waitfor; | ||||
struct thread *a_td; | struct thread *a_td; | ||||
▲ Show 20 Lines • Show All 286 Lines • ▼ Show 20 Lines | struct vop_readlink_args { | ||||
struct uio *a_uio; | struct uio *a_uio; | ||||
struct ucred *a_cred; | struct ucred *a_cred; | ||||
}; | }; | ||||
#endif | #endif | ||||
static int | static int | ||||
zfs_freebsd_readlink(struct vop_readlink_args *ap) | zfs_freebsd_readlink(struct vop_readlink_args *ap) | ||||
{ | { | ||||
zfs_uio_t uio; | |||||
znode_t *zp = VTOZ(ap->a_vp); | znode_t *zp = VTOZ(ap->a_vp); | ||||
struct uio *auio; | |||||
char *symlink, *base; | char *symlink, *base; | ||||
size_t symlink_len; | size_t symlink_len; | ||||
int error; | int error; | ||||
bool trycache; | bool trycache; | ||||
auio = ap->a_uio; | zfs_uio_init(&uio, ap->a_uio); | ||||
trycache = false; | trycache = false; | ||||
if (auio->uio_segflg == UIO_SYSSPACE && auio->uio_iovcnt == 1) { | if (zfs_uio_segflg(&uio) == UIO_SYSSPACE && | ||||
base = auio->uio_iov->iov_base; | zfs_uio_iovcnt(&uio) == 1) { | ||||
symlink_len = auio->uio_iov->iov_len; | base = zfs_uio_iovbase(&uio, 0); | ||||
symlink_len = zfs_uio_iovlen(&uio, 0); | |||||
trycache = true; | trycache = true; | ||||
} | } | ||||
error = zfs_readlink(ap->a_vp, auio, ap->a_cred, NULL); | error = zfs_readlink(ap->a_vp, &uio, ap->a_cred, NULL); | ||||
if (atomic_load_ptr(&zp->z_cached_symlink) != NULL || | if (atomic_load_ptr(&zp->z_cached_symlink) != NULL || | ||||
error != 0 || !trycache) { | error != 0 || !trycache) { | ||||
return (error); | return (error); | ||||
} | } | ||||
symlink_len -= auio->uio_resid; | symlink_len -= zfs_uio_resid(&uio); | ||||
symlink = cache_symlink_alloc(symlink_len + 1, M_WAITOK); | symlink = cache_symlink_alloc(symlink_len + 1, M_WAITOK); | ||||
if (symlink != NULL) { | if (symlink != NULL) { | ||||
memcpy(symlink, base, symlink_len); | memcpy(symlink, base, symlink_len); | ||||
symlink[symlink_len] = '\0'; | symlink[symlink_len] = '\0'; | ||||
if (!atomic_cmpset_rel_ptr((uintptr_t *)&zp->z_cached_symlink, | if (!atomic_cmpset_rel_ptr((uintptr_t *)&zp->z_cached_symlink, | ||||
(uintptr_t)NULL, (uintptr_t)symlink)) { | (uintptr_t)NULL, (uintptr_t)symlink)) { | ||||
cache_symlink_free(symlink, symlink_len + 1); | cache_symlink_free(symlink, symlink_len + 1); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 460 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
zfsvfs_t *zfsvfs = VTOZ(ap->a_vp)->z_zfsvfs; | zfsvfs_t *zfsvfs = VTOZ(ap->a_vp)->z_zfsvfs; | ||||
struct thread *td = ap->a_td; | struct thread *td = ap->a_td; | ||||
struct nameidata nd; | struct nameidata nd; | ||||
char attrprefix[16]; | char attrprefix[16]; | ||||
uint8_t dirbuf[sizeof (struct dirent)]; | uint8_t dirbuf[sizeof (struct dirent)]; | ||||
struct dirent *dp; | struct dirent *dp; | ||||
struct iovec aiov; | struct iovec aiov; | ||||
struct uio auio, *uio = ap->a_uio; | struct uio auio; | ||||
size_t *sizep = ap->a_size; | size_t *sizep = ap->a_size; | ||||
size_t plen; | size_t plen; | ||||
vnode_t *xvp = NULL, *vp; | vnode_t *xvp = NULL, *vp; | ||||
int done, error, eof, pos; | int done, error, eof, pos; | ||||
zfs_uio_t uio; | |||||
zfs_uio_init(&uio, ap->a_uio); | |||||
/* | /* | ||||
* If the xattr property is off, refuse the request. | * If the xattr property is off, refuse the request. | ||||
*/ | */ | ||||
if (!(zfsvfs->z_flags & ZSB_XATTR)) { | if (!(zfsvfs->z_flags & ZSB_XATTR)) { | ||||
return (SET_ERROR(EOPNOTSUPP)); | return (SET_ERROR(EOPNOTSUPP)); | ||||
} | } | ||||
error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, | error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | for (pos = 0; pos < done; ) { | ||||
if (plen == 0 && | if (plen == 0 && | ||||
strncmp(dp->d_name, "freebsd:", 8) == 0) | strncmp(dp->d_name, "freebsd:", 8) == 0) | ||||
continue; | continue; | ||||
else if (strncmp(dp->d_name, attrprefix, plen) != 0) | else if (strncmp(dp->d_name, attrprefix, plen) != 0) | ||||
continue; | continue; | ||||
nlen = dp->d_namlen - plen; | nlen = dp->d_namlen - plen; | ||||
if (sizep != NULL) | if (sizep != NULL) | ||||
*sizep += 1 + nlen; | *sizep += 1 + nlen; | ||||
else if (uio != NULL) { | else if (GET_UIO_STRUCT(&uio) != NULL) { | ||||
/* | /* | ||||
* Format of extattr name entry is one byte for | * Format of extattr name entry is one byte for | ||||
* length and the rest for name. | * length and the rest for name. | ||||
*/ | */ | ||||
error = uiomove(&nlen, 1, uio->uio_rw, uio); | error = zfs_uiomove(&nlen, 1, zfs_uio_rw(&uio), | ||||
&uio); | |||||
if (error == 0) { | if (error == 0) { | ||||
error = uiomove(dp->d_name + plen, nlen, | error = zfs_uiomove(dp->d_name + plen, | ||||
uio->uio_rw, uio); | nlen, zfs_uio_rw(&uio), &uio); | ||||
} | } | ||||
if (error != 0) | if (error != 0) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} while (!eof && error == 0); | } while (!eof && error == 0); | ||||
vput(vp); | vput(vp); | ||||
▲ Show 20 Lines • Show All 270 Lines • Show Last 20 Lines |