ufs: restore maintaining ->i_blocks
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 9 Jun 2017 01:15:03 +0000 (21:15 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Jun 2017 13:06:01 +0000 (15:06 +0200)
commit eb315d2ae614493fd1ebb026c75a80573d84f7ad upstream.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/stat.c
fs/ufs/balloc.c

index 2935032..068fdbc 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -454,6 +454,7 @@ void __inode_add_bytes(struct inode *inode, loff_t bytes)
                inode->i_bytes -= 512;
        }
 }
+EXPORT_SYMBOL(__inode_add_bytes);
 
 void inode_add_bytes(struct inode *inode, loff_t bytes)
 {
index 67e085d..a81b970 100644 (file)
@@ -81,7 +81,8 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
                        ufs_error (sb, "ufs_free_fragments",
                                   "bit already cleared for fragment %u", i);
        }
-       
+
+       inode_sub_bytes(inode, count << uspi->s_fshift);
        fs32_add(sb, &ucg->cg_cs.cs_nffree, count);
        uspi->cs_total.cs_nffree += count;
        fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
@@ -183,6 +184,7 @@ do_more:
                        ufs_error(sb, "ufs_free_blocks", "freeing free fragment");
                }
                ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
+               inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift);
                if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
                        ufs_clusteracct (sb, ucpi, blkno, 1);
 
@@ -494,6 +496,20 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
        return 0;
 }              
 
+static bool try_add_frags(struct inode *inode, unsigned frags)
+{
+       unsigned size = frags * i_blocksize(inode);
+       spin_lock(&inode->i_lock);
+       __inode_add_bytes(inode, size);
+       if (unlikely((u32)inode->i_blocks != inode->i_blocks)) {
+               __inode_sub_bytes(inode, size);
+               spin_unlock(&inode->i_lock);
+               return false;
+       }
+       spin_unlock(&inode->i_lock);
+       return true;
+}
+
 static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
                             unsigned oldcount, unsigned newcount)
 {
@@ -530,6 +546,9 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
        for (i = oldcount; i < newcount; i++)
                if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
                        return 0;
+
+       if (!try_add_frags(inode, count))
+               return 0;
        /*
         * Block can be extended
         */
@@ -647,6 +666,7 @@ cg_found:
                        ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
                i = uspi->s_fpb - count;
 
+               inode_sub_bytes(inode, i << uspi->s_fshift);
                fs32_add(sb, &ucg->cg_cs.cs_nffree, i);
                uspi->cs_total.cs_nffree += i;
                fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i);
@@ -657,6 +677,8 @@ cg_found:
        result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
        if (result == INVBLOCK)
                return 0;
+       if (!try_add_frags(inode, count))
+               return 0;
        for (i = 0; i < count; i++)
                ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i);
        
@@ -716,6 +738,8 @@ norot:
                return INVBLOCK;
        ucpi->c_rotor = result;
 gotit:
+       if (!try_add_frags(inode, uspi->s_fpb))
+               return 0;
        blkno = ufs_fragstoblks(result);
        ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
        if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)