]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - fs/gfs2/bmap.c
Merge tag 'gfs2-for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux...
[mirror_ubuntu-jammy-kernel.git] / fs / gfs2 / bmap.c
index 8dfe09f52cbc0b06478ff36e185a0e9c26c93614..770f3a720db9a44f853c95fe4b7985505f7d83ad 100644 (file)
@@ -1351,9 +1351,15 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
        return ret;
 }
 
+/*
+ * NOTE: Never call gfs2_block_zero_range with an open transaction because it
+ * uses iomap write to perform its actions, which begin their own transactions
+ * (iomap_begin, page_prepare, etc.)
+ */
 static int gfs2_block_zero_range(struct inode *inode, loff_t from,
                                 unsigned int length)
 {
+       BUG_ON(current->journal_info);
        return iomap_zero_range(inode, from, length, NULL, &gfs2_iomap_ops);
 }
 
@@ -1414,6 +1420,16 @@ static int trunc_start(struct inode *inode, u64 newsize)
        u64 oldsize = inode->i_size;
        int error;
 
+       if (!gfs2_is_stuffed(ip)) {
+               unsigned int blocksize = i_blocksize(inode);
+               unsigned int offs = newsize & (blocksize - 1);
+               if (offs) {
+                       error = gfs2_block_zero_range(inode, newsize,
+                                                     blocksize - offs);
+                       if (error)
+                               return error;
+               }
+       }
        if (journaled)
                error = gfs2_trans_begin(sdp, RES_DINODE + RES_JDATA, GFS2_JTRUNC_REVOKES);
        else
@@ -1427,19 +1443,10 @@ static int trunc_start(struct inode *inode, u64 newsize)
 
        gfs2_trans_add_meta(ip->i_gl, dibh);
 
-       if (gfs2_is_stuffed(ip)) {
+       if (gfs2_is_stuffed(ip))
                gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + newsize);
-       } else {
-               unsigned int blocksize = i_blocksize(inode);
-               unsigned int offs = newsize & (blocksize - 1);
-               if (offs) {
-                       error = gfs2_block_zero_range(inode, newsize,
-                                                     blocksize - offs);
-                       if (error)
-                               goto out;
-               }
+       else
                ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG;
-       }
 
        i_size_write(inode, newsize);
        ip->i_inode.i_mtime = ip->i_inode.i_ctime = current_time(&ip->i_inode);
@@ -2448,25 +2455,7 @@ int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length)
        loff_t start, end;
        int error;
 
-       start = round_down(offset, blocksize);
-       end = round_up(offset + length, blocksize) - 1;
-       error = filemap_write_and_wait_range(inode->i_mapping, start, end);
-       if (error)
-               return error;
-
-       if (gfs2_is_jdata(ip))
-               error = gfs2_trans_begin(sdp, RES_DINODE + 2 * RES_JDATA,
-                                        GFS2_JTRUNC_REVOKES);
-       else
-               error = gfs2_trans_begin(sdp, RES_DINODE, 0);
-       if (error)
-               return error;
-
-       if (gfs2_is_stuffed(ip)) {
-               error = stuffed_zero_range(inode, offset, length);
-               if (error)
-                       goto out;
-       } else {
+       if (!gfs2_is_stuffed(ip)) {
                unsigned int start_off, end_len;
 
                start_off = offset & (blocksize - 1);
@@ -2489,6 +2478,26 @@ int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length)
                }
        }
 
+       start = round_down(offset, blocksize);
+       end = round_up(offset + length, blocksize) - 1;
+       error = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (error)
+               return error;
+
+       if (gfs2_is_jdata(ip))
+               error = gfs2_trans_begin(sdp, RES_DINODE + 2 * RES_JDATA,
+                                        GFS2_JTRUNC_REVOKES);
+       else
+               error = gfs2_trans_begin(sdp, RES_DINODE, 0);
+       if (error)
+               return error;
+
+       if (gfs2_is_stuffed(ip)) {
+               error = stuffed_zero_range(inode, offset, length);
+               if (error)
+                       goto out;
+       }
+
        if (gfs2_is_jdata(ip)) {
                BUG_ON(!current->journal_info);
                gfs2_journaled_truncate_range(inode, offset, length);