⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xfs_dquot_item.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like.	 Any license provided herein, whether implied or * otherwise, applies only to this software file.  Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA  94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */#include "xfs.h"#include "xfs_fs.h"#include "xfs_inum.h"#include "xfs_log.h"#include "xfs_trans.h"#include "xfs_sb.h"#include "xfs_ag.h"#include "xfs_dir.h"#include "xfs_dir2.h"#include "xfs_alloc.h"#include "xfs_dmapi.h"#include "xfs_quota.h"#include "xfs_mount.h"#include "xfs_alloc_btree.h"#include "xfs_bmap_btree.h"#include "xfs_ialloc_btree.h"#include "xfs_btree.h"#include "xfs_ialloc.h"#include "xfs_attr_sf.h"#include "xfs_dir_sf.h"#include "xfs_dir2_sf.h"#include "xfs_dinode.h"#include "xfs_inode.h"#include "xfs_bmap.h"#include "xfs_bit.h"#include "xfs_rtalloc.h"#include "xfs_error.h"#include "xfs_itable.h"#include "xfs_rw.h"#include "xfs_acl.h"#include "xfs_cap.h"#include "xfs_mac.h"#include "xfs_attr.h"#include "xfs_buf_item.h"#include "xfs_trans_priv.h"#include "xfs_qm.h"/* * returns the number of iovecs needed to log the given dquot item. *//* ARGSUSED */STATIC uintxfs_qm_dquot_logitem_size(	xfs_dq_logitem_t	*logitem){	/*	 * we need only two iovecs, one for the format, one for the real thing	 */	return (2);}/* * fills in the vector of log iovecs for the given dquot log item. */STATIC voidxfs_qm_dquot_logitem_format(	xfs_dq_logitem_t	*logitem,	xfs_log_iovec_t		*logvec){	ASSERT(logitem);	ASSERT(logitem->qli_dquot);	logvec->i_addr = (xfs_caddr_t)&logitem->qli_format;	logvec->i_len  = sizeof(xfs_dq_logformat_t);	logvec++;	logvec->i_addr = (xfs_caddr_t)&logitem->qli_dquot->q_core;	logvec->i_len  = sizeof(xfs_disk_dquot_t);	ASSERT(2 == logitem->qli_item.li_desc->lid_size);	logitem->qli_format.qlf_size = 2;}/* * Increment the pin count of the given dquot. * This value is protected by pinlock spinlock in the xQM structure. */STATIC voidxfs_qm_dquot_logitem_pin(	xfs_dq_logitem_t *logitem){	unsigned long	s;	xfs_dquot_t *dqp;	dqp = logitem->qli_dquot;	ASSERT(XFS_DQ_IS_LOCKED(dqp));	s = XFS_DQ_PINLOCK(dqp);	dqp->q_pincount++;	XFS_DQ_PINUNLOCK(dqp, s);}/* * Decrement the pin count of the given dquot, and wake up * anyone in xfs_dqwait_unpin() if the count goes to 0.	 The * dquot must have been previously pinned with a call to xfs_dqpin(). *//* ARGSUSED */STATIC voidxfs_qm_dquot_logitem_unpin(	xfs_dq_logitem_t *logitem,	int		  stale){	unsigned long	s;	xfs_dquot_t *dqp;	dqp = logitem->qli_dquot;	ASSERT(dqp->q_pincount > 0);	s = XFS_DQ_PINLOCK(dqp);	dqp->q_pincount--;	if (dqp->q_pincount == 0) {		sv_broadcast(&dqp->q_pinwait);	}	XFS_DQ_PINUNLOCK(dqp, s);}/* ARGSUSED */STATIC voidxfs_qm_dquot_logitem_unpin_remove(	xfs_dq_logitem_t *logitem,	xfs_trans_t	 *tp){	xfs_qm_dquot_logitem_unpin(logitem, 0);}/* * Given the logitem, this writes the corresponding dquot entry to disk * asynchronously. This is called with the dquot entry securely locked; * we simply get xfs_qm_dqflush() to do the work, and unlock the dquot * at the end. */STATIC voidxfs_qm_dquot_logitem_push(	xfs_dq_logitem_t	*logitem){	xfs_dquot_t	*dqp;	dqp = logitem->qli_dquot;	ASSERT(XFS_DQ_IS_LOCKED(dqp));	ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp));	/*	 * Since we were able to lock the dquot's flush lock and	 * we found it on the AIL, the dquot must be dirty.  This	 * is because the dquot is removed from the AIL while still	 * holding the flush lock in xfs_dqflush_done().  Thus, if	 * we found it in the AIL and were able to obtain the flush	 * lock without sleeping, then there must not have been	 * anyone in the process of flushing the dquot.	 */	xfs_qm_dqflush(dqp, XFS_B_DELWRI);	xfs_dqunlock(dqp);}/*ARGSUSED*/STATIC xfs_lsn_txfs_qm_dquot_logitem_committed(	xfs_dq_logitem_t	*l,	xfs_lsn_t		lsn){	/*	 * We always re-log the entire dquot when it becomes dirty,	 * so, the latest copy _is_ the only one that matters.	 */	return (lsn);}/* * This is called to wait for the given dquot to be unpinned. * Most of these pin/unpin routines are plagiarized from inode code. */voidxfs_qm_dqunpin_wait(	xfs_dquot_t	*dqp){	SPLDECL(s);	ASSERT(XFS_DQ_IS_LOCKED(dqp));	if (dqp->q_pincount == 0) {		return;	}	/*	 * Give the log a push so we don't wait here too long.	 */	xfs_log_force(dqp->q_mount, (xfs_lsn_t)0, XFS_LOG_FORCE);	s = XFS_DQ_PINLOCK(dqp);	if (dqp->q_pincount == 0) {		XFS_DQ_PINUNLOCK(dqp, s);		return;	}	sv_wait(&(dqp->q_pinwait), PINOD,		&(XFS_DQ_TO_QINF(dqp)->qi_pinlock), s);}/* * This is called when IOP_TRYLOCK returns XFS_ITEM_PUSHBUF to indicate that * the dquot is locked by us, but the flush lock isn't. So, here we are * going to see if the relevant dquot buffer is incore, waiting on DELWRI. * If so, we want to push it out to help us take this item off the AIL as soon * as possible. * * We must not be holding the AIL_LOCK at this point. Calling incore() to * search the buffercache can be a time consuming thing, and AIL_LOCK is a * spinlock. */STATIC voidxfs_qm_dquot_logitem_pushbuf(	xfs_dq_logitem_t    *qip){	xfs_dquot_t	*dqp;	xfs_mount_t	*mp;	xfs_buf_t	*bp;	uint		dopush;	dqp = qip->qli_dquot;	ASSERT(XFS_DQ_IS_LOCKED(dqp));	/*	 * The qli_pushbuf_flag keeps others from	 * trying to duplicate our effort.	 */	ASSERT(qip->qli_pushbuf_flag != 0);	ASSERT(qip->qli_push_owner == get_thread_id());	/*	 * If flushlock isn't locked anymore, chances are that the	 * inode flush completed and the inode was taken off the AIL.	 * So, just get out.	 */	if ((valusema(&(dqp->q_flock)) > 0)  ||	    ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) {		qip->qli_pushbuf_flag = 0;		xfs_dqunlock(dqp);		return;	}	mp = dqp->q_mount;	bp = xfs_incore(mp->m_ddev_targp, qip->qli_format.qlf_blkno,		    XFS_QI_DQCHUNKLEN(mp),		    XFS_INCORE_TRYLOCK);	if (bp != NULL) {		if (XFS_BUF_ISDELAYWRITE(bp)) {			dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) &&				  (valusema(&(dqp->q_flock)) <= 0));			qip->qli_pushbuf_flag = 0;			xfs_dqunlock(dqp);			if (XFS_BUF_ISPINNED(bp)) {				xfs_log_force(mp, (xfs_lsn_t)0,					      XFS_LOG_FORCE);			}			if (dopush) {#ifdef XFSRACEDEBUG				delay_for_intr();				delay(300);#endif				xfs_bawrite(mp, bp);			} else {				xfs_buf_relse(bp);			}		} else {			qip->qli_pushbuf_flag = 0;			xfs_dqunlock(dqp);			xfs_buf_relse(bp);		}		return;	}	qip->qli_pushbuf_flag = 0;	xfs_dqunlock(dqp);}/* * This is called to attempt to lock the dquot associated with this * dquot log item.  Don't sleep on the dquot lock or the flush lock. * If the flush lock is already held, indicating that the dquot has * been or is in the process of being flushed, then see if we can * find the dquot's buffer in the buffer cache without sleeping.  If * we can and it is marked delayed write, then we want to send it out. * We delay doing so until the push routine, though, to avoid sleeping * in any device strategy routines. */STATIC uintxfs_qm_dquot_logitem_trylock(	xfs_dq_logitem_t	*qip){	xfs_dquot_t		*dqp;	uint			retval;	dqp = qip->qli_dquot;	if (dqp->q_pincount > 0)		return (XFS_ITEM_PINNED);	if (! xfs_qm_dqlock_nowait(dqp))		return (XFS_ITEM_LOCKED);	retval = XFS_ITEM_SUCCESS;	if (! xfs_qm_dqflock_nowait(dqp)) {		/*		 * The dquot is already being flushed.	It may have been		 * flushed delayed write, however, and we don't want to		 * get stuck waiting for that to complete.  So, we want to check		 * to see if we can lock the dquot's buffer without sleeping.		 * If we can and it is marked for delayed write, then we		 * hold it and send it out from the push routine.  We don't		 * want to do that now since we might sleep in the device		 * strategy routine.  We also don't want to grab the buffer lock		 * here because we'd like not to call into the buffer cache		 * while holding the AIL_LOCK.		 * Make sure to only return PUSHBUF if we set pushbuf_flag		 * ourselves.  If someone else is doing it then we don't		 * want to go to the push routine and duplicate their efforts.		 */		if (qip->qli_pushbuf_flag == 0) {			qip->qli_pushbuf_flag = 1;			ASSERT(qip->qli_format.qlf_blkno == dqp->q_blkno);#ifdef DEBUG			qip->qli_push_owner = get_thread_id();#endif			/*			 * The dquot is left locked.			 */			retval = XFS_ITEM_PUSHBUF;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -