Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/tmpfs/tmpfs_vnops.c
| Show First 20 Lines • Show All 2,086 Lines • ▼ Show 20 Lines | tmpfs_setextattr(struct vop_setextattr_args *ap) | ||||
| } | } | ||||
| LIST_INSERT_HEAD(&node->tn_extattrs, new_ea, ea_extattrs); | LIST_INSERT_HEAD(&node->tn_extattrs, new_ea, ea_extattrs); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static off_t | static off_t | ||||
| tmpfs_seek_data_locked(vm_object_t obj, off_t noff) | tmpfs_seek_data_locked(vm_object_t obj, off_t noff) | ||||
| { | { | ||||
| vm_page_t m; | vm_pindex_t p; | ||||
| vm_pindex_t p, p_swp; | |||||
| p = OFF_TO_IDX(noff); | p = swap_pager_seek_data(obj, OFF_TO_IDX(noff)); | ||||
| m = vm_page_find_least(obj, p); | return (p == OFF_TO_IDX(noff) ? noff : IDX_TO_OFF(p)); | ||||
| /* | |||||
| * Microoptimize the most common case for SEEK_DATA, where | |||||
| * there is no hole and the page is resident. | |||||
| */ | |||||
| if (m != NULL && m->pindex == p && vm_page_any_valid(m)) | |||||
| return (noff); | |||||
| p_swp = swap_pager_find_least(obj, p); | |||||
| if (p_swp == p) | |||||
| return (noff); | |||||
| /* | |||||
| * Find the first resident page after p, before p_swp. | |||||
| */ | |||||
| while (m != NULL && m->pindex < p_swp) { | |||||
| if (vm_page_any_valid(m)) | |||||
| return (IDX_TO_OFF(m->pindex)); | |||||
| m = TAILQ_NEXT(m, listq); | |||||
| } | } | ||||
| if (p_swp == OBJ_MAX_SIZE) | |||||
| p_swp = obj->size; | |||||
| return (IDX_TO_OFF(p_swp)); | |||||
| } | |||||
| static off_t | |||||
| tmpfs_seek_next(off_t noff) | |||||
| { | |||||
| return (noff + PAGE_SIZE - (noff & PAGE_MASK)); | |||||
| } | |||||
| static int | static int | ||||
| tmpfs_seek_clamp(struct tmpfs_node *tn, off_t *noff, bool seekdata) | tmpfs_seek_clamp(struct tmpfs_node *tn, off_t *noff, bool seekdata) | ||||
| { | { | ||||
| if (*noff < tn->tn_size) | if (*noff < tn->tn_size) | ||||
| return (0); | return (0); | ||||
| if (seekdata) | if (seekdata) | ||||
| return (ENXIO); | return (ENXIO); | ||||
| *noff = tn->tn_size; | *noff = tn->tn_size; | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static off_t | static off_t | ||||
| tmpfs_seek_hole_locked(vm_object_t obj, off_t noff) | tmpfs_seek_hole_locked(vm_object_t obj, off_t noff) | ||||
| { | { | ||||
| vm_page_t m; | |||||
| vm_pindex_t p, p_swp; | |||||
| for (;; noff = tmpfs_seek_next(noff)) { | return (IDX_TO_OFF(swap_pager_seek_hole(obj, OFF_TO_IDX(noff)))); | ||||
| /* | |||||
| * Walk over the largest sequential run of the valid pages. | |||||
| */ | |||||
| for (m = vm_page_lookup(obj, OFF_TO_IDX(noff)); | |||||
| m != NULL && vm_page_any_valid(m); | |||||
| m = vm_page_next(m), noff = tmpfs_seek_next(noff)) | |||||
| ; | |||||
| /* | |||||
| * Found a hole in the object's page queue. Check if | |||||
| * there is a hole in the swap at the same place. | |||||
| */ | |||||
| p = OFF_TO_IDX(noff); | |||||
| p_swp = swap_pager_find_least(obj, p); | |||||
| if (p_swp != p) { | |||||
| noff = IDX_TO_OFF(p); | |||||
| break; | |||||
| } | |||||
| } | |||||
| return (noff); | |||||
| } | } | ||||
| static int | static int | ||||
| tmpfs_seek_datahole(struct vnode *vp, off_t *off, bool seekdata) | tmpfs_seek_datahole(struct vnode *vp, off_t *off, bool seekdata) | ||||
| { | { | ||||
| struct tmpfs_node *tn; | struct tmpfs_node *tn; | ||||
| vm_object_t obj; | vm_object_t obj; | ||||
| off_t noff; | off_t noff; | ||||
| ▲ Show 20 Lines • Show All 108 Lines • Show Last 20 Lines | |||||