Changeset View
Changeset View
Standalone View
Standalone View
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
Show First 20 Lines • Show All 4,492 Lines • ▼ Show 20 Lines | zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind, | ||||
ZFS_ENTER(zfsvfs); | ZFS_ENTER(zfsvfs); | ||||
ZFS_VERIFY_ZP(zp); | ZFS_VERIFY_ZP(zp); | ||||
start = IDX_TO_OFF(ma[0]->pindex); | start = IDX_TO_OFF(ma[0]->pindex); | ||||
end = IDX_TO_OFF(ma[count - 1]->pindex + 1); | end = IDX_TO_OFF(ma[count - 1]->pindex + 1); | ||||
/* | /* | ||||
* Lock a range covering all required and optional pages. | * Try to lock a range covering all required and optional pages, to | ||||
* Note that we need to handle the case of the block size growing. | * handle the case of the block size growing. It is not safe to block | ||||
* on the range lock since the owner may be waiting for the fault page | |||||
* to be unbusied. | |||||
*/ | */ | ||||
for (;;) { | for (;;) { | ||||
blksz = zp->z_blksz; | blksz = zp->z_blksz; | ||||
lr = rangelock_enter(&zp->z_rangelock, rounddown(start, blksz), | lr = rangelock_tryenter(&zp->z_rangelock, | ||||
rounddown(start, blksz), | |||||
roundup(end, blksz) - rounddown(start, blksz), RL_READER); | roundup(end, blksz) - rounddown(start, blksz), RL_READER); | ||||
if (lr == NULL) { | |||||
if (rahead != NULL) { | |||||
*rahead = 0; | |||||
rahead = NULL; | |||||
} | |||||
if (rbehind != NULL) { | |||||
*rbehind = 0; | |||||
rbehind = NULL; | |||||
} | |||||
break; | |||||
} | |||||
if (blksz == zp->z_blksz) | if (blksz == zp->z_blksz) | ||||
break; | break; | ||||
rangelock_exit(lr); | rangelock_exit(lr); | ||||
} | } | ||||
object = ma[0]->object; | object = ma[0]->object; | ||||
zfs_vmobject_wlock(object); | zfs_vmobject_wlock(object); | ||||
obj_size = object->un_pager.vnp.vnp_size; | obj_size = object->un_pager.vnp.vnp_size; | ||||
zfs_vmobject_wunlock(object); | zfs_vmobject_wunlock(object); | ||||
if (IDX_TO_OFF(ma[count - 1]->pindex) >= obj_size) { | if (IDX_TO_OFF(ma[count - 1]->pindex) >= obj_size) { | ||||
if (lr != NULL) | |||||
rangelock_exit(lr); | rangelock_exit(lr); | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
return (zfs_vm_pagerret_bad); | return (zfs_vm_pagerret_bad); | ||||
} | } | ||||
pgsin_b = 0; | pgsin_b = 0; | ||||
if (rbehind != NULL) { | if (rbehind != NULL) { | ||||
pgsin_b = OFF_TO_IDX(start - rounddown(start, blksz)); | pgsin_b = OFF_TO_IDX(start - rounddown(start, blksz)); | ||||
pgsin_b = MIN(*rbehind, pgsin_b); | pgsin_b = MIN(*rbehind, pgsin_b); | ||||
Show All 11 Lines | zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind, | ||||
* NB: we need to pass the exact byte size of the data that we expect | * NB: we need to pass the exact byte size of the data that we expect | ||||
* to read after accounting for the file size. This is required because | * to read after accounting for the file size. This is required because | ||||
* ZFS will panic if we request DMU to read beyond the end of the last | * ZFS will panic if we request DMU to read beyond the end of the last | ||||
* allocated block. | * allocated block. | ||||
*/ | */ | ||||
error = dmu_read_pages(os, zp->z_id, ma, count, &pgsin_b, &pgsin_a, | error = dmu_read_pages(os, zp->z_id, ma, count, &pgsin_b, &pgsin_a, | ||||
MIN(end, obj_size) - (end - PAGE_SIZE)); | MIN(end, obj_size) - (end - PAGE_SIZE)); | ||||
if (lr != NULL) | |||||
rangelock_exit(lr); | rangelock_exit(lr); | ||||
ZFS_ACCESSTIME_STAMP(zfsvfs, zp); | ZFS_ACCESSTIME_STAMP(zfsvfs, zp); | ||||
ZFS_EXIT(zfsvfs); | ZFS_EXIT(zfsvfs); | ||||
if (error != 0) | if (error != 0) | ||||
return (zfs_vm_pagerret_error); | return (zfs_vm_pagerret_error); | ||||
VM_CNT_INC(v_vnodein); | VM_CNT_INC(v_vnodein); | ||||
VM_CNT_ADD(v_vnodepgsin, count + pgsin_b + pgsin_a); | VM_CNT_ADD(v_vnodepgsin, count + pgsin_b + pgsin_a); | ||||
▲ Show 20 Lines • Show All 1,505 Lines • Show Last 20 Lines |