quota: provide interface for readding allocated space into reserved space
authorJan Kara <jack@suse.cz>
Sat, 17 Aug 2013 13:32:32 +0000 (09:32 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 17 Aug 2013 13:32:32 +0000 (09:32 -0400)
ext4 needs to convert allocated (metadata) blocks back into blocks
reserved for delayed allocation. Add functions into quota code for
supporting such operation.

Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
fs/quota/dquot.c
fs/stat.c
include/linux/fs.h
include/linux/quotaops.h

index fbad622841f904ebd471ae0668f03018309a076e..9a702e1935383d1e8deda7678e529426262a8636 100644 (file)
@@ -1094,6 +1094,14 @@ static void dquot_claim_reserved_space(struct dquot *dquot, qsize_t number)
        dquot->dq_dqb.dqb_rsvspace -= number;
 }
 
+static void dquot_reclaim_reserved_space(struct dquot *dquot, qsize_t number)
+{
+       if (WARN_ON_ONCE(dquot->dq_dqb.dqb_curspace < number))
+               number = dquot->dq_dqb.dqb_curspace;
+       dquot->dq_dqb.dqb_rsvspace += number;
+       dquot->dq_dqb.dqb_curspace -= number;
+}
+
 static inline
 void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
 {
@@ -1528,6 +1536,15 @@ void inode_claim_rsv_space(struct inode *inode, qsize_t number)
 }
 EXPORT_SYMBOL(inode_claim_rsv_space);
 
+void inode_reclaim_rsv_space(struct inode *inode, qsize_t number)
+{
+       spin_lock(&inode->i_lock);
+       *inode_reserved_space(inode) += number;
+       __inode_sub_bytes(inode, number);
+       spin_unlock(&inode->i_lock);
+}
+EXPORT_SYMBOL(inode_reclaim_rsv_space);
+
 void inode_sub_rsv_space(struct inode *inode, qsize_t number)
 {
        spin_lock(&inode->i_lock);
@@ -1701,6 +1718,35 @@ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
 }
 EXPORT_SYMBOL(dquot_claim_space_nodirty);
 
+/*
+ * Convert allocated space back to in-memory reserved quotas
+ */
+void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
+{
+       int cnt;
+
+       if (!dquot_active(inode)) {
+               inode_reclaim_rsv_space(inode, number);
+               return;
+       }
+
+       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+       spin_lock(&dq_data_lock);
+       /* Claim reserved quotas to allocated quotas */
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+               if (inode->i_dquot[cnt])
+                       dquot_reclaim_reserved_space(inode->i_dquot[cnt],
+                                                    number);
+       }
+       /* Update inode bytes */
+       inode_reclaim_rsv_space(inode, number);
+       spin_unlock(&dq_data_lock);
+       mark_all_dquot_dirty(inode->i_dquot);
+       up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+       return;
+}
+EXPORT_SYMBOL(dquot_reclaim_space_nodirty);
+
 /*
  * This operation can block, but only after everything is updated
  */
index 04ce1ac20d20b393d13bdfcd0e24c8ca4cde743e..d0ea7ef75e264ef2cccf2c100d4e3a8c7393121c 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -447,9 +447,8 @@ void inode_add_bytes(struct inode *inode, loff_t bytes)
 
 EXPORT_SYMBOL(inode_add_bytes);
 
-void inode_sub_bytes(struct inode *inode, loff_t bytes)
+void __inode_sub_bytes(struct inode *inode, loff_t bytes)
 {
-       spin_lock(&inode->i_lock);
        inode->i_blocks -= bytes >> 9;
        bytes &= 511;
        if (inode->i_bytes < bytes) {
@@ -457,6 +456,14 @@ void inode_sub_bytes(struct inode *inode, loff_t bytes)
                inode->i_bytes += 512;
        }
        inode->i_bytes -= bytes;
+}
+
+EXPORT_SYMBOL(__inode_sub_bytes);
+
+void inode_sub_bytes(struct inode *inode, loff_t bytes)
+{
+       spin_lock(&inode->i_lock);
+       __inode_sub_bytes(inode, bytes);
        spin_unlock(&inode->i_lock);
 }
 
index 981874773e85adfe81c2d24d59daa79aea157114..e7893523f81f200cb1f038820493e45dd8b7e697 100644 (file)
@@ -2503,6 +2503,7 @@ extern void generic_fillattr(struct inode *, struct kstat *);
 extern int vfs_getattr(struct path *, struct kstat *);
 void __inode_add_bytes(struct inode *inode, loff_t bytes);
 void inode_add_bytes(struct inode *inode, loff_t bytes);
+void __inode_sub_bytes(struct inode *inode, loff_t bytes);
 void inode_sub_bytes(struct inode *inode, loff_t bytes);
 loff_t inode_get_bytes(struct inode *inode);
 void inode_set_bytes(struct inode *inode, loff_t bytes);
index 1c50093ae656d97211374aeaf30b6998a9e0a764..6965fe394c3bb9d3b66681a8bfd1b9f84a970def 100644 (file)
@@ -41,6 +41,7 @@ void __quota_error(struct super_block *sb, const char *func,
 void inode_add_rsv_space(struct inode *inode, qsize_t number);
 void inode_claim_rsv_space(struct inode *inode, qsize_t number);
 void inode_sub_rsv_space(struct inode *inode, qsize_t number);
+void inode_reclaim_rsv_space(struct inode *inode, qsize_t number);
 
 void dquot_initialize(struct inode *inode);
 void dquot_drop(struct inode *inode);
@@ -59,6 +60,7 @@ int dquot_alloc_inode(const struct inode *inode);
 
 int dquot_claim_space_nodirty(struct inode *inode, qsize_t number);
 void dquot_free_inode(const struct inode *inode);
+void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number);
 
 int dquot_disable(struct super_block *sb, int type, unsigned int flags);
 /* Suspend quotas on remount RO */
@@ -238,6 +240,13 @@ static inline int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
        return 0;
 }
 
+static inline int dquot_reclaim_space_nodirty(struct inode *inode,
+                                             qsize_t number)
+{
+       inode_sub_bytes(inode, number);
+       return 0;
+}
+
 static inline int dquot_disable(struct super_block *sb, int type,
                unsigned int flags)
 {
@@ -336,6 +345,12 @@ static inline int dquot_claim_block(struct inode *inode, qsize_t nr)
        return ret;
 }
 
+static inline void dquot_reclaim_block(struct inode *inode, qsize_t nr)
+{
+       dquot_reclaim_space_nodirty(inode, nr << inode->i_blkbits);
+       mark_inode_dirty_sync(inode);
+}
+
 static inline void dquot_free_space_nodirty(struct inode *inode, qsize_t nr)
 {
        __dquot_free_space(inode, nr, 0);