Commit 6706415b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull gfs2 updates from Andreas Gruenbacher:
 "Fixes and cleanups:

   - Revise the glock reference counting model and LRU list handling to
     be more sensible

   - Several quota related fixes: clean up the quota code, add some
     missing locking, and work around the on-disk corruption that the
     reverted patch "gfs2: ignore negated quota changes" causes

   - Clean up the glock demote logic in glock_work_func()"

* tag 'gfs2-v6.10-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: (29 commits)
  gfs2: Clean up glock demote logic
  gfs2: Revert "check for no eligible quota changes"
  gfs2: Be more careful with the quota sync generation
  gfs2: Get rid of some unnecessary quota locking
  gfs2: Add some missing quota locking
  gfs2: Fold qd_fish into gfs2_quota_sync
  gfs2: quota need_sync cleanup
  gfs2: Fix and clean up function do_qc
  gfs2: Revert "Add quota_change type"
  gfs2: Revert "ignore negated quota changes"
  gfs2: qd_check_sync cleanups
  gfs2: Revert "introduce qd_bh_get_or_undo"
  gfs2: Check quota consistency on mount
  gfs2: Minor gfs2_quota_init error path cleanup
  gfs2: Get rid of demote_ok checks
  Revert "GFS2: Don't add all glocks to the lru"
  gfs2: Revise glock reference counting model
  gfs2: Switch to a per-filesystem glock workqueue
  gfs2: Report when glocks cannot be freed for a long time
  gfs2: gfs2_glock_get cleanup
  ...
parents f097ef0e f75efefb
Loading
Loading
Loading
Loading
+26 −29
Original line number Diff line number Diff line
@@ -41,11 +41,11 @@ operations. The glocks are basically a lock plus some routines which deal
with cache management. The following rules apply for the cache:

==========      ==============   ==========   ==========   ==============
Glock mode      Cache data   Cache Metadata   Dirty Data   Dirty Metadata
Glock mode      Cache Metadata   Cache data   Dirty Data   Dirty Metadata
==========      ==============   ==========   ==========   ==============
    UN                No            No            No            No
    DF                Yes           No            No            No
    SH                Yes           Yes           No            No
    DF             No              Yes            No            No
    EX                Yes           Yes           Yes           Yes
==========      ==============   ==========   ==========   ==============

@@ -55,23 +55,22 @@ all the modes. Only inode glocks use the DF mode for example.

Table of glock operations and per type constants:

=============      =============================================================
==============     =============================================================
Field              Purpose
=============      =============================================================
go_xmote_th        Called before remote state change (e.g. to sync dirty data)
==============     =============================================================
go_sync            Called before remote state change (e.g. to sync dirty data)
go_xmote_bh        Called after remote state change (e.g. to refill cache)
go_inval           Called if remote state change requires invalidating the cache
go_demote_ok       Returns boolean value of whether its ok to demote a glock
                   (e.g. checks timeout, and that there is no cached data)
go_lock            Called for the first local holder of a lock
go_unlock          Called on the final local unlock of a lock
go_instantiate     Called when a glock has been acquired
go_held            Called every time a glock holder is acquired
go_dump            Called to print content of object for debugfs file, or on
                   error to dump glock to the log.
go_type            The type of the glock, ``LM_TYPE_*``
go_callback	   Called if the DLM sends a callback to drop this lock
go_unlocked        Called when a glock is unlocked (dlm_unlock())
go_type            The type of the glock, ``LM_TYPE_*``
go_flags	   GLOF_ASPACE is set, if the glock has an address space
                   associated with it
=============      =============================================================
==============     =============================================================

The minimum hold time for each lock is the time after a remote lock
grant for which we ignore remote demote requests. This is in order to
@@ -82,26 +81,24 @@ to by multiple nodes. By delaying the demotion in response to a
remote callback, that gives the userspace program time to make
some progress before the pages are unmapped.

There is a plan to try and remove the go_lock and go_unlock callbacks
if possible, in order to try and speed up the fast path though the locking.
Also, eventually we hope to make the glock "EX" mode locally shared
such that any local locking will be done with the i_mutex as required
rather than via the glock.
Eventually, we hope to make the glock "EX" mode locally shared such that any
local locking will be done with the i_mutex as required rather than via the
glock.

Locking rules for glock operations:

=============    ======================    =============================
==============   ======================    =============================
Operation        GLF_LOCK bit lock held    gl_lockref.lock spinlock held
=============    ======================    =============================
go_xmote_th           Yes                       No
==============   ======================    =============================
go_sync               Yes                       No
go_xmote_bh           Yes                       No
go_inval              Yes                       No
go_demote_ok          Sometimes                 Yes
go_lock               Yes                       No
go_unlock             Yes                       No
go_instantiate        No                        No
go_held               No                        No
go_dump               Sometimes                 Yes
go_callback           Sometimes (N/A)           Yes
=============    ======================    =============================
go_unlocked           Yes                       No
==============   ======================    =============================

.. Note::

+99 −128
Original line number Diff line number Diff line
@@ -61,12 +61,10 @@ struct gfs2_glock_iter {
typedef void (*glock_examiner) (struct gfs2_glock * gl);

static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target);
static void __gfs2_glock_dq(struct gfs2_holder *gh);
static void handle_callback(struct gfs2_glock *gl, unsigned int state,
static void request_demote(struct gfs2_glock *gl, unsigned int state,
			   unsigned long delay, bool remote);

static struct dentry *gfs2_root;
static struct workqueue_struct *glock_workqueue;
static LIST_HEAD(lru_list);
static atomic_t lru_count = ATOMIC_INIT(0);
static DEFINE_SPINLOCK(lru_lock);
@@ -218,34 +216,9 @@ struct gfs2_glock *gfs2_glock_hold(struct gfs2_glock *gl)
	return gl;
}

/**
 * demote_ok - Check to see if it's ok to unlock a glock
 * @gl: the glock
 *
 * Returns: 1 if it's ok
 */

static int demote_ok(const struct gfs2_glock *gl)
static void gfs2_glock_add_to_lru(struct gfs2_glock *gl)
{
	const struct gfs2_glock_operations *glops = gl->gl_ops;

	if (gl->gl_state == LM_ST_UNLOCKED)
		return 0;
	if (!list_empty(&gl->gl_holders))
		return 0;
	if (glops->go_demote_ok)
		return glops->go_demote_ok(gl);
	return 1;
}


void gfs2_glock_add_to_lru(struct gfs2_glock *gl)
{
	if (!(gl->gl_ops->go_flags & GLOF_LRU))
		return;

	spin_lock(&lru_lock);

	list_move_tail(&gl->gl_lru, &lru_list);

	if (!test_bit(GLF_LRU, &gl->gl_flags)) {
@@ -258,9 +231,6 @@ void gfs2_glock_add_to_lru(struct gfs2_glock *gl)

static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl)
{
	if (!(gl->gl_ops->go_flags & GLOF_LRU))
		return;

	spin_lock(&lru_lock);
	if (test_bit(GLF_LRU, &gl->gl_flags)) {
		list_del_init(&gl->gl_lru);
@@ -275,7 +245,9 @@ static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl)
 * work queue.
 */
static void gfs2_glock_queue_work(struct gfs2_glock *gl, unsigned long delay) {
	if (!queue_delayed_work(glock_workqueue, &gl->gl_work, delay)) {
	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;

	if (!queue_delayed_work(sdp->sd_glock_wq, &gl->gl_work, delay)) {
		/*
		 * We are holding the lockref spinlock, and the work was still
		 * queued above.  The queued work (glock_work_func) takes that
@@ -305,6 +277,20 @@ static void __gfs2_glock_put(struct gfs2_glock *gl)
	sdp->sd_lockstruct.ls_ops->lm_put_lock(gl);
}

static bool __gfs2_glock_put_or_lock(struct gfs2_glock *gl)
{
	if (lockref_put_or_lock(&gl->gl_lockref))
		return true;
	GLOCK_BUG_ON(gl, gl->gl_lockref.count != 1);
	if (gl->gl_state != LM_ST_UNLOCKED) {
		gl->gl_lockref.count--;
		gfs2_glock_add_to_lru(gl);
		spin_unlock(&gl->gl_lockref.lock);
		return true;
	}
	return false;
}

/**
 * gfs2_glock_put() - Decrement reference count on glock
 * @gl: The glock to put
@@ -313,7 +299,7 @@ static void __gfs2_glock_put(struct gfs2_glock *gl)

void gfs2_glock_put(struct gfs2_glock *gl)
{
	if (lockref_put_or_lock(&gl->gl_lockref))
	if (__gfs2_glock_put_or_lock(gl))
		return;

	__gfs2_glock_put(gl);
@@ -328,10 +314,9 @@ void gfs2_glock_put(struct gfs2_glock *gl)
 */
void gfs2_glock_put_async(struct gfs2_glock *gl)
{
	if (lockref_put_or_lock(&gl->gl_lockref))
	if (__gfs2_glock_put_or_lock(gl))
		return;

	GLOCK_BUG_ON(gl, gl->gl_lockref.count != 1);
	gfs2_glock_queue_work(gl, 0);
	spin_unlock(&gl->gl_lockref.lock);
}
@@ -570,18 +555,6 @@ static inline struct gfs2_holder *find_last_waiter(const struct gfs2_glock *gl)

static void state_change(struct gfs2_glock *gl, unsigned int new_state)
{
	int held1, held2;

	held1 = (gl->gl_state != LM_ST_UNLOCKED);
	held2 = (new_state != LM_ST_UNLOCKED);

	if (held1 != held2) {
		GLOCK_BUG_ON(gl, __lockref_is_dead(&gl->gl_lockref));
		if (held2)
			gl->gl_lockref.count++;
		else
			gl->gl_lockref.count--;
	}
	if (new_state != gl->gl_target)
		/* shorten our minimum hold time */
		gl->gl_hold_time = max(gl->gl_hold_time - GL_GLOCK_HOLD_DECR,
@@ -812,7 +785,7 @@ __acquires(&gl->gl_lockref.lock)
	    (target != LM_ST_UNLOCKED ||
	     test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags))) {
		if (!is_system_glock(gl)) {
			handle_callback(gl, LM_ST_UNLOCKED, 0, false); /* sets demote */
			request_demote(gl, LM_ST_UNLOCKED, 0, false);
			/*
			 * Ordinarily, we would call dlm and its callback would call
			 * finish_xmote, which would call state_change() to the new state.
@@ -910,7 +883,6 @@ __acquires(&gl->gl_lockref.lock)
out_unlock:
	clear_bit(GLF_LOCK, &gl->gl_flags);
	smp_mb__after_atomic();
	return;
}

/**
@@ -1111,19 +1083,21 @@ static void glock_work_func(struct work_struct *work)
	unsigned int drop_refs = 1;

	spin_lock(&gl->gl_lockref.lock);
	if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags)) {
		clear_bit(GLF_REPLY_PENDING, &gl->gl_flags);
	if (test_bit(GLF_HAVE_REPLY, &gl->gl_flags)) {
		clear_bit(GLF_HAVE_REPLY, &gl->gl_flags);
		finish_xmote(gl, gl->gl_reply);
		drop_refs++;
	}
	if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
	    gl->gl_state != LM_ST_UNLOCKED &&
	    gl->gl_demote_state != LM_ST_EXCLUSIVE) {
		if (gl->gl_name.ln_type == LM_TYPE_INODE) {
			unsigned long holdtime, now = jiffies;

			holdtime = gl->gl_tchange + gl->gl_hold_time;
			if (time_before(now, holdtime))
				delay = holdtime - now;
		}

		if (!delay) {
			clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags);
@@ -1134,21 +1108,19 @@ static void glock_work_func(struct work_struct *work)
	if (delay) {
		/* Keep one glock reference for the work we requeue. */
		drop_refs--;
		if (gl->gl_name.ln_type != LM_TYPE_INODE)
			delay = 0;
		gfs2_glock_queue_work(gl, delay);
	}

	/*
	 * Drop the remaining glock references manually here. (Mind that
	 * gfs2_glock_queue_work depends on the lockref spinlock begin held
	 * here as well.)
	 */
	/* Drop the remaining glock references manually. */
	GLOCK_BUG_ON(gl, gl->gl_lockref.count < drop_refs);
	gl->gl_lockref.count -= drop_refs;
	if (!gl->gl_lockref.count) {
		if (gl->gl_state == LM_ST_UNLOCKED) {
			__gfs2_glock_put(gl);
			return;
		}
		gfs2_glock_add_to_lru(gl);
	}
	spin_unlock(&gl->gl_lockref.lock);
}

@@ -1183,6 +1155,8 @@ static struct gfs2_glock *find_insert_glock(struct lm_lockname *name,
out:
	rcu_read_unlock();
	finish_wait(wq, &wait.wait);
	if (gl)
		gfs2_glock_remove_from_lru(gl);
	return gl;
}

@@ -1209,13 +1183,10 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
				    .ln_sbd = sdp };
	struct gfs2_glock *gl, *tmp;
	struct address_space *mapping;
	int ret = 0;

	gl = find_insert_glock(&name, NULL);
	if (gl) {
		*glp = gl;
		return 0;
	}
	if (gl)
		goto found;
	if (!create)
		return -ENOENT;

@@ -1243,7 +1214,9 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,

	atomic_inc(&sdp->sd_glock_disposal);
	gl->gl_node.next = NULL;
	gl->gl_flags = glops->go_instantiate ? BIT(GLF_INSTANTIATE_NEEDED) : 0;
	gl->gl_flags = BIT(GLF_INITIAL);
	if (glops->go_instantiate)
		gl->gl_flags |= BIT(GLF_INSTANTIATE_NEEDED);
	gl->gl_name = name;
	lockdep_set_subclass(&gl->gl_lockref.lock, glops->go_subclass);
	gl->gl_lockref.count = 1;
@@ -1275,23 +1248,19 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
	}

	tmp = find_insert_glock(&name, gl);
	if (!tmp) {
		*glp = gl;
		goto out;
	}
	if (IS_ERR(tmp)) {
		ret = PTR_ERR(tmp);
		goto out_free;
	}
	*glp = tmp;

out_free:
	if (tmp) {
		gfs2_glock_dealloc(&gl->gl_rcu);
		if (atomic_dec_and_test(&sdp->sd_glock_disposal))
			wake_up(&sdp->sd_kill_wait);

out:
	return ret;
		if (IS_ERR(tmp))
			return PTR_ERR(tmp);
		gl = tmp;
	}

found:
	*glp = gl;
	return 0;
}

/**
@@ -1461,7 +1430,7 @@ int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs)
}

/**
 * handle_callback - process a demote request
 * request_demote - process a demote request
 * @gl: the glock
 * @state: the state the caller wants us to change to
 * @delay: zero to demote immediately; otherwise pending demote
@@ -1471,7 +1440,7 @@ int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs)
 * practise: LM_ST_SHARED and LM_ST_UNLOCKED
 */

static void handle_callback(struct gfs2_glock *gl, unsigned int state,
static void request_demote(struct gfs2_glock *gl, unsigned int state,
			   unsigned long delay, bool remote)
{
	if (delay)
@@ -1636,15 +1605,12 @@ int gfs2_glock_nq(struct gfs2_holder *gh)
		return error;
	}

	if (test_bit(GLF_LRU, &gl->gl_flags))
		gfs2_glock_remove_from_lru(gl);

	gh->gh_error = 0;
	spin_lock(&gl->gl_lockref.lock);
	add_to_queue(gh);
	if (unlikely((LM_FLAG_NOEXP & gh->gh_flags) &&
		     test_and_clear_bit(GLF_FROZEN, &gl->gl_flags))) {
		set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
		     test_and_clear_bit(GLF_HAVE_FROZEN_REPLY, &gl->gl_flags))) {
		set_bit(GLF_HAVE_REPLY, &gl->gl_flags);
		gl->gl_lockref.count++;
		gfs2_glock_queue_work(gl, 0);
	}
@@ -1688,7 +1654,7 @@ static void __gfs2_glock_dq(struct gfs2_holder *gh)
	 * below.
	 */
	if (gh->gh_flags & GL_NOCACHE)
		handle_callback(gl, LM_ST_UNLOCKED, 0, false);
		request_demote(gl, LM_ST_UNLOCKED, 0, false);

	list_del_init(&gh->gh_list);
	clear_bit(HIF_HOLDER, &gh->gh_iflags);
@@ -1703,9 +1669,6 @@ static void __gfs2_glock_dq(struct gfs2_holder *gh)
			fast_path = 1;
	}

	if (!test_bit(GLF_LFLUSH, &gl->gl_flags) && demote_ok(gl))
		gfs2_glock_add_to_lru(gl);

	if (unlikely(!fast_path)) {
		gl->gl_lockref.count++;
		if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
@@ -1932,10 +1895,10 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
	    gl->gl_name.ln_type == LM_TYPE_INODE) {
		if (time_before(now, holdtime))
			delay = holdtime - now;
		if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
		if (test_bit(GLF_HAVE_REPLY, &gl->gl_flags))
			delay = gl->gl_hold_time;
	}
	handle_callback(gl, state, delay, true);
	request_demote(gl, state, delay, true);
	gfs2_glock_queue_work(gl, delay);
	spin_unlock(&gl->gl_lockref.lock);
}
@@ -1988,14 +1951,14 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret)

	if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_recover_flags))) {
		if (gfs2_should_freeze(gl)) {
			set_bit(GLF_FROZEN, &gl->gl_flags);
			set_bit(GLF_HAVE_FROZEN_REPLY, &gl->gl_flags);
			spin_unlock(&gl->gl_lockref.lock);
			return;
		}
	}

	gl->gl_lockref.count++;
	set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
	set_bit(GLF_HAVE_REPLY, &gl->gl_flags);
	gfs2_glock_queue_work(gl, 0);
	spin_unlock(&gl->gl_lockref.lock);
}
@@ -2018,10 +1981,12 @@ static int glock_cmp(void *priv, const struct list_head *a,

static bool can_free_glock(struct gfs2_glock *gl)
{
	bool held = gl->gl_state != LM_ST_UNLOCKED;
	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;

	return !test_bit(GLF_LOCK, &gl->gl_flags) &&
	       gl->gl_lockref.count == held;
	       !gl->gl_lockref.count &&
	       (!test_bit(GLF_LFLUSH, &gl->gl_flags) ||
		test_bit(SDF_KILL, &sdp->sd_flags));
}

/**
@@ -2063,8 +2028,8 @@ __acquires(&lru_lock)
		clear_bit(GLF_LRU, &gl->gl_flags);
		freed++;
		gl->gl_lockref.count++;
		if (demote_ok(gl))
			handle_callback(gl, LM_ST_UNLOCKED, 0, false);
		if (gl->gl_state != LM_ST_UNLOCKED)
			request_demote(gl, LM_ST_UNLOCKED, 0, false);
		gfs2_glock_queue_work(gl, 0);
		spin_unlock(&gl->gl_lockref.lock);
		cond_resched_lock(&lru_lock);
@@ -2182,13 +2147,14 @@ void gfs2_flush_delete_work(struct gfs2_sbd *sdp)

static void thaw_glock(struct gfs2_glock *gl)
{
	if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags))
	if (!test_and_clear_bit(GLF_HAVE_FROZEN_REPLY, &gl->gl_flags))
		return;
	if (!lockref_get_not_dead(&gl->gl_lockref))
		return;

	gfs2_glock_remove_from_lru(gl);
	spin_lock(&gl->gl_lockref.lock);
	set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
	set_bit(GLF_HAVE_REPLY, &gl->gl_flags);
	gfs2_glock_queue_work(gl, 0);
	spin_unlock(&gl->gl_lockref.lock);
}
@@ -2207,7 +2173,7 @@ static void clear_glock(struct gfs2_glock *gl)
	if (!__lockref_is_dead(&gl->gl_lockref)) {
		gl->gl_lockref.count++;
		if (gl->gl_state != LM_ST_UNLOCKED)
			handle_callback(gl, LM_ST_UNLOCKED, 0, false);
			request_demote(gl, LM_ST_UNLOCKED, 0, false);
		gfs2_glock_queue_work(gl, 0);
	}
	spin_unlock(&gl->gl_lockref.lock);
@@ -2259,16 +2225,30 @@ void gfs2_gl_dq_holders(struct gfs2_sbd *sdp)

void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
{
	unsigned long start = jiffies;
	bool timed_out = false;

	set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags);
	flush_workqueue(glock_workqueue);
	flush_workqueue(sdp->sd_glock_wq);
	glock_hash_walk(clear_glock, sdp);
	flush_workqueue(glock_workqueue);
	flush_workqueue(sdp->sd_glock_wq);

	while (!timed_out) {
		wait_event_timeout(sdp->sd_kill_wait,
			   atomic_read(&sdp->sd_glock_disposal) == 0,
			   HZ * 600);
				   !atomic_read(&sdp->sd_glock_disposal),
				   HZ * 60);
		if (!atomic_read(&sdp->sd_glock_disposal))
			break;
		timed_out = time_after(jiffies, start + (HZ * 600));
		fs_warn(sdp, "%u glocks left after %u seconds%s\n",
			atomic_read(&sdp->sd_glock_disposal),
			jiffies_to_msecs(jiffies - start) / 1000,
			timed_out ? ":" : "; still waiting");
	}
	gfs2_lm_unmount(sdp);
	gfs2_free_dead_glocks(sdp);
	glock_hash_walk(dump_glock_func, sdp);
	destroy_workqueue(sdp->sd_glock_wq);
}

static const char *state2str(unsigned state)
@@ -2366,11 +2346,11 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
		*p++ = 'f';
	if (test_bit(GLF_INVALIDATE_IN_PROGRESS, gflags))
		*p++ = 'i';
	if (test_bit(GLF_REPLY_PENDING, gflags))
	if (test_bit(GLF_HAVE_REPLY, gflags))
		*p++ = 'r';
	if (test_bit(GLF_INITIAL, gflags))
		*p++ = 'I';
	if (test_bit(GLF_FROZEN, gflags))
		*p++ = 'a';
	if (test_bit(GLF_HAVE_FROZEN_REPLY, gflags))
		*p++ = 'F';
	if (!list_empty(&gl->gl_holders))
		*p++ = 'q';
@@ -2380,7 +2360,7 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
		*p++ = 'o';
	if (test_bit(GLF_BLOCKING, gflags))
		*p++ = 'b';
	if (test_bit(GLF_FREEING, gflags))
	if (test_bit(GLF_UNLOCKED, gflags))
		*p++ = 'x';
	if (test_bit(GLF_INSTANTIATE_NEEDED, gflags))
		*p++ = 'n';
@@ -2533,16 +2513,8 @@ int __init gfs2_glock_init(void)
	if (ret < 0)
		return ret;

	glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
					  WQ_HIGHPRI | WQ_FREEZABLE, 0);
	if (!glock_workqueue) {
		rhashtable_destroy(&gl_hash_table);
		return -ENOMEM;
	}

	glock_shrinker = shrinker_alloc(0, "gfs2-glock");
	if (!glock_shrinker) {
		destroy_workqueue(glock_workqueue);
		rhashtable_destroy(&gl_hash_table);
		return -ENOMEM;
	}
@@ -2562,7 +2534,6 @@ void gfs2_glock_exit(void)
{
	shrinker_free(glock_shrinker);
	rhashtable_destroy(&gl_hash_table);
	destroy_workqueue(glock_workqueue);
}

static void gfs2_glock_iter_next(struct gfs2_glock_iter *gi, loff_t n)
+0 −1
Original line number Diff line number Diff line
@@ -250,7 +250,6 @@ void gfs2_flush_delete_work(struct gfs2_sbd *sdp);
void gfs2_gl_hash_clear(struct gfs2_sbd *sdp);
void gfs2_gl_dq_holders(struct gfs2_sbd *sdp);
void gfs2_glock_thaw(struct gfs2_sbd *sdp);
void gfs2_glock_add_to_lru(struct gfs2_glock *gl);
void gfs2_glock_free(struct gfs2_glock *gl);
void gfs2_glock_free_later(struct gfs2_glock *gl);

+12 −30
Original line number Diff line number Diff line
@@ -385,23 +385,6 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
	gfs2_clear_glop_pending(ip);
}

/**
 * inode_go_demote_ok - Check to see if it's ok to unlock an inode glock
 * @gl: the glock
 *
 * Returns: 1 if it's ok
 */

static int inode_go_demote_ok(const struct gfs2_glock *gl)
{
	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;

	if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object)
		return 0;

	return 1;
}

static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
{
	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
@@ -648,21 +631,21 @@ static void iopen_go_callback(struct gfs2_glock *gl, bool remote)
}

/**
 * inode_go_free - wake up anyone waiting for dlm's unlock ast to free it
 * @gl: glock being freed
 * inode_go_unlocked - wake up anyone waiting for dlm's unlock ast
 * @gl: glock being unlocked
 *
 * For now, this is only used for the journal inode glock. In withdraw
 * situations, we need to wait for the glock to be freed so that we know
 * situations, we need to wait for the glock to be unlocked so that we know
 * other nodes may proceed with recovery / journal replay.
 */
static void inode_go_free(struct gfs2_glock *gl)
static void inode_go_unlocked(struct gfs2_glock *gl)
{
	/* Note that we cannot reference gl_object because it's already set
	 * to NULL by this point in its lifecycle. */
	if (!test_bit(GLF_FREEING, &gl->gl_flags))
	if (!test_bit(GLF_UNLOCKED, &gl->gl_flags))
		return;
	clear_bit_unlock(GLF_FREEING, &gl->gl_flags);
	wake_up_bit(&gl->gl_flags, GLF_FREEING);
	clear_bit_unlock(GLF_UNLOCKED, &gl->gl_flags);
	wake_up_bit(&gl->gl_flags, GLF_UNLOCKED);
}

/**
@@ -722,13 +705,12 @@ const struct gfs2_glock_operations gfs2_meta_glops = {
const struct gfs2_glock_operations gfs2_inode_glops = {
	.go_sync = inode_go_sync,
	.go_inval = inode_go_inval,
	.go_demote_ok = inode_go_demote_ok,
	.go_instantiate = inode_go_instantiate,
	.go_held = inode_go_held,
	.go_dump = inode_go_dump,
	.go_type = LM_TYPE_INODE,
	.go_flags = GLOF_ASPACE | GLOF_LRU | GLOF_LVB,
	.go_free = inode_go_free,
	.go_flags = GLOF_ASPACE | GLOF_LVB,
	.go_unlocked = inode_go_unlocked,
};

const struct gfs2_glock_operations gfs2_rgrp_glops = {
@@ -751,13 +733,13 @@ const struct gfs2_glock_operations gfs2_iopen_glops = {
	.go_type = LM_TYPE_IOPEN,
	.go_callback = iopen_go_callback,
	.go_dump = inode_go_dump,
	.go_flags = GLOF_LRU | GLOF_NONDISK,
	.go_flags = GLOF_NONDISK,
	.go_subclass = 1,
};

const struct gfs2_glock_operations gfs2_flock_glops = {
	.go_type = LM_TYPE_FLOCK,
	.go_flags = GLOF_LRU | GLOF_NONDISK,
	.go_flags = GLOF_NONDISK,
};

const struct gfs2_glock_operations gfs2_nondisk_glops = {
@@ -768,7 +750,7 @@ const struct gfs2_glock_operations gfs2_nondisk_glops = {

const struct gfs2_glock_operations gfs2_quota_glops = {
	.go_type = LM_TYPE_QUOTA,
	.go_flags = GLOF_LVB | GLOF_LRU | GLOF_NONDISK,
	.go_flags = GLOF_LVB | GLOF_NONDISK,
};

const struct gfs2_glock_operations gfs2_journal_glops = {
+5 −7
Original line number Diff line number Diff line
@@ -218,19 +218,17 @@ struct gfs2_glock_operations {
	int (*go_sync) (struct gfs2_glock *gl);
	int (*go_xmote_bh)(struct gfs2_glock *gl);
	void (*go_inval) (struct gfs2_glock *gl, int flags);
	int (*go_demote_ok) (const struct gfs2_glock *gl);
	int (*go_instantiate) (struct gfs2_glock *gl);
	int (*go_held)(struct gfs2_holder *gh);
	void (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl,
			const char *fs_id_buf);
	void (*go_callback)(struct gfs2_glock *gl, bool remote);
	void (*go_free)(struct gfs2_glock *gl);
	void (*go_unlocked)(struct gfs2_glock *gl);
	const int go_subclass;
	const int go_type;
	const unsigned long go_flags;
#define GLOF_ASPACE 1 /* address space attached */
#define GLOF_LVB    2 /* Lock Value Block attached */
#define GLOF_LRU    4 /* LRU managed */
#define GLOF_NONDISK   8 /* not I/O related */
};

@@ -322,14 +320,14 @@ enum {
	GLF_DIRTY			= 6,
	GLF_LFLUSH			= 7,
	GLF_INVALIDATE_IN_PROGRESS	= 8,
	GLF_REPLY_PENDING		= 9,
	GLF_HAVE_REPLY			= 9,
	GLF_INITIAL			= 10,
	GLF_FROZEN			= 11,
	GLF_HAVE_FROZEN_REPLY		= 11,
	GLF_INSTANTIATE_IN_PROG		= 12, /* instantiate happening now */
	GLF_LRU				= 13,
	GLF_OBJECT			= 14, /* Used only for tracing */
	GLF_BLOCKING			= 15,
	GLF_FREEING			= 16, /* Wait for glock to be freed */
	GLF_UNLOCKED			= 16, /* Wait for glock to be unlocked */
	GLF_TRY_TO_EVICT		= 17, /* iopen glocks only */
	GLF_VERIFY_EVICT		= 18, /* iopen glocks only */
};
@@ -772,6 +770,7 @@ struct gfs2_sbd {

	/* Workqueue stuff */

	struct workqueue_struct *sd_glock_wq;
	struct workqueue_struct *sd_delete_wq;

	/* Daemon stuff */
@@ -783,7 +782,6 @@ struct gfs2_sbd {

	struct list_head sd_quota_list;
	atomic_t sd_quota_count;
	struct mutex sd_quota_mutex;
	struct mutex sd_quota_sync_mutex;
	wait_queue_head_t sd_quota_wait;

Loading