FreeBSD/sys/fs/tmpfs/tmpfs_subr.c
/*
 * Resizes the aobj associated with the regular file pointed to by 'vp' to the
 * size 'newsize'.  'vp' must point to a vnode that represents a regular file.
 * 'newsize' must be positive.
 *
 * Returns zero on success or an appropriate error code on failure.
 */
Resizes the aobj associated with the regular file pointed to by 'vp' to the
size 'newsize'.  'vp' must point to a vnode that represents a regular file.
'newsize' must be positive.

Returns zero on success or an appropriate error code on failure.
Resizes the aobj associated with the regular file pointed to by ' vp ' to the size ' newsize ' . ' vp ' must point to a vnode that represents a regular file . ' newsize ' must be positive . Returns zero on success or an appropriate error code on failure .
int
tmpfs_reg_resize(struct vnode *vp, off_t newsize, boolean_t ignerr)
{
	struct tmpfs_mount *tmp;
	struct tmpfs_node *node;
	vm_object_t uobj;
	vm_page_t m;
	vm_pindex_t idx, newpages, oldpages;
	off_t oldsize;
	int base, rv;
	MPASS(vp->v_type == VREG);
	MPASS(newsize >= 0);
	node = VP_TO_TMPFS_NODE(vp);
	uobj = node->tn_reg.tn_aobj;
	tmp = VFS_TO_TMPFS(vp->v_mount);
	oldsize = node->tn_size;
	oldpages = OFF_TO_IDX(oldsize + PAGE_MASK);
	MPASS(oldpages == uobj->size);
	newpages = OFF_TO_IDX(newsize + PAGE_MASK);
	if (newpages > oldpages &&
	    tmpfs_pages_check_avail(tmp, newpages - oldpages) == 0)
		return (ENOSPC);
	VM_OBJECT_WLOCK(uobj);
	if (newsize < oldsize) {
		base = newsize & PAGE_MASK;
		if (base != 0) {
			idx = OFF_TO_IDX(newsize);
retry:
			m = vm_page_lookup(uobj, idx);
			if (m != NULL) {
				if (vm_page_sleep_if_busy(m, "tmfssz"))
					goto retry;
				MPASS(m->valid == VM_PAGE_BITS_ALL);
			} else if (vm_pager_has_page(uobj, idx, NULL, NULL)) {
				m = vm_page_alloc(uobj, idx, VM_ALLOC_NORMAL);
				if (m == NULL) {
					VM_OBJECT_WUNLOCK(uobj);
					VM_WAIT;
					VM_OBJECT_WLOCK(uobj);
					goto retry;
				} else if (m->valid != VM_PAGE_BITS_ALL)
					rv = vm_pager_get_pages(uobj, &m, 1,
					    NULL, NULL);
				else
					rv = VM_PAGER_OK;
				vm_page_lock(m);
				if (rv == VM_PAGER_OK) {
					vm_page_deactivate(m);
					vm_page_unlock(m);
					vm_page_xunbusy(m);
				} else {
					vm_page_free(m);
					vm_page_unlock(m);
					if (ignerr)
						m = NULL;
					else {
						VM_OBJECT_WUNLOCK(uobj);
						return (EIO);
					}
				}
			}
			if (m != NULL) {
				pmap_zero_page_area(m, base, PAGE_SIZE - base);
				vm_page_dirty(m);
				vm_pager_page_unswapped(m);
			}
		}
		if (newpages < oldpages) {
			swap_pager_freespace(uobj, newpages, oldpages -
			    newpages);
			vm_object_page_remove(uobj, newpages, 0, 0);
		}
	}
	uobj->size = newpages;
	VM_OBJECT_WUNLOCK(uobj);
	TMPFS_LOCK(tmp);
	tmp->tm_pages_used += (newpages - oldpages);
	TMPFS_UNLOCK(tmp);
	node->tn_size = newsize;
	return (0);
}
int tmpfs_reg_resize ( struct vnode * vp , off_t newsize , boolean_t ignerr ) { struct tmpfs_mount * tmp ; struct tmpfs_node * node ; vm_object_t uobj ; vm_page_t m ; vm_pindex_t idx , newpages , oldpages ; off_t oldsize ; int base , rv ; MPASS ( vp -> v_type == VREG ) ; MPASS ( newsize >= 0 ) ; node = VP_TO_TMPFS_NODE ( vp ) ; uobj = node -> tn_reg . tn_aobj ; tmp = VFS_TO_TMPFS ( vp -> v_mount ) ; oldsize = node -> tn_size ; oldpages = OFF_TO_IDX ( oldsize + PAGE_MASK ) ; MPASS ( oldpages == uobj -> size ) ; newpages = OFF_TO_IDX ( newsize + PAGE_MASK ) ; if ( newpages > oldpages && tmpfs_pages_check_avail ( tmp , newpages - oldpages ) == 0 ) return ( ENOSPC ) ; VM_OBJECT_WLOCK ( uobj ) ; if ( newsize < oldsize ) { base = newsize & PAGE_MASK ; if ( base != 0 ) { idx = OFF_TO_IDX ( newsize ) ; retry : m = vm_page_lookup ( uobj , idx ) ; if ( m != NULL ) { if ( vm_page_sleep_if_busy ( m , " " ) ) goto retry ; MPASS ( m -> valid == VM_PAGE_BITS_ALL ) ; } else if ( vm_pager_has_page ( uobj , idx , NULL , NULL ) ) { m = vm_page_alloc ( uobj , idx , VM_ALLOC_NORMAL ) ; if ( m == NULL ) { VM_OBJECT_WUNLOCK ( uobj ) ; VM_WAIT ; VM_OBJECT_WLOCK ( uobj ) ; goto retry ; } else if ( m -> valid != VM_PAGE_BITS_ALL ) rv = vm_pager_get_pages ( uobj , & m , 1 , NULL , NULL ) ; else rv = VM_PAGER_OK ; vm_page_lock ( m ) ; if ( rv == VM_PAGER_OK ) { vm_page_deactivate ( m ) ; vm_page_unlock ( m ) ; vm_page_xunbusy ( m ) ; } else { vm_page_free ( m ) ; vm_page_unlock ( m ) ; if ( ignerr ) m = NULL ; else { VM_OBJECT_WUNLOCK ( uobj ) ; return ( EIO ) ; } } } if ( m != NULL ) { pmap_zero_page_area ( m , base , PAGE_SIZE - base ) ; vm_page_dirty ( m ) ; vm_pager_page_unswapped ( m ) ; } } if ( newpages < oldpages ) { swap_pager_freespace ( uobj , newpages , oldpages - newpages ) ; vm_object_page_remove ( uobj , newpages , 0 , 0 ) ; } } uobj -> size = newpages ; VM_OBJECT_WUNLOCK ( uobj ) ; TMPFS_LOCK ( tmp ) ; tmp -> tm_pages_used += ( newpages - oldpages ) ; TMPFS_UNLOCK ( tmp ) ; node -> tn_size = newsize ; return ( 0 ) ; }
Resizes the aobj associated with the regular file pointed to by 'vp' to the
 size 'newsize'.
Resizes the aobj associated with the regular file pointed to by ' vp ' to the size ' newsize ' .
/*
	 * Convert the old and new sizes to the number of pages needed to
	 * store them.  It may happen that we do not need to do anything
	 * because the last allocated page can accommodate the change on
	 * its own.
	 */ /*
		 * Zero the truncated part of the last page.
		 */ /* A cached page was reactivated. */ /*
		 * Release any swap space and free any whole pages.
		 */