nlink_t		nlink, 
xfs_nlink_t	nlink, 
xfs_dir_ialloc(	xfs_trans_t	**tpp,		/* input: current transaction;					   output: may be a new transaction. */	xfs_inode_t	*dp,		/* directory within whose allocate					   the inode. */	mode_t		mode,	nlink_t		nlink,	xfs_dev_t	rdev,	cred_t		*credp,	prid_t		prid,		/* project id */	int		okalloc,	/* ok to allocate new space */	xfs_inode_t	**ipp,		/* pointer to inode; it will be					   locked. */	int		*committed){	xfs_trans_t	*tp;	xfs_trans_t	*ntp;	xfs_inode_t	*ip;	xfs_buf_t	*ialloc_context = NULL;	boolean_t	call_again = B_FALSE;	int		code;	uint		log_res;	uint		log_count;	void		*dqinfo;	uint		tflags;	tp = *tpp;	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);	/*	 * xfs_ialloc will return a pointer to an incore inode if	 * the Space Manager has an available inode on the free	 * list. Otherwise, it will do an allocation and replenish	 * the freelist.  Since we can only do one allocation per	 * transaction without deadlocks, we will need to commit the	 * current transaction and start a new one.  We will then	 * need to call xfs_ialloc again to get the inode.	 *	 * If xfs_ialloc did an allocation to replenish the freelist,	 * it returns the bp containing the head of the freelist as	 * ialloc_context. We will hold a lock on it across the	 * transaction commit so that no other process can steal	 * the inode(s) that we've just allocated.	 */	code = xfs_ialloc(tp, dp, mode, nlink, rdev, credp, prid, okalloc,			  &ialloc_context, &call_again, &ip);	/*	 * Return an error if we were unable to allocate a new inode.	 * This should only happen if we run out of space on disk or	 * encounter a disk error.	 */	if (code) {		*ipp = NULL;		return code;	}	if (!call_again && (ip == NULL)) {		*ipp = NULL;		return XFS_ERROR(ENOSPC);	}	/*	 * If call_again is set, then we were unable to get an	 * inode in one operation.  We need to commit the current	 * transaction and call xfs_ialloc() again.  It is guaranteed	 * to succeed the second time.	 */	if (call_again) {		/*		 * Normally, xfs_trans_commit releases all the locks.		 * We call bhold to hang on to the ialloc_context across		 * the commit.  Holding this buffer prevents any other		 * processes from doing any allocations in this		 * allocation group.		 */		xfs_trans_bhold(tp, ialloc_context);		/*		 * Save the log reservation so we can use		 * them in the next transaction.		 */		log_res = xfs_trans_get_log_res(tp);		log_count = xfs_trans_get_log_count(tp);		/*		 * We want the quota changes to be associated with the next		 * transaction, NOT this one. So, detach the dqinfo from this		 * and attach it to the next transaction.		 */		dqinfo = NULL;		tflags = 0;		if (tp->t_dqinfo) {			dqinfo = (void *)tp->t_dqinfo;			tp->t_dqinfo = NULL;			tflags = tp->t_flags & XFS_TRANS_DQ_DIRTY;			tp->t_flags &= ~(XFS_TRANS_DQ_DIRTY);		}		ntp = xfs_trans_dup(tp);		code = xfs_trans_commit(tp, 0, NULL);		tp = ntp;		if (committed != NULL) {			*committed = 1;		}		/*		 * If we get an error during the commit processing,		 * release the buffer that is still held and return		 * to the caller.		 */		if (code) {			xfs_buf_relse(ialloc_context);			if (dqinfo) {				tp->t_dqinfo = dqinfo;				XFS_TRANS_FREE_DQINFO(tp->t_mountp, tp);			}			*tpp = ntp;			*ipp = NULL;			return code;		}		code = xfs_trans_reserve(tp, 0, log_res, 0,					 XFS_TRANS_PERM_LOG_RES, log_count);		/*		 * Re-attach the quota info that we detached from prev trx.		 */		if (dqinfo) {			tp->t_dqinfo = dqinfo;			tp->t_flags |= tflags;		}		if (code) {			xfs_buf_relse(ialloc_context);			*tpp = ntp;			*ipp = NULL;			return code;		}		xfs_trans_bjoin(tp, ialloc_context);		/*		 * Call ialloc again. Since we've locked out all		 * other allocations in this allocation group,		 * this call should always succeed.		 */		code = xfs_ialloc(tp, dp, mode, nlink, rdev, credp, prid,				  okalloc, &ialloc_context, &call_again, &ip);		/*		 * If we get an error at this point, return to the caller		 * so that the current transaction can be aborted.		 */		if (code) {			*tpp = tp;			*ipp = NULL;			return code;		}		ASSERT ((!call_again) && (ip != NULL));	} else {		if (committed != NULL) {			*committed = 0;		}	}	*ipp = ip;	*tpp = tp;	return 0;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/31b084aef3f088962f56c100b31bb8479c5dd769/xfs_utils.c/clean/fs/xfs/xfs_utils.c