Commit 2bd99df5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull gfs2 updates from Bob Peterson:
 "We've only got nine GFS2 patches for this merge window:

   - report journal recovery times more accurately during journal replay
     (Abhi Das)

   - fix fallocate chunk size (Andreas Gruenbacher)

   - correctly dirty inodes during rename (Andreas Gruenbacher)

   - improve the comment for function gfs2_block_map (Andreas
     Gruenbacher)

   - improve kernel trace point iomap end: The physical block address
     was added (Andreas Gruenbacher)

   - fix a nasty file system corruption bug that surfaced in xfstests
     476 in punch-hole/truncate (Andreas Gruenbacher)

   - fix a problem Christoph Helwig pointed out, namely, that GFS2 was
     misusing the IOMAP_ZERO flag. The zeroing of new blocks was moved
     to the proper fallocate code (Andreas Gruenbacher)

   - declare function gfs2_remove_from_ail as static (Bob Peterson)

   - only set PageChecked for jdata page writes (Bob Peterson)"

* tag 'gfs2-4.17.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: time journal recovery steps accurately
  gfs2: Zero out fallocated blocks in fallocate_chunk
  gfs2: Check for the end of metadata in punch_hole
  gfs2: gfs2_iomap_end tracepoint: log block address
  gfs2: Improve gfs2_block_map comment
  GFS2: Only set PageChecked for jdata pages
  GFS2: Make function gfs2_remove_from_ail static
  gfs2: Dirty source inode during rename
  gfs2: Fix fallocate chunk size
parents 94514bbe 5e86d9d1
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -940,13 +940,13 @@ failed:
}

/**
 * gfs2_set_page_dirty - Page dirtying function
 * jdata_set_page_dirty - Page dirtying function
 * @page: The page to dirty
 *
 * Returns: 1 if it dirtyed the page, or 0 otherwise
 */
 
static int gfs2_set_page_dirty(struct page *page)
static int jdata_set_page_dirty(struct page *page)
{
	SetPageChecked(page);
	return __set_page_dirty_buffers(page);
@@ -1214,7 +1214,7 @@ static const struct address_space_operations gfs2_ordered_aops = {
	.readpages = gfs2_readpages,
	.write_begin = gfs2_write_begin,
	.write_end = gfs2_write_end,
	.set_page_dirty = gfs2_set_page_dirty,
	.set_page_dirty = __set_page_dirty_buffers,
	.bmap = gfs2_bmap,
	.invalidatepage = gfs2_invalidatepage,
	.releasepage = gfs2_releasepage,
@@ -1231,7 +1231,7 @@ static const struct address_space_operations gfs2_jdata_aops = {
	.readpages = gfs2_readpages,
	.write_begin = gfs2_write_begin,
	.write_end = gfs2_write_end,
	.set_page_dirty = gfs2_set_page_dirty,
	.set_page_dirty = jdata_set_page_dirty,
	.bmap = gfs2_bmap,
	.invalidatepage = gfs2_invalidatepage,
	.releasepage = gfs2_releasepage,
+20 −18
Original line number Diff line number Diff line
@@ -491,14 +491,12 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
{
	struct gfs2_inode *ip = GFS2_I(inode);
	struct gfs2_sbd *sdp = GFS2_SB(inode);
	struct super_block *sb = sdp->sd_vfs;
	struct buffer_head *dibh = mp->mp_bh[0];
	u64 bn;
	unsigned n, i, blks, alloced = 0, iblks = 0, branch_start = 0;
	unsigned dblks = 0;
	unsigned ptrs_per_blk;
	const unsigned end_of_metadata = mp->mp_fheight - 1;
	int ret;
	enum alloc_state state;
	__be64 *ptr;
	__be64 zero_bn = 0;
@@ -607,15 +605,6 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
			iomap->flags |= IOMAP_F_NEW;
			while (n-- > 0)
				*ptr++ = cpu_to_be64(bn++);
			if (flags & IOMAP_ZERO) {
				ret = sb_issue_zeroout(sb, iomap->addr >> inode->i_blkbits,
						       dblks, GFP_NOFS);
				if (ret) {
					fs_err(sdp,
					       "Failed to zero data buffers\n");
					flags &= ~IOMAP_ZERO;
				}
			}
			break;
		}
	} while (iomap->addr == IOMAP_NULL_ADDR);
@@ -812,15 +801,22 @@ do_alloc:
}

/**
 * gfs2_block_map - Map a block from an inode to a disk block
 * gfs2_block_map - Map one or more blocks of an inode to a disk block
 * @inode: The inode
 * @lblock: The logical block number
 * @bh_map: The bh to be mapped
 * @create: True if its ok to alloc blocks to satify the request
 *
 * Sets buffer_mapped() if successful, sets buffer_boundary() if a
 * read of metadata will be required before the next block can be
 * mapped. Sets buffer_new() if new blocks were allocated.
 * The size of the requested mapping is defined in bh_map->b_size.
 *
 * Clears buffer_mapped(bh_map) and leaves bh_map->b_size unchanged
 * when @lblock is not mapped.  Sets buffer_mapped(bh_map) and
 * bh_map->b_size to indicate the size of the mapping when @lblock and
 * successive blocks are mapped, up to the requested size.
 *
 * Sets buffer_boundary() if a read of metadata will be required
 * before the next block can be mapped. Sets buffer_new() if new
 * blocks were allocated.
 *
 * Returns: errno
 */
@@ -839,8 +835,6 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,

	if (create)
		flags |= IOMAP_WRITE;
	if (buffer_zeronew(bh_map))
		flags |= IOMAP_ZERO;
	ret = gfs2_iomap_begin(inode, (loff_t)lblock << inode->i_blkbits,
			       bh_map->b_size, flags, &iomap);
	if (ret) {
@@ -1344,6 +1338,7 @@ static inline bool walk_done(struct gfs2_sbd *sdp,
static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
{
	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
	u64 maxsize = sdp->sd_heightsize[ip->i_height];
	struct metapath mp = {};
	struct buffer_head *dibh, *bh;
	struct gfs2_holder rd_gh;
@@ -1359,6 +1354,14 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
	u64 prev_bnr = 0;
	__be64 *start, *end;

	if (offset >= maxsize) {
		/*
		 * The starting point lies beyond the allocated meta-data;
		 * there are no blocks do deallocate.
		 */
		return 0;
	}

	/*
	 * The start position of the hole is defined by lblock, start_list, and
	 * start_aligned.  The end position of the hole is defined by lend,
@@ -1372,7 +1375,6 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
	 */

	if (length) {
		u64 maxsize = sdp->sd_heightsize[ip->i_height];
		u64 end_offset = offset + length;
		u64 lend;

+2 −11
Original line number Diff line number Diff line
@@ -1940,7 +1940,6 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
{
	struct buffer_head *bh;
	struct gfs2_dirent *dent;
	int error;

	dent = gfs2_dirent_search(&dip->i_inode, filename, gfs2_dirent_find, &bh);
	if (!dent) {
@@ -1953,18 +1952,10 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
	gfs2_trans_add_meta(dip->i_gl, bh);
	gfs2_inum_out(nip, dent);
	dent->de_type = cpu_to_be16(new_type);

	if (dip->i_diskflags & GFS2_DIF_EXHASH) {
	brelse(bh);
		error = gfs2_meta_inode_buffer(dip, &bh);
		if (error)
			return error;
		gfs2_trans_add_meta(dip->i_gl, bh);
	}

	dip->i_inode.i_mtime = dip->i_inode.i_ctime = current_time(&dip->i_inode);
	gfs2_dinode_out(dip, bh->b_data);
	brelse(bh);
	mark_inode_dirty_sync(&dip->i_inode);
	return 0;
}

+17 −17
Original line number Diff line number Diff line
@@ -729,11 +729,12 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
			   int mode)
{
	struct super_block *sb = inode->i_sb;
	struct gfs2_inode *ip = GFS2_I(inode);
	loff_t end = offset + len;
	struct buffer_head *dibh;
	struct iomap iomap;
	int error;
	unsigned int nr_blks;
	sector_t lblock = offset >> inode->i_blkbits;

	error = gfs2_meta_inode_buffer(ip, &dibh);
	if (unlikely(error))
@@ -747,21 +748,19 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
			goto out;
	}

	while (len) {
		struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 };
		bh_map.b_size = len;
		set_buffer_zeronew(&bh_map);

		error = gfs2_block_map(inode, lblock, &bh_map, 1);
		if (unlikely(error))
	while (offset < end) {
		error = gfs2_iomap_begin(inode, offset, end - offset,
					 IOMAP_WRITE, &iomap);
		if (error)
			goto out;
		len -= bh_map.b_size;
		nr_blks = bh_map.b_size >> inode->i_blkbits;
		lblock += nr_blks;
		if (!buffer_new(&bh_map))
		offset = iomap.offset + iomap.length;
		if (iomap.type != IOMAP_HOLE)
			continue;
		if (unlikely(!buffer_zeronew(&bh_map))) {
			error = -EIO;
		error = sb_issue_zeroout(sb, iomap.addr >> inode->i_blkbits,
					 iomap.length >> inode->i_blkbits,
					 GFP_NOFS);
		if (error) {
			fs_err(GFS2_SB(inode), "Failed to zero data buffers\n");
			goto out;
		}
	}
@@ -809,7 +808,7 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
	struct gfs2_inode *ip = GFS2_I(inode);
	struct gfs2_alloc_parms ap = { .aflags = 0, };
	unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
	loff_t bytes, max_bytes, max_blks = UINT_MAX;
	loff_t bytes, max_bytes, max_blks;
	int error;
	const loff_t pos = offset;
	const loff_t count = len;
@@ -861,7 +860,8 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
			return error;
		/* ap.allowed tells us how many blocks quota will allow
		 * us to write. Check if this reduces max_blks */
		if (ap.allowed && ap.allowed < max_blks)
		max_blks = UINT_MAX;
		if (ap.allowed)
			max_blks = ap.allowed;

		error = gfs2_inplace_reserve(ip, &ap);
+0 −3
Original line number Diff line number Diff line
@@ -130,15 +130,12 @@ static inline bool gfs2_rbm_eq(const struct gfs2_rbm *rbm1,
enum gfs2_state_bits {
	BH_Pinned = BH_PrivateStart,
	BH_Escaped = BH_PrivateStart + 1,
	BH_Zeronew = BH_PrivateStart + 2,
};

BUFFER_FNS(Pinned, pinned)
TAS_BUFFER_FNS(Pinned, pinned)
BUFFER_FNS(Escaped, escaped)
TAS_BUFFER_FNS(Escaped, escaped)
BUFFER_FNS(Zeronew, zeronew)
TAS_BUFFER_FNS(Zeronew, zeronew)

struct gfs2_bufdata {
	struct buffer_head *bd_bh;
Loading