Commit 018d21f5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull gfs2 updates from Bob Peterson:
 "We've got a lot of patches (39) for this merge window. Most of these
  patches are related to corruption that occurs when journals are
  replayed. For example:

   1. A node fails while writing to the file system.
   2. Other nodes use the metadata that was once used by the failed
      node.
   3. When the node returns to the cluster, its journal is replayed, but
      the older metadata blocks overwrite the changes from step 2.

  Summary:

   - Fixed the recovery sequence to prevent corruption during journal
     replay.

   - Many bug fixes found during recovery testing.

   - New improved file system withdraw sequence.

   - Fixed how resource group buffers are managed.

   - Fixed how metadata revokes are tracked and written.

   - Improve processing of IO errors hit by daemons like logd and
     quotad.

   - Improved error checking in metadata writes.

   - Fixed how qadata quota data structures are managed"

* tag 'gfs2-for-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: (39 commits)
  gfs2: Fix oversight in gfs2_ail1_flush
  gfs2: change from write to read lock for sd_log_flush_lock in journal replay
  gfs2: instrumentation wrt ail1 stuck
  gfs2: don't lock sd_log_flush_lock in try_rgrp_unlink
  gfs2: Remove unnecessary gfs2_qa_{get,put} pairs
  gfs2: Split gfs2_rsqa_delete into gfs2_rs_delete and gfs2_qa_put
  gfs2: Change inode qa_data to allow multiple users
  gfs2: eliminate gfs2_rsqa_alloc in favor of gfs2_qa_alloc
  gfs2: Switch to list_{first,last}_entry
  gfs2: Clean up inode initialization and teardown
  gfs2: Additional information when gfs2_ail1_flush withdraws
  gfs2: leaf_dealloc needs to allocate one more revoke
  gfs2: allow journal replay to hold sd_log_flush_lock
  gfs2: don't allow releasepage to free bd still used for revokes
  gfs2: flesh out delayed withdraw for gfs2_log_flush
  gfs2: Do proper error checking for go_sync family of glops functions
  gfs2: Don't demote a glock until its revokes are written
  gfs2: drain the ail2 list after io errors
  gfs2: Withdraw in gfs2_ail1_flush if write_cache_pages fails
  gfs2: Do log_flush in gfs2_ail_empty_gl even if ail list is empty
  ...
parents 15c981d1 75b46c43
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include "glock.h"
#include "inode.h"
#include "meta_io.h"
#include "quota.h"
#include "rgrp.h"
#include "trans.h"
#include "util.h"
@@ -116,14 +117,14 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
	if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode)))
		return -E2BIG;

	ret = gfs2_rsqa_alloc(ip);
	ret = gfs2_qa_get(ip);
	if (ret)
		return ret;

	if (!gfs2_glock_is_locked_by_me(ip->i_gl)) {
		ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
		if (ret)
			return ret;
			goto out;
		need_unlock = true;
	}

@@ -143,5 +144,7 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
unlock:
	if (need_unlock)
		gfs2_glock_dq_uninit(&gh);
out:
	gfs2_qa_put(ip);
	return ret;
}
+8 −3
Original line number Diff line number Diff line
@@ -805,10 +805,15 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
		bd = bh->b_private;
		if (bd) {
			gfs2_assert_warn(sdp, bd->bd_bh == bh);
			if (!list_empty(&bd->bd_list))
				list_del_init(&bd->bd_list);
			bd->bd_bh = NULL;
			bh->b_private = NULL;
			/*
			 * The bd may still be queued as a revoke, in which
			 * case we must not dequeue nor free it.
			 */
			if (!bd->bd_blkno && !list_empty(&bd->bd_list))
				list_del_init(&bd->bd_list);
			if (list_empty(&bd->bd_list))
				kmem_cache_free(gfs2_bufdata_cachep, bd);
		}

+5 −4
Original line number Diff line number Diff line
@@ -2183,7 +2183,7 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)

	inode_dio_wait(inode);

	ret = gfs2_rsqa_alloc(ip);
	ret = gfs2_qa_get(ip);
	if (ret)
		goto out;

@@ -2194,7 +2194,8 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)

	ret = do_shrink(inode, newsize);
out:
	gfs2_rsqa_delete(ip, NULL);
	gfs2_rs_delete(ip, NULL);
	gfs2_qa_put(ip);
	return ret;
}

@@ -2223,7 +2224,7 @@ void gfs2_free_journal_extents(struct gfs2_jdesc *jd)
	struct gfs2_journal_extent *jext;

	while(!list_empty(&jd->extent_list)) {
		jext = list_entry(jd->extent_list.next, struct gfs2_journal_extent, list);
		jext = list_first_entry(&jd->extent_list, struct gfs2_journal_extent, list);
		list_del(&jext->list);
		kfree(jext);
	}
@@ -2244,7 +2245,7 @@ static int gfs2_add_jextent(struct gfs2_jdesc *jd, u64 lblock, u64 dblock, u64 b
	struct gfs2_journal_extent *jext;

	if (!list_empty(&jd->extent_list)) {
		jext = list_entry(jd->extent_list.prev, struct gfs2_journal_extent, list);
		jext = list_last_entry(&jd->extent_list, struct gfs2_journal_extent, list);
		if ((jext->dblock + jext->blocks) == dblock) {
			jext->blocks += blocks;
			return 0;
+2 −1
Original line number Diff line number Diff line
@@ -2028,7 +2028,8 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,

	error = gfs2_trans_begin(sdp,
			rg_blocks + (DIV_ROUND_UP(size, sdp->sd_jbsize) + 1) +
			RES_DINODE + RES_STATFS + RES_QUOTA, l_blocks);
			RES_DINODE + RES_STATFS + RES_QUOTA, RES_DINODE +
				 l_blocks);
	if (error)
		goto out_rg_gunlock;

+17 −26
Original line number Diff line number Diff line
@@ -458,10 +458,6 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)

	sb_start_pagefault(inode->i_sb);

	ret = gfs2_rsqa_alloc(ip);
	if (ret)
		goto out;

	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
	ret = gfs2_glock_nq(&gh);
	if (ret)
@@ -558,7 +554,6 @@ out_uninit:
		set_page_dirty(page);
		wait_for_stable_page(page);
	}
out:
	sb_end_pagefault(inode->i_sb);
	return block_page_mkwrite_return(ret);
}
@@ -635,7 +630,17 @@ int gfs2_open_common(struct inode *inode, struct file *file)

	gfs2_assert_warn(GFS2_SB(inode), !file->private_data);
	file->private_data = fp;
	if (file->f_mode & FMODE_WRITE) {
		ret = gfs2_qa_get(GFS2_I(inode));
		if (ret)
			goto fail;
	}
	return 0;

fail:
	kfree(file->private_data);
	file->private_data = NULL;
	return ret;
}

/**
@@ -690,10 +695,10 @@ static int gfs2_release(struct inode *inode, struct file *file)
	kfree(file->private_data);
	file->private_data = NULL;

	if (!(file->f_mode & FMODE_WRITE))
		return 0;

	gfs2_rsqa_delete(ip, &inode->i_writecount);
	if (file->f_mode & FMODE_WRITE) {
		gfs2_rs_delete(ip, &inode->i_writecount);
		gfs2_qa_put(ip);
	}
	return 0;
}

@@ -849,10 +854,6 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
	struct gfs2_inode *ip = GFS2_I(inode);
	ssize_t ret;

	ret = gfs2_rsqa_alloc(ip);
	if (ret)
		return ret;

	gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from));

	if (iocb->ki_flags & IOCB_APPEND) {
@@ -1149,17 +1150,11 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t le
	if (mode & FALLOC_FL_PUNCH_HOLE) {
		ret = __gfs2_punch_hole(file, offset, len);
	} else {
		ret = gfs2_rsqa_alloc(ip);
		if (ret)
			goto out_putw;

		ret = __gfs2_fallocate(file, mode, offset, len);

		if (ret)
			gfs2_rs_deltree(&ip->i_res);
	}

out_putw:
	put_write_access(inode);
out_unlock:
	gfs2_glock_dq(&gh);
@@ -1173,16 +1168,12 @@ static ssize_t gfs2_file_splice_write(struct pipe_inode_info *pipe,
				      struct file *out, loff_t *ppos,
				      size_t len, unsigned int flags)
{
	int error;
	struct gfs2_inode *ip = GFS2_I(out->f_mapping->host);

	error = gfs2_rsqa_alloc(ip);
	if (error)
		return (ssize_t)error;
	ssize_t ret;

	gfs2_size_hint(out, *ppos, len);

	return iter_file_splice_write(pipe, out, ppos, len, flags);
	ret = iter_file_splice_write(pipe, out, ppos, len, flags);
	return ret;
}

#ifdef CONFIG_GFS2_FS_LOCKING_DLM
Loading