Commit 6830d503 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull gfs2 updtaes from Andreas Gruenbacher:

 - Revert a change to delete_work_func() that has gone wrong in commit
   c412a97c ("gfs2: Use TRY lock in gfs2_inode_lookup for UNLINKED
   inodes").

 - Avoid dequeuing GL_ASYNC glock holders twice by first checking if the
   holder is still queued.

 - gfs2: Always check the inode size of inline inodes when reading in
   inodes to prevent corrupt filesystem images from causing weid errors.

 - Properly handle a race between gfs2_create_inode() and
   gfs2_inode_lookup() that causes insert_inode_locked4() to return
   -EBUSY.

 - Fix and clean up the interaction between gfs2_create_inode() and
   gfs2_evict_inode() by completely handling the inode deallocation and
   destruction in gfs2_evict_inode().

 - Remove support for glock holder auto-demotion as we have no current
   plans of using this feature again.

 - And a few more minor cleanups and clarifications.

* tag 'gfs2-v6.1-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: Remove support for glock holder auto-demotion (2)
  gfs2: Remove support for glock holder auto-demotion
  gfs2: Minor gfs2_try_evict cleanup
  gfs2: Partially revert gfs2_inode_lookup change
  gfs2: Add gfs2_inode_lookup comment
  gfs2: Uninline and improve glock_{set,clear}_object
  gfs2: Simply dequeue iopen glock in gfs2_evict_inode
  gfs2: Clean up after gfs2_create_inode rework
  gfs2: Avoid dequeuing GL_ASYNC glock holders twice
  gfs2: Make gfs2_glock_hold return its glock argument
  gfs2: Always check inode size of inline inodes
  gfs2: Cosmetic gfs2_dinode_{in,out} cleanup
  gfs2: Handle -EBUSY result of insert_inode_locked4
  gfs2: Fix and clean up create / evict interaction
  gfs2: Clean up initialization of "ip" in gfs2_create_inode
  gfs2: Get rid of ghs[] in gfs2_create_inode
  gfs2: Add extra error check in alloc_dinode
parents 77856d91 6b46a061
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -427,8 +427,6 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
		return error;

	kaddr = kmap_atomic(page);
	if (dsize > gfs2_max_stuffed_size(ip))
		dsize = gfs2_max_stuffed_size(ip);
	memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
	memset(kaddr + dsize, 0, PAGE_SIZE - dsize);
	kunmap_atomic(kaddr);
+0 −3
Original line number Diff line number Diff line
@@ -61,9 +61,6 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
		void *kaddr = kmap(page);
		u64 dsize = i_size_read(inode);
 
		if (dsize > gfs2_max_stuffed_size(ip))
			dsize = gfs2_max_stuffed_size(ip);

		memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
		memset(kaddr + dsize, 0, PAGE_SIZE - dsize);
		kunmap(page);
+1 −2
Original line number Diff line number Diff line
@@ -1445,14 +1445,13 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)

static void __flock_holder_uninit(struct file *file, struct gfs2_holder *fl_gh)
{
	struct gfs2_glock *gl = fl_gh->gh_gl;
	struct gfs2_glock *gl = gfs2_glock_hold(fl_gh->gh_gl);

	/*
	 * Make sure gfs2_glock_put() won't sleep under the file->f_lock
	 * spinlock.
	 */

	gfs2_glock_hold(gl);
	spin_lock(&file->f_lock);
	gfs2_holder_uninit(fl_gh);
	spin_unlock(&file->f_lock);
+99 −170
Original line number Diff line number Diff line
@@ -186,10 +186,11 @@ void gfs2_glock_free(struct gfs2_glock *gl)
 *
 */

void gfs2_glock_hold(struct gfs2_glock *gl)
struct gfs2_glock *gfs2_glock_hold(struct gfs2_glock *gl)
{
	GLOCK_BUG_ON(gl, __lockref_is_dead(&gl->gl_lockref));
	lockref_get(&gl->gl_lockref);
	return gl;
}

/**
@@ -205,12 +206,6 @@ static int demote_ok(const struct gfs2_glock *gl)

	if (gl->gl_state == LM_ST_UNLOCKED)
		return 0;
	/*
	 * Note that demote_ok is used for the lru process of disposing of
	 * glocks. For this purpose, we don't care if the glock's holders
	 * have the HIF_MAY_DEMOTE flag set or not. If someone is using
	 * them, don't demote.
	 */
	if (!list_empty(&gl->gl_holders))
		return 0;
	if (glops->go_demote_ok)
@@ -393,7 +388,7 @@ static void do_error(struct gfs2_glock *gl, const int ret)
	struct gfs2_holder *gh, *tmp;

	list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
		if (!test_bit(HIF_WAIT, &gh->gh_iflags))
		if (test_bit(HIF_HOLDER, &gh->gh_iflags))
			continue;
		if (ret & LM_OUT_ERROR)
			gh->gh_error = -EIO;
@@ -407,45 +402,6 @@ static void do_error(struct gfs2_glock *gl, const int ret)
	}
}

/**
 * demote_incompat_holders - demote incompatible demoteable holders
 * @gl: the glock we want to promote
 * @current_gh: the newly promoted holder
 *
 * We're passing the newly promoted holder in @current_gh, but actually, any of
 * the strong holders would do.
 */
static void demote_incompat_holders(struct gfs2_glock *gl,
				    struct gfs2_holder *current_gh)
{
	struct gfs2_holder *gh, *tmp;

	/*
	 * Demote incompatible holders before we make ourselves eligible.
	 * (This holder may or may not allow auto-demoting, but we don't want
	 * to demote the new holder before it's even granted.)
	 */
	list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
		/*
		 * Since holders are at the front of the list, we stop when we
		 * find the first non-holder.
		 */
		if (!test_bit(HIF_HOLDER, &gh->gh_iflags))
			return;
		if (gh == current_gh)
			continue;
		if (test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags) &&
		    !may_grant(gl, current_gh, gh)) {
			/*
			 * We should not recurse into do_promote because
			 * __gfs2_glock_dq only calls handle_callback,
			 * gfs2_glock_add_to_lru and __gfs2_glock_queue_work.
			 */
			__gfs2_glock_dq(gh);
		}
	}
}

/**
 * find_first_holder - find the first "holder" gh
 * @gl: the glock
@@ -464,26 +420,6 @@ static inline struct gfs2_holder *find_first_holder(const struct gfs2_glock *gl)
	return NULL;
}

/**
 * find_first_strong_holder - find the first non-demoteable holder
 * @gl: the glock
 *
 * Find the first holder that doesn't have the HIF_MAY_DEMOTE flag set.
 */
static inline struct gfs2_holder *
find_first_strong_holder(struct gfs2_glock *gl)
{
	struct gfs2_holder *gh;

	list_for_each_entry(gh, &gl->gl_holders, gh_list) {
		if (!test_bit(HIF_HOLDER, &gh->gh_iflags))
			return NULL;
		if (!test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags))
			return gh;
	}
	return NULL;
}

/*
 * gfs2_instantiate - Call the glops instantiate function
 * @gh: The glock holder
@@ -540,9 +476,8 @@ int gfs2_instantiate(struct gfs2_holder *gh)
static int do_promote(struct gfs2_glock *gl)
{
	struct gfs2_holder *gh, *current_gh;
	bool incompat_holders_demoted = false;

	current_gh = find_first_strong_holder(gl);
	current_gh = find_first_holder(gl);
	list_for_each_entry(gh, &gl->gl_holders, gh_list) {
		if (test_bit(HIF_HOLDER, &gh->gh_iflags))
			continue;
@@ -561,11 +496,8 @@ static int do_promote(struct gfs2_glock *gl)
		set_bit(HIF_HOLDER, &gh->gh_iflags);
		trace_gfs2_promote(gh);
		gfs2_holder_wake(gh);
		if (!incompat_holders_demoted) {
		if (!current_gh)
			current_gh = gh;
			demote_incompat_holders(gl, current_gh);
			incompat_holders_demoted = true;
		}
	}
	return 0;
}
@@ -927,6 +859,48 @@ __acquires(&gl->gl_lockref.lock)
	return;
}

/**
 * glock_set_object - set the gl_object field of a glock
 * @gl: the glock
 * @object: the object
 */
void glock_set_object(struct gfs2_glock *gl, void *object)
{
	void *prev_object;

	spin_lock(&gl->gl_lockref.lock);
	prev_object = gl->gl_object;
	gl->gl_object = object;
	spin_unlock(&gl->gl_lockref.lock);
	if (gfs2_assert_warn(gl->gl_name.ln_sbd, prev_object == NULL)) {
		pr_warn("glock=%u/%llx\n",
			gl->gl_name.ln_type,
			(unsigned long long)gl->gl_name.ln_number);
		gfs2_dump_glock(NULL, gl, true);
	}
}

/**
 * glock_clear_object - clear the gl_object field of a glock
 * @gl: the glock
 */
void glock_clear_object(struct gfs2_glock *gl, void *object)
{
	void *prev_object;

	spin_lock(&gl->gl_lockref.lock);
	prev_object = gl->gl_object;
	gl->gl_object = NULL;
	spin_unlock(&gl->gl_lockref.lock);
	if (gfs2_assert_warn(gl->gl_name.ln_sbd,
			     prev_object == object || prev_object == NULL)) {
		pr_warn("glock=%u/%llx\n",
			gl->gl_name.ln_type,
			(unsigned long long)gl->gl_name.ln_number);
		gfs2_dump_glock(NULL, gl, true);
	}
}

void gfs2_inode_remember_delete(struct gfs2_glock *gl, u64 generation)
{
	struct gfs2_inode_lvb *ri = (void *)gl->gl_lksb.sb_lvbptr;
@@ -980,8 +954,6 @@ static bool gfs2_try_evict(struct gfs2_glock *gl)
		ip = NULL;
	spin_unlock(&gl->gl_lockref.lock);
	if (ip) {
		struct gfs2_glock *inode_gl = NULL;

		gl->gl_no_formal_ino = ip->i_no_formal_ino;
		set_bit(GIF_DEFERRED_DELETE, &ip->i_flags);
		d_prune_aliases(&ip->i_inode);
@@ -991,14 +963,14 @@ static bool gfs2_try_evict(struct gfs2_glock *gl)
		spin_lock(&gl->gl_lockref.lock);
		ip = gl->gl_object;
		if (ip) {
			inode_gl = ip->i_gl;
			lockref_get(&inode_gl->gl_lockref);
			clear_bit(GIF_DEFERRED_DELETE, &ip->i_flags);
			if (!igrab(&ip->i_inode))
				ip = NULL;
		}
		spin_unlock(&gl->gl_lockref.lock);
		if (inode_gl) {
			gfs2_glock_poke(inode_gl);
			gfs2_glock_put(inode_gl);
		if (ip) {
			gfs2_glock_poke(ip->i_gl);
			iput(&ip->i_inode);
		}
		evicted = !ip;
	}
@@ -1039,6 +1011,7 @@ static void delete_work_func(struct work_struct *work)
			if (gfs2_queue_delete_work(gl, 5 * HZ))
				return;
		}
		goto out;
	}

	inode = gfs2_lookup_by_inum(sdp, no_addr, gl->gl_no_formal_ino,
@@ -1051,6 +1024,7 @@ static void delete_work_func(struct work_struct *work)
		d_prune_aliases(inode);
		iput(inode);
	}
out:
	gfs2_glock_put(gl);
}

@@ -1256,13 +1230,12 @@ void __gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, u16 flags,
			struct gfs2_holder *gh, unsigned long ip)
{
	INIT_LIST_HEAD(&gh->gh_list);
	gh->gh_gl = gl;
	gh->gh_gl = gfs2_glock_hold(gl);
	gh->gh_ip = ip;
	gh->gh_owner_pid = get_pid(task_pid(current));
	gh->gh_state = state;
	gh->gh_flags = flags;
	gh->gh_iflags = 0;
	gfs2_glock_hold(gl);
}

/**
@@ -1496,7 +1469,7 @@ __acquires(&gl->gl_lockref.lock)
		if (test_bit(GLF_LOCK, &gl->gl_flags)) {
			struct gfs2_holder *current_gh;

			current_gh = find_first_strong_holder(gl);
			current_gh = find_first_holder(gl);
			try_futile = !may_grant(gl, current_gh, gh);
		}
		if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags))
@@ -1508,8 +1481,6 @@ __acquires(&gl->gl_lockref.lock)
			continue;
		if (gh->gh_gl->gl_ops->go_type == LM_TYPE_FLOCK)
			continue;
		if (test_bit(HIF_MAY_DEMOTE, &gh2->gh_iflags))
			continue;
		if (!pid_is_meaningful(gh2))
			continue;
		goto trap_recursive;
@@ -1619,35 +1590,9 @@ static inline bool needs_demote(struct gfs2_glock *gl)
static void __gfs2_glock_dq(struct gfs2_holder *gh)
{
	struct gfs2_glock *gl = gh->gh_gl;
	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
	unsigned delay = 0;
	int fast_path = 0;

	/*
	 * This while loop is similar to function demote_incompat_holders:
	 * If the glock is due to be demoted (which may be from another node
	 * or even if this holder is GL_NOCACHE), the weak holders are
	 * demoted as well, allowing the glock to be demoted.
	 */
	while (gh) {
		/*
		 * If we're in the process of file system withdraw, we cannot
		 * just dequeue any glocks until our journal is recovered, lest
		 * we introduce file system corruption. We need two exceptions
		 * to this rule: We need to allow unlocking of nondisk glocks
		 * and the glock for our own journal that needs recovery.
		 */
		if (test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags) &&
		    glock_blocked_by_withdraw(gl) &&
		    gh->gh_gl != sdp->sd_jinode_gl) {
			sdp->sd_glock_dqs_held++;
			spin_unlock(&gl->gl_lockref.lock);
			might_sleep();
			wait_on_bit(&sdp->sd_flags, SDF_WITHDRAW_RECOVERY,
				    TASK_UNINTERRUPTIBLE);
			spin_lock(&gl->gl_lockref.lock);
		}

	/*
	 * This holder should not be cached, so mark it for demote.
	 * Note: this should be done before the check for needs_demote
@@ -1667,21 +1612,6 @@ static void __gfs2_glock_dq(struct gfs2_holder *gh)
	if (!needs_demote(gl)) {
		if (list_empty(&gl->gl_holders))
			fast_path = 1;
			break;
		}
		/*
		 * If we have another strong holder (we cannot auto-demote)
		 * we are done. It keeps holding it until it is done.
		 */
		if (find_first_strong_holder(gl))
			break;

		/*
		 * If we have a weak holder at the head of the list, it
		 * (and all others like it) must be auto-demoted. If there
		 * are no more weak holders, we exit the while loop.
		 */
		gh = find_first_holder(gl);
	}

	if (!test_bit(GLF_LFLUSH, &gl->gl_flags) && demote_ok(gl))
@@ -1705,8 +1635,17 @@ static void __gfs2_glock_dq(struct gfs2_holder *gh)
void gfs2_glock_dq(struct gfs2_holder *gh)
{
	struct gfs2_glock *gl = gh->gh_gl;
	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;

	spin_lock(&gl->gl_lockref.lock);
	if (!gfs2_holder_queued(gh)) {
		/*
		 * May have already been dequeued because the locking request
		 * was GL_ASYNC and it has failed in the meantime.
		 */
		goto out;
	}

	if (list_is_first(&gh->gh_list, &gl->gl_holders) &&
	    !test_bit(HIF_HOLDER, &gh->gh_iflags)) {
		spin_unlock(&gl->gl_lockref.lock);
@@ -1715,7 +1654,26 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
		spin_lock(&gl->gl_lockref.lock);
	}

	/*
	 * If we're in the process of file system withdraw, we cannot just
	 * dequeue any glocks until our journal is recovered, lest we introduce
	 * file system corruption. We need two exceptions to this rule: We need
	 * to allow unlocking of nondisk glocks and the glock for our own
	 * journal that needs recovery.
	 */
	if (test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags) &&
	    glock_blocked_by_withdraw(gl) &&
	    gh->gh_gl != sdp->sd_jinode_gl) {
		sdp->sd_glock_dqs_held++;
		spin_unlock(&gl->gl_lockref.lock);
		might_sleep();
		wait_on_bit(&sdp->sd_flags, SDF_WITHDRAW_RECOVERY,
			    TASK_UNINTERRUPTIBLE);
		spin_lock(&gl->gl_lockref.lock);
	}

	__gfs2_glock_dq(gh);
out:
	spin_unlock(&gl->gl_lockref.lock);
}

@@ -1888,33 +1846,6 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
		if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
			delay = gl->gl_hold_time;
	}
	/*
	 * Note 1: We cannot call demote_incompat_holders from handle_callback
	 * or gfs2_set_demote due to recursion problems like: gfs2_glock_dq ->
	 * handle_callback -> demote_incompat_holders -> gfs2_glock_dq
	 * Plus, we only want to demote the holders if the request comes from
	 * a remote cluster node because local holder conflicts are resolved
	 * elsewhere.
	 *
	 * Note 2: if a remote node wants this glock in EX mode, lock_dlm will
	 * request that we set our state to UNLOCKED. Here we mock up a holder
	 * to make it look like someone wants the lock EX locally. Any SH
	 * and DF requests should be able to share the lock without demoting.
	 *
	 * Note 3: We only want to demote the demoteable holders when there
	 * are no more strong holders. The demoteable holders might as well
	 * keep the glock until the last strong holder is done with it.
	 */
	if (!find_first_strong_holder(gl)) {
		struct gfs2_holder mock_gh = {
			.gh_gl = gl,
			.gh_state = (state == LM_ST_UNLOCKED) ?
				    LM_ST_EXCLUSIVE : state,
			.gh_iflags = BIT(HIF_HOLDER)
		};

		demote_incompat_holders(gl, &mock_gh);
	}
	handle_callback(gl, state, delay, true);
	__gfs2_glock_queue_work(gl, delay);
	spin_unlock(&gl->gl_lockref.lock);
@@ -2306,8 +2237,6 @@ static const char *hflags2str(char *buf, u16 flags, unsigned long iflags)
		*p++ = 'H';
	if (test_bit(HIF_WAIT, &iflags))
		*p++ = 'W';
	if (test_bit(HIF_MAY_DEMOTE, &iflags))
		*p++ = 'D';
	if (flags & GL_SKIP)
		*p++ = 's';
	*p = 0;
+4 −61
Original line number Diff line number Diff line
@@ -156,8 +156,6 @@ static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *
	list_for_each_entry(gh, &gl->gl_holders, gh_list) {
		if (!test_bit(HIF_HOLDER, &gh->gh_iflags))
			break;
		if (test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags))
			continue;
		if (gh->gh_owner_pid == pid)
			goto out;
	}
@@ -196,7 +194,7 @@ static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl)
extern int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
			  const struct gfs2_glock_operations *glops,
			  int create, struct gfs2_glock **glp);
extern void gfs2_glock_hold(struct gfs2_glock *gl);
extern struct gfs2_glock *gfs2_glock_hold(struct gfs2_glock *gl);
extern void gfs2_glock_put(struct gfs2_glock *gl);
extern void gfs2_glock_queue_put(struct gfs2_glock *gl);

@@ -288,6 +286,9 @@ extern void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp);
extern void gfs2_register_debugfs(void);
extern void gfs2_unregister_debugfs(void);

extern void glock_set_object(struct gfs2_glock *gl, void *object);
extern void glock_clear_object(struct gfs2_glock *gl, void *object);

extern const struct lm_lockops gfs2_dlm_ops;

static inline void gfs2_holder_mark_uninitialized(struct gfs2_holder *gh)
@@ -305,64 +306,6 @@ static inline bool gfs2_holder_queued(struct gfs2_holder *gh)
	return !list_empty(&gh->gh_list);
}

/**
 * glock_set_object - set the gl_object field of a glock
 * @gl: the glock
 * @object: the object
 */
static inline void glock_set_object(struct gfs2_glock *gl, void *object)
{
	spin_lock(&gl->gl_lockref.lock);
	if (gfs2_assert_warn(gl->gl_name.ln_sbd, gl->gl_object == NULL))
		gfs2_dump_glock(NULL, gl, true);
	gl->gl_object = object;
	spin_unlock(&gl->gl_lockref.lock);
}

/**
 * glock_clear_object - clear the gl_object field of a glock
 * @gl: the glock
 * @object: the object
 *
 * I'd love to similarly add this:
 *	else if (gfs2_assert_warn(gl->gl_sbd, gl->gl_object == object))
 *		gfs2_dump_glock(NULL, gl, true);
 * Unfortunately, that's not possible because as soon as gfs2_delete_inode
 * frees the block in the rgrp, another process can reassign it for an I_NEW
 * inode in gfs2_create_inode because that calls new_inode, not gfs2_iget.
 * That means gfs2_delete_inode may subsequently try to call this function
 * for a glock that's already pointing to a brand new inode. If we clear the
 * new inode's gl_object, we'll introduce metadata corruption. Function
 * gfs2_delete_inode calls clear_inode which calls gfs2_clear_inode which also
 * tries to clear gl_object, so it's more than just gfs2_delete_inode.
 *
 */
static inline void glock_clear_object(struct gfs2_glock *gl, void *object)
{
	spin_lock(&gl->gl_lockref.lock);
	if (gl->gl_object == object)
		gl->gl_object = NULL;
	spin_unlock(&gl->gl_lockref.lock);
}

static inline void gfs2_holder_allow_demote(struct gfs2_holder *gh)
{
	struct gfs2_glock *gl = gh->gh_gl;

	spin_lock(&gl->gl_lockref.lock);
	set_bit(HIF_MAY_DEMOTE, &gh->gh_iflags);
	spin_unlock(&gl->gl_lockref.lock);
}

static inline void gfs2_holder_disallow_demote(struct gfs2_holder *gh)
{
	struct gfs2_glock *gl = gh->gh_gl;

	spin_lock(&gl->gl_lockref.lock);
	clear_bit(HIF_MAY_DEMOTE, &gh->gh_iflags);
	spin_unlock(&gl->gl_lockref.lock);
}

extern void gfs2_inode_remember_delete(struct gfs2_glock *gl, u64 generation);
extern bool gfs2_inode_already_deleted(struct gfs2_glock *gl, u64 generation);

Loading