softdep_collect_pagecache(ip);
softdep_setup_freeblocks(ip, length)	struct inode *ip;	/* The inode whose length is to be reduced */	off_t length;		/* The new length for the file */{	struct freeblks *freeblks;	struct inodedep *inodedep;	struct allocdirect *adp;	struct vnode *vp;	struct buf *bp;	struct fs *fs;	int i, delay, error;	fs = ip->i_fs;	vp = ITOV(ip);	if (length != 0)		panic("softdep_setup_freeblocks: non-zero length");	MALLOC(freeblks, struct freeblks *, sizeof(struct freeblks),	    M_FREEBLKS, M_SOFTDEP_FLAGS);	bzero(freeblks, sizeof(struct freeblks));	freeblks->fb_list.wk_type = D_FREEBLKS;	freeblks->fb_uid = ip->i_ffs_uid;	freeblks->fb_previousinum = ip->i_number;	freeblks->fb_devvp = ip->i_devvp;	freeblks->fb_mnt = ITOV(ip)->v_mount;	freeblks->fb_oldsize = ip->i_ffs_size;	freeblks->fb_newsize = length;	freeblks->fb_chkcnt = ip->i_ffs_blocks;	for (i = 0; i < NDADDR; i++) {		freeblks->fb_dblks[i] = ip->i_ffs_db[i];		ip->i_ffs_db[i] = 0;	}	for (i = 0; i < NIADDR; i++) {		freeblks->fb_iblks[i] = ip->i_ffs_ib[i];		ip->i_ffs_ib[i] = 0;	}	ip->i_ffs_blocks = 0;	ip->i_ffs_size = 0;	/*	 * Push the zero'ed inode to to its disk buffer so that we are free	 * to delete its dependencies below. Once the dependencies are gone	 * the buffer can be safely released.	 */	if ((error = bread(ip->i_devvp,	    fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),	    (int)fs->fs_bsize, NOCRED, &bp)) != 0)		softdep_error("softdep_setup_freeblocks", error);	*((struct dinode *)bp->b_data + ino_to_fsbo(fs, ip->i_number)) =	    ip->i_din.ffs_din;	/*	 * Find and eliminate any inode dependencies.	 */	ACQUIRE_LOCK(&lk);	(void) inodedep_lookup(fs, ip->i_number, DEPALLOC, &inodedep);	if ((inodedep->id_state & IOSTARTED) != 0) {		FREE_LOCK(&lk);		panic("softdep_setup_freeblocks: inode busy");	}	/*	 * Add the freeblks structure to the list of operations that	 * must await the zero'ed inode being written to disk. If we	 * still have a bitmap dependency (delay == 0), then the inode	 * has never been written to disk, so we can process the	 * freeblks below once we have deleted the dependencies.	 */	delay = (inodedep->id_state & DEPCOMPLETE);	if (delay)		WORKLIST_INSERT(&inodedep->id_bufwait, &freeblks->fb_list);	/*	 * Because the file length has been truncated to zero, any	 * pending block allocation dependency structures associated	 * with this inode are obsolete and can simply be de-allocated.	 * We must first merge the two dependency lists to get rid of	 * any duplicate freefrag structures, then purge the merged list.	 * We must remove any pagecache markers from the pagecache	 * hashtable first because any I/Os in flight will want to see	 * dependencies attached to their pagecache markers.  We cannot	 * free the pagecache markers until after we've freed all the	 * dependencies that reference them later.	 * If we still have a bitmap dependency, then the inode has never	 * been written to disk, so we can free any fragments without delay.	 */	softdep_collect_pagecache(ip);	merge_inode_lists(inodedep);	while ((adp = TAILQ_FIRST(&inodedep->id_inoupdt)) != 0)		free_allocdirect(&inodedep->id_inoupdt, adp, delay);	FREE_LOCK(&lk);	bdwrite(bp);	/*	 * We must wait for any I/O in progress to finish so that	 * all potential buffers on the dirty list will be visible.	 * Once they are all there, walk the list and get rid of	 * any dependencies.	 */	ACQUIRE_LOCK(&lk);	drain_output(vp, 1);	while (getdirtybuf(&LIST_FIRST(&vp->v_dirtyblkhd), MNT_WAIT)) {		bp = LIST_FIRST(&vp->v_dirtyblkhd);		(void) inodedep_lookup(fs, ip->i_number, 0, &inodedep);		deallocate_dependencies(bp, inodedep);		bp->b_flags |= B_INVAL | B_NOCACHE;		FREE_LOCK(&lk);		brelse(bp);		ACQUIRE_LOCK(&lk);	}	softdep_free_pagecache(ip);	if (inodedep_lookup(fs, ip->i_number, 0, &inodedep) != 0)		(void) free_inodedep(inodedep);	FREE_LOCK(&lk);	/*	 * If the inode has never been written to disk (delay == 0),	 * then we can process the freeblks now that we have deleted	 * the dependencies.	 */	if (!delay)		handle_workitem_freeblocks(freeblks);}