linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jan Kara <jack@suse.cz>
To: linux-kernel@vger.kernel.org
Cc: linux-ext4@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	Mingming Cao <cmm@us.ibm.com>, Jan Kara <jack@suse.cz>
Subject: [PATCH 06/11] quota: Add quota reservation claim and released operations
Date: Fri, 16 Jan 2009 19:08:14 +0100	[thread overview]
Message-ID: <1232129299-22018-7-git-send-email-jack@suse.cz> (raw)
In-Reply-To: <1232129299-22018-6-git-send-email-jack@suse.cz>

From: Mingming Cao <cmm@us.ibm.com>

Reserved quota will be claimed at the block allocation time. Over-booked
quota could be returned back with the release callback function.

Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/dquot.c               |  110 ++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/quota.h    |    6 +++
 include/linux/quotaops.h |   53 ++++++++++++++++++++++
 3 files changed, 165 insertions(+), 4 deletions(-)

diff --git a/fs/dquot.c b/fs/dquot.c
index 9b1c4d3..2916f91 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -904,6 +904,23 @@ static inline void dquot_resv_space(struct dquot *dquot, qsize_t number)
 	dquot->dq_dqb.dqb_rsvspace += number;
 }
 
+/*
+ * Claim reserved quota space
+ */
+static void dquot_claim_reserved_space(struct dquot *dquot,
+						qsize_t number)
+{
+	WARN_ON(dquot->dq_dqb.dqb_rsvspace < number);
+	dquot->dq_dqb.dqb_curspace += number;
+	dquot->dq_dqb.dqb_rsvspace -= number;
+}
+
+static inline
+void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
+{
+	dquot->dq_dqb.dqb_rsvspace -= number;
+}
+
 static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
 {
 	if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
@@ -1452,6 +1469,72 @@ warn_put_all:
 	return ret;
 }
 
+int dquot_claim_space(struct inode *inode, qsize_t number)
+{
+	int cnt;
+	int ret = QUOTA_OK;
+
+	if (IS_NOQUOTA(inode)) {
+		inode_add_bytes(inode, number);
+		goto out;
+	}
+
+	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	if (IS_NOQUOTA(inode))	{
+		up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+		inode_add_bytes(inode, number);
+		goto out;
+	}
+
+	spin_lock(&dq_data_lock);
+	/* Claim reserved quotas to allocated quotas */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+		if (inode->i_dquot[cnt] != NODQUOT)
+			dquot_claim_reserved_space(inode->i_dquot[cnt],
+							number);
+	}
+	/* Update inode bytes */
+	inode_add_bytes(inode, number);
+	spin_unlock(&dq_data_lock);
+	/* Dirtify all the dquots - this can block when journalling */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+		if (inode->i_dquot[cnt])
+			mark_dquot_dirty(inode->i_dquot[cnt]);
+	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
+	return ret;
+}
+EXPORT_SYMBOL(dquot_claim_space);
+
+/*
+ * Release reserved quota space
+ */
+void dquot_release_reserved_space(struct inode *inode, qsize_t number)
+{
+	int cnt;
+
+	if (IS_NOQUOTA(inode))
+		goto out;
+
+	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	if (IS_NOQUOTA(inode))
+		goto out_unlock;
+
+	spin_lock(&dq_data_lock);
+	/* Release reserved dquots */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+		if (inode->i_dquot[cnt] != NODQUOT)
+			dquot_free_reserved_space(inode->i_dquot[cnt], number);
+	}
+	spin_unlock(&dq_data_lock);
+
+out_unlock:
+	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
+	return;
+}
+EXPORT_SYMBOL(dquot_release_reserved_space);
+
 /*
  * This operation can block, but only after everything is updated
  */
@@ -1529,6 +1612,19 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
 }
 
 /*
+ * call back function, get reserved quota space from underlying fs
+ */
+qsize_t dquot_get_reserved_space(struct inode *inode)
+{
+	qsize_t reserved_space = 0;
+
+	if (sb_any_quota_active(inode->i_sb) &&
+	    inode->i_sb->dq_op->get_reserved_space)
+		reserved_space = inode->i_sb->dq_op->get_reserved_space(inode);
+	return reserved_space;
+}
+
+/*
  * Transfer the number of inode and blocks from one diskquota to an other.
  *
  * This operation can block, but only after everything is updated
@@ -1536,7 +1632,8 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
  */
 int dquot_transfer(struct inode *inode, struct iattr *iattr)
 {
-	qsize_t space;
+	qsize_t space, cur_space;
+	qsize_t rsv_space = 0;
 	struct dquot *transfer_from[MAXQUOTAS];
 	struct dquot *transfer_to[MAXQUOTAS];
 	int cnt, ret = QUOTA_OK;
@@ -1575,7 +1672,9 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
 		goto put_all;
 	}
 	spin_lock(&dq_data_lock);
-	space = inode_get_bytes(inode);
+	cur_space = inode_get_bytes(inode);
+	rsv_space = dquot_get_reserved_space(inode);
+	space = cur_space + rsv_space;
 	/* Build the transfer_from list and check the limits */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (transfer_to[cnt] == NODQUOT)
@@ -1604,11 +1703,14 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
 			warntype_from_space[cnt] =
 				info_bdq_free(transfer_from[cnt], space);
 			dquot_decr_inodes(transfer_from[cnt], 1);
-			dquot_decr_space(transfer_from[cnt], space);
+			dquot_decr_space(transfer_from[cnt], cur_space);
+			dquot_free_reserved_space(transfer_from[cnt],
+						  rsv_space);
 		}
 
 		dquot_incr_inodes(transfer_to[cnt], 1);
-		dquot_incr_space(transfer_to[cnt], space);
+		dquot_incr_space(transfer_to[cnt], cur_space);
+		dquot_resv_space(transfer_to[cnt], rsv_space);
 
 		inode->i_dquot[cnt] = transfer_to[cnt];
 	}
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 54b837f..a510d91 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -311,6 +311,12 @@ struct dquot_operations {
 	int (*write_info) (struct super_block *, int);	/* Write of quota "superblock" */
 	/* reserve quota for delayed block allocation */
 	int (*reserve_space) (struct inode *, qsize_t, int);
+	/* claim reserved quota for delayed alloc */
+	int (*claim_space) (struct inode *, qsize_t);
+	/* release rsved quota for delayed alloc */
+	void (*release_rsv) (struct inode *, qsize_t);
+	/* get reserved quota for delayed alloc */
+	qsize_t (*get_reserved_space) (struct inode *);
 };
 
 /* Operations handling requests from userspace */
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 3e3a0d2..7369d04 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -35,6 +35,11 @@ void dquot_destroy(struct dquot *dquot);
 int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
 int dquot_alloc_inode(const struct inode *inode, qsize_t number);
 
+int dquot_reserve_space(struct inode *inode, qsize_t number, int prealloc);
+int dquot_claim_space(struct inode *inode, qsize_t number);
+void dquot_release_reserved_space(struct inode *inode, qsize_t number);
+qsize_t dquot_get_reserved_space(struct inode *inode);
+
 int dquot_free_space(struct inode *inode, qsize_t number);
 int dquot_free_inode(const struct inode *inode, qsize_t number);
 
@@ -203,6 +208,31 @@ static inline int vfs_dq_alloc_inode(struct inode *inode)
 	return 0;
 }
 
+/*
+ * Convert in-memory reserved quotas to real consumed quotas
+ */
+static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr)
+{
+	if (sb_any_quota_active(inode->i_sb)) {
+		if (inode->i_sb->dq_op->claim_space(inode, nr) == NO_QUOTA)
+			return 1;
+	} else
+		inode_add_bytes(inode, nr);
+
+	mark_inode_dirty(inode);
+	return 0;
+}
+
+/*
+ * Release reserved (in-memory) quotas
+ */
+static inline
+void vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr)
+{
+	if (sb_any_quota_active(inode->i_sb))
+		inode->i_sb->dq_op->release_rsv(inode, nr);
+}
+
 static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
 {
 	if (sb_any_quota_active(inode->i_sb))
@@ -354,6 +384,17 @@ static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr)
 	return 0;
 }
 
+static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr)
+{
+	return vfs_dq_alloc_space(inode, nr);
+}
+
+static inline
+int vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr)
+{
+	return 0;
+}
+
 static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
 {
 	inode_sub_bytes(inode, nr);
@@ -397,6 +438,18 @@ static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr)
 			nr << inode->i_blkbits);
 }
 
+static inline int vfs_dq_claim_block(struct inode *inode, qsize_t nr)
+{
+	return vfs_dq_claim_space(inode,
+			nr << inode->i_blkbits);
+}
+
+static inline
+void vfs_dq_release_reservation_block(struct inode *inode, qsize_t nr)
+{
+	vfs_dq_release_reservation_space(inode, nr << inode->i_blkbits);
+}
+
 static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr)
 {
 	vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits);
-- 
1.6.0.2


  reply	other threads:[~2009-01-16 18:08 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <yes>
2009-01-16 18:08 ` Quota fixes and improvements Jan Kara
2009-01-16 18:08   ` [PATCH 01/11] quota: Improve locking Jan Kara
2009-01-16 18:08     ` [PATCH 02/11] ocfs2: Remove ocfs2_dquot_initialize() and ocfs2_dquot_drop() Jan Kara
2009-01-16 18:08       ` [PATCH 03/11] ocfs2: Push out dropping of dentry lock to ocfs2_wq Jan Kara
2009-01-16 18:08         ` [PATCH 04/11] ocfs2: Fix possible deadlock in ocfs2_write_dquot() Jan Kara
2009-01-16 18:08           ` [PATCH 05/11] quota: Add quota reservation support Jan Kara
2009-01-16 18:08             ` Jan Kara [this message]
2009-01-16 18:08               ` [PATCH 07/11] quota: Use inode->i_blkbits to get block bits Jan Kara
2009-01-16 18:08                 ` [PATCH 08/11] quota: Move EXPORT_SYMBOL immediately next to the functions/varibles Jan Kara
2009-01-16 18:08                   ` [PATCH 09/11] ext3: Remove unnecessary quota functions Jan Kara
2009-01-16 18:08                     ` [PATCH 10/11] ext4: " Jan Kara
2009-01-16 18:08                       ` [PATCH 11/11] reiserfs: " Jan Kara
2009-01-20 21:41                       ` [PATCH 10/11] ext4: " Mingming Cao
2009-01-20 21:41                     ` [PATCH 09/11] ext3: " Mingming Cao
2009-01-24  7:49     ` [PATCH 01/11] quota: Improve locking Andrew Morton
2009-01-26 10:04       ` Jan Kara
2010-06-22 15:20 ` [RFC][PATCH 00/10] cifs: local caching support using FS-Cache Suresh Jayaraman
2010-06-22 15:22 ` [RFC][PATCH 01/10] cifs: add kernel config option for CIFS Client caching support Suresh Jayaraman
2010-06-22 15:22 ` [RFC][PATCH 02/10] cifs: guard cifsglob.h against multiple inclusion Suresh Jayaraman
     [not found]   ` <1277220170-3442-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-22 21:37     ` Jeff Layton
2010-06-22 15:23 ` [RFC][PATCH 03/10] cifs: register CIFS for caching Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache Suresh Jayaraman
     [not found]   ` <1277220198-3522-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-22 21:52     ` Jeff Layton
     [not found]       ` <20100622175214.4c56234f-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
2010-06-23  5:34         ` Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 07/10] cifs: FS-Cache page management Suresh Jayaraman
2010-06-22 15:24 ` [RFC][PATCH 08/10] cifs: store pages into local cache Suresh Jayaraman
2010-06-22 15:24 ` [RFC][PATCH 09/10] cifs: read pages from FS-Cache Suresh Jayaraman
2010-06-22 15:25 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching Suresh Jayaraman
2010-06-23 18:32   ` Scott Lovenberg
     [not found]     ` <4C225338.9010807-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2010-06-25 10:48       ` Suresh Jayaraman
     [not found] ` <1277220189-3485-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-23 16:51   ` [RFC][PATCH 03/10] cifs: register CIFS for caching David Howells
     [not found]     ` <9603.1277311877-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-25 10:56       ` Suresh Jayaraman
2010-06-23 16:54 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache David Howells
     [not found] ` <1277220206-3559-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-23 16:58   ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them David Howells
     [not found]     ` <9720.1277312290-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-25 12:44       ` Suresh Jayaraman
2010-06-25 12:58     ` David Howells
     [not found]     ` <22746.1277470713-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-25 13:26       ` David Howells
     [not found]         ` <23204.1277472412-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-28 12:53           ` Suresh Jayaraman
2010-06-28 13:24         ` David Howells
     [not found] ` <1277220214-3597-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-23 17:02   ` [RFC][PATCH 06/10] cifs: define inode-level cache object " David Howells
     [not found]     ` <9822.1277312573-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-25 12:50       ` Suresh Jayaraman
     [not found]     ` <4C24A606.5040001-l3A5Bk7waGM@public.gmane.org>
2010-06-25 12:55       ` David Howells
     [not found]         ` <22697.1277470549-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-25 16:53           ` Jeff Layton
2010-06-25 21:46         ` David Howells
2010-06-25 22:26           ` Jeff Layton
2010-06-25 23:05             ` Steve French
2010-06-26  0:52               ` Mingming Cao
2010-06-27 18:17                 ` Aneesh Kumar K. V
     [not found]                   ` <871vbscpce.fsf-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
2010-06-27 18:22                     ` Christoph Hellwig
     [not found]           ` <20100625182651.36800d06-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
2010-06-25 23:04             ` David Howells
2010-06-23 17:05 ` [RFC][PATCH 07/10] cifs: FS-Cache page management David Howells
     [not found] ` <1277220240-3674-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-23 17:06   ` [RFC][PATCH 08/10] cifs: store pages into local cache David Howells
     [not found] ` <1277220261-3717-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-23 17:07   ` [RFC][PATCH 09/10] cifs: read pages from FS-Cache David Howells
2010-06-23 17:08 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching David Howells

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1232129299-22018-7-git-send-email-jack@suse.cz \
    --to=jack@suse.cz \
    --cc=cmm@us.ibm.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).