diff mbox

[2/3] quota: add the option to not fail with EDQUOT in block allocation

Message ID 4BBCFE9C.4070302@redhat.com
State Accepted, archived
Headers show

Commit Message

Eric Sandeen April 7, 2010, 9:52 p.m. UTC
To simplify metadata tracking for delalloc writes, ext4
will simply claim metadata blocks at allocation time, without
first speculatively reserving the worst case and then freeing
what was not used.

To do this, we need a mechanism to track allocations in
the quota subsystem, but potentially allow that allocation
to actually go over quota.

This patch adds a DQUOT_SPACE_NOFAIL flag and function
variants for this purpose.

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---


--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Jan Kara April 12, 2010, 1:23 p.m. UTC | #1
> To simplify metadata tracking for delalloc writes, ext4
> will simply claim metadata blocks at allocation time, without
> first speculatively reserving the worst case and then freeing
> what was not used.
> 
> To do this, we need a mechanism to track allocations in
> the quota subsystem, but potentially allow that allocation
> to actually go over quota.
> 
> This patch adds a DQUOT_SPACE_NOFAIL flag and function
> variants for this purpose.
> 
> Signed-off-by: Eric Sandeen <sandeen@redhat.com>
   Looks fine. Acked-by: Jan Kara <jack@suse.cz>

								Honza
> ---
> 
> diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
> index 8436d9b..c38b137 100644
> --- a/fs/quota/dquot.c
> +++ b/fs/quota/dquot.c
> @@ -1490,6 +1490,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
>  	char warntype[MAXQUOTAS];
>  	int warn = flags & DQUOT_SPACE_WARN;
>  	int reserve = flags & DQUOT_SPACE_RESERVE;
> +	int nofail = flags & DQUOT_SPACE_NOFAIL;
>  
>  	/*
>  	 * First test before acquiring mutex - solves deadlocks when we
> @@ -1510,7 +1511,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
>  			continue;
>  		ret = check_bdq(inode->i_dquot[cnt], number, !warn,
>  				warntype+cnt);
> -		if (ret) {
> +		if (ret && !nofail) {
>  			spin_unlock(&dq_data_lock);
>  			goto out_flush_warn;
>  		}
> diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
> index daa106f..8f858ce 100644
> --- a/include/linux/quotaops.h
> +++ b/include/linux/quotaops.h
> @@ -16,6 +16,7 @@ static inline struct quota_info *sb_dqopt(struct super_block *sb)
>  
>  #define DQUOT_SPACE_WARN	0x1
>  #define DQUOT_SPACE_RESERVE	0x2
> +#define DQUOT_SPACE_NOFAIL	0x4
>  
>  #if defined(CONFIG_QUOTA)
>  
> @@ -262,6 +263,12 @@ static inline int dquot_alloc_space_nodirty(struct inode *inode, qsize_t nr)
>  	return __dquot_alloc_space(inode, nr, DQUOT_SPACE_WARN);
>  }
>  
> +static inline void dquot_alloc_space_nofail(struct inode *inode, qsize_t nr)
> +{
> +	__dquot_alloc_space(inode, nr, DQUOT_SPACE_WARN|DQUOT_SPACE_NOFAIL);
> +	mark_inode_dirty(inode);
> +}
> +
>  static inline int dquot_alloc_space(struct inode *inode, qsize_t nr)
>  {
>  	int ret;
> @@ -277,6 +284,11 @@ static inline int dquot_alloc_block_nodirty(struct inode *inode, qsize_t nr)
>  	return dquot_alloc_space_nodirty(inode, nr << inode->i_blkbits);
>  }
>  
> +static inline void dquot_alloc_block_nofail(struct inode *inode, qsize_t nr)
> +{
> +	dquot_alloc_space_nofail(inode, nr << inode->i_blkbits);
> +}
> +
>  static inline int dquot_alloc_block(struct inode *inode, qsize_t nr)
>  {
>  	return dquot_alloc_space(inode, nr << inode->i_blkbits);
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Theodore Ts'o May 20, 2010, 10:32 p.m. UTC | #2
On Wed, Apr 07, 2010 at 04:52:28PM -0500, Eric Sandeen wrote:
> To simplify metadata tracking for delalloc writes, ext4
> will simply claim metadata blocks at allocation time, without
> first speculatively reserving the worst case and then freeing
> what was not used.
> 
> To do this, we need a mechanism to track allocations in
> the quota subsystem, but potentially allow that allocation
> to actually go over quota.
> 
> This patch adds a DQUOT_SPACE_NOFAIL flag and function
> variants for this purpose.
> 
> Signed-off-by: Eric Sandeen <sandeen@redhat.com>

Applied to the ext4 patch queue.

					- Ted
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 8436d9b..c38b137 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -1490,6 +1490,7 @@  int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
 	char warntype[MAXQUOTAS];
 	int warn = flags & DQUOT_SPACE_WARN;
 	int reserve = flags & DQUOT_SPACE_RESERVE;
+	int nofail = flags & DQUOT_SPACE_NOFAIL;
 
 	/*
 	 * First test before acquiring mutex - solves deadlocks when we
@@ -1510,7 +1511,7 @@  int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
 			continue;
 		ret = check_bdq(inode->i_dquot[cnt], number, !warn,
 				warntype+cnt);
-		if (ret) {
+		if (ret && !nofail) {
 			spin_unlock(&dq_data_lock);
 			goto out_flush_warn;
 		}
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index daa106f..8f858ce 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -16,6 +16,7 @@  static inline struct quota_info *sb_dqopt(struct super_block *sb)
 
 #define DQUOT_SPACE_WARN	0x1
 #define DQUOT_SPACE_RESERVE	0x2
+#define DQUOT_SPACE_NOFAIL	0x4
 
 #if defined(CONFIG_QUOTA)
 
@@ -262,6 +263,12 @@  static inline int dquot_alloc_space_nodirty(struct inode *inode, qsize_t nr)
 	return __dquot_alloc_space(inode, nr, DQUOT_SPACE_WARN);
 }
 
+static inline void dquot_alloc_space_nofail(struct inode *inode, qsize_t nr)
+{
+	__dquot_alloc_space(inode, nr, DQUOT_SPACE_WARN|DQUOT_SPACE_NOFAIL);
+	mark_inode_dirty(inode);
+}
+
 static inline int dquot_alloc_space(struct inode *inode, qsize_t nr)
 {
 	int ret;
@@ -277,6 +284,11 @@  static inline int dquot_alloc_block_nodirty(struct inode *inode, qsize_t nr)
 	return dquot_alloc_space_nodirty(inode, nr << inode->i_blkbits);
 }
 
+static inline void dquot_alloc_block_nofail(struct inode *inode, qsize_t nr)
+{
+	dquot_alloc_space_nofail(inode, nr << inode->i_blkbits);
+}
+
 static inline int dquot_alloc_block(struct inode *inode, qsize_t nr)
 {
 	return dquot_alloc_space(inode, nr << inode->i_blkbits);