quota: add the option to not fail with EDQUOT in block
authorEric Sandeen <sandeen@redhat.com>
Sun, 16 May 2010 14:00:00 +0000 (10:00 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 16 May 2010 14:00:00 +0000 (10:00 -0400)
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>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
fs/quota/dquot.c
include/linux/quotaops.h

index 8c40c07797ad3d8c64a05ae799f746edceebea4f..df6832ec17c3adcc831cfa100ab80dab4e3d958f 100644 (file)
@@ -1494,6 +1494,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
@@ -1514,7 +1515,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;
                }
index 9edd53c24984b9f378eb9adbe99f3c23663a4ffb..f8dbeb0fe0c9742a800c83b2bc6b97a876a8bb5a 100644 (file)
@@ -11,6 +11,7 @@
 
 #define DQUOT_SPACE_WARN       0x1
 #define DQUOT_SPACE_RESERVE    0x2
+#define DQUOT_SPACE_NOFAIL     0x4
 
 static inline struct quota_info *sb_dqopt(struct super_block *sb)
 {
@@ -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);