mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'gfs2-v6.5-rc5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2
Pull gfs2 updates from Andreas Gruenbacher: - Fix a glock state (non-)transition bug when a dlm request times out and is canceled, and we have locking requests that can now be granted immediately - Various fixes and cleanups in how the logd and quotad daemons are woken up and terminated - Fix several bugs in the quota data reference counting and shrinking. Free quota data objects synchronously in put_super() instead of letting call_rcu() run wild - Make sure not to deallocate quota data during a withdraw; rather, defer quota data deallocation to put_super(). Withdraws can happen in contexts in which callers on the stack are holding quota data references - Many minor quota fixes and cleanups by Bob - Update the the mailing list address for gfs2 and dlm. (It's the same list for both and we are moving it to gfs2@lists.linux.dev) - Various other minor cleanups * tag 'gfs2-v6.5-rc5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: (51 commits) MAINTAINERS: Update dlm mailing list MAINTAINERS: Update gfs2 mailing list gfs2: change qd_slot_count to qd_slot_ref gfs2: check for no eligible quota changes gfs2: Remove useless assignment gfs2: simplify slot_get gfs2: Simplify qd2offset gfs2: introduce qd_bh_get_or_undo gfs2: Remove quota allocation info from quota file gfs2: use constant for array size gfs2: Set qd_sync_gen in do_sync gfs2: Remove useless err set gfs2: Small gfs2_quota_lock cleanup gfs2: move qdsb_put and reduce redundancy gfs2: improvements to sysfs status gfs2: Don't try to sync non-changes gfs2: Simplify function need_sync gfs2: remove unneeded pg_oflow variable gfs2: remove unneeded variable done gfs2: pass sdp to gfs2_write_buf_to_page ...
This commit is contained in:
@@ -20,8 +20,7 @@ The gl_holders list contains all the queued lock requests (not
|
||||
just the holders) associated with the glock. If there are any
|
||||
held locks, then they will be contiguous entries at the head
|
||||
of the list. Locks are granted in strictly the order that they
|
||||
are queued, except for those marked LM_FLAG_PRIORITY which are
|
||||
used only during recovery, and even then only for journal locks.
|
||||
are queued.
|
||||
|
||||
There are three lock states that users of the glock layer can request,
|
||||
namely shared (SH), deferred (DF) and exclusive (EX). Those translate
|
||||
|
||||
+2
-2
@@ -6118,7 +6118,7 @@ F: include/video/udlfb.h
|
||||
DISTRIBUTED LOCK MANAGER (DLM)
|
||||
M: Christine Caulfield <ccaulfie@redhat.com>
|
||||
M: David Teigland <teigland@redhat.com>
|
||||
L: cluster-devel@redhat.com
|
||||
L: gfs2@lists.linux.dev
|
||||
S: Supported
|
||||
W: http://sources.redhat.com/cluster/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm.git
|
||||
@@ -8774,7 +8774,7 @@ F: scripts/get_maintainer.pl
|
||||
GFS2 FILE SYSTEM
|
||||
M: Bob Peterson <rpeterso@redhat.com>
|
||||
M: Andreas Gruenbacher <agruenba@redhat.com>
|
||||
L: cluster-devel@redhat.com
|
||||
L: gfs2@lists.linux.dev
|
||||
S: Supported
|
||||
B: https://bugzilla.kernel.org/enter_bug.cgi?product=File%20System&component=gfs2
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git
|
||||
|
||||
+3
-4
@@ -183,13 +183,13 @@ static int gfs2_writepages(struct address_space *mapping,
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Even if we didn't write any pages here, we might still be holding
|
||||
* Even if we didn't write enough pages here, we might still be holding
|
||||
* dirty pages in the ail. We forcibly flush the ail because we don't
|
||||
* want balance_dirty_pages() to loop indefinitely trying to write out
|
||||
* pages held in the ail that it can't find.
|
||||
*/
|
||||
ret = iomap_writepages(mapping, wbc, &wpc, &gfs2_writeback_ops);
|
||||
if (ret == 0)
|
||||
if (ret == 0 && wbc->nr_to_write > 0)
|
||||
set_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags);
|
||||
return ret;
|
||||
}
|
||||
@@ -272,8 +272,7 @@ continue_unlock:
|
||||
* not be suitable for data integrity
|
||||
* writeout).
|
||||
*/
|
||||
*done_index = folio->index +
|
||||
folio_nr_pages(folio);
|
||||
*done_index = folio_next_index(folio);
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
+1
-1
@@ -161,7 +161,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip)
|
||||
int error;
|
||||
|
||||
down_write(&ip->i_rw_mutex);
|
||||
page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS);
|
||||
page = grab_cache_page(inode->i_mapping, 0);
|
||||
error = -ENOMEM;
|
||||
if (!page)
|
||||
goto out;
|
||||
|
||||
+19
-28
@@ -176,7 +176,7 @@ void gfs2_glock_free(struct gfs2_glock *gl)
|
||||
wake_up_glock(gl);
|
||||
call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
|
||||
if (atomic_dec_and_test(&sdp->sd_glock_disposal))
|
||||
wake_up(&sdp->sd_glock_wait);
|
||||
wake_up(&sdp->sd_kill_wait);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -468,10 +468,10 @@ done:
|
||||
* do_promote - promote as many requests as possible on the current queue
|
||||
* @gl: The glock
|
||||
*
|
||||
* Returns: 1 if there is a blocked holder at the head of the list
|
||||
* Returns true on success (i.e., progress was made or there are no waiters).
|
||||
*/
|
||||
|
||||
static int do_promote(struct gfs2_glock *gl)
|
||||
static bool do_promote(struct gfs2_glock *gl)
|
||||
{
|
||||
struct gfs2_holder *gh, *current_gh;
|
||||
|
||||
@@ -484,10 +484,10 @@ static int do_promote(struct gfs2_glock *gl)
|
||||
* If we get here, it means we may not grant this
|
||||
* holder for some reason. If this holder is at the
|
||||
* head of the list, it means we have a blocked holder
|
||||
* at the head, so return 1.
|
||||
* at the head, so return false.
|
||||
*/
|
||||
if (list_is_first(&gh->gh_list, &gl->gl_holders))
|
||||
return 1;
|
||||
return false;
|
||||
do_error(gl, 0);
|
||||
break;
|
||||
}
|
||||
@@ -497,7 +497,7 @@ static int do_promote(struct gfs2_glock *gl)
|
||||
if (!current_gh)
|
||||
current_gh = gh;
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -591,10 +591,11 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
|
||||
if (gh && !test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)) {
|
||||
/* move to back of queue and try next entry */
|
||||
if (ret & LM_OUT_CANCELED) {
|
||||
if ((gh->gh_flags & LM_FLAG_PRIORITY) == 0)
|
||||
list_move_tail(&gh->gh_list, &gl->gl_holders);
|
||||
list_move_tail(&gh->gh_list, &gl->gl_holders);
|
||||
gh = find_first_waiter(gl);
|
||||
gl->gl_target = gh->gh_state;
|
||||
if (do_promote(gl))
|
||||
goto out;
|
||||
goto retry;
|
||||
}
|
||||
/* Some error or failed "try lock" - report it */
|
||||
@@ -679,8 +680,7 @@ __acquires(&gl->gl_lockref.lock)
|
||||
gh && !(gh->gh_flags & LM_FLAG_NOEXP))
|
||||
goto skip_inval;
|
||||
|
||||
lck_flags &= (LM_FLAG_TRY | LM_FLAG_TRY_1CB | LM_FLAG_NOEXP |
|
||||
LM_FLAG_PRIORITY);
|
||||
lck_flags &= (LM_FLAG_TRY | LM_FLAG_TRY_1CB | LM_FLAG_NOEXP);
|
||||
GLOCK_BUG_ON(gl, gl->gl_state == target);
|
||||
GLOCK_BUG_ON(gl, gl->gl_state == gl->gl_target);
|
||||
if ((target == LM_ST_UNLOCKED || target == LM_ST_DEFERRED) &&
|
||||
@@ -834,7 +834,7 @@ __acquires(&gl->gl_lockref.lock)
|
||||
} else {
|
||||
if (test_bit(GLF_DEMOTE, &gl->gl_flags))
|
||||
gfs2_demote_wake(gl);
|
||||
if (do_promote(gl) == 0)
|
||||
if (do_promote(gl))
|
||||
goto out_unlock;
|
||||
gh = find_first_waiter(gl);
|
||||
gl->gl_target = gh->gh_state;
|
||||
@@ -1022,7 +1022,7 @@ static void delete_work_func(struct work_struct *work)
|
||||
* step entirely.
|
||||
*/
|
||||
if (gfs2_try_evict(gl)) {
|
||||
if (test_bit(SDF_DEACTIVATING, &sdp->sd_flags))
|
||||
if (test_bit(SDF_KILL, &sdp->sd_flags))
|
||||
goto out;
|
||||
if (gfs2_queue_verify_evict(gl))
|
||||
return;
|
||||
@@ -1035,7 +1035,7 @@ static void delete_work_func(struct work_struct *work)
|
||||
GFS2_BLKST_UNLINKED);
|
||||
if (IS_ERR(inode)) {
|
||||
if (PTR_ERR(inode) == -EAGAIN &&
|
||||
!test_bit(SDF_DEACTIVATING, &sdp->sd_flags) &&
|
||||
!test_bit(SDF_KILL, &sdp->sd_flags) &&
|
||||
gfs2_queue_verify_evict(gl))
|
||||
return;
|
||||
} else {
|
||||
@@ -1231,7 +1231,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
|
||||
out_free:
|
||||
gfs2_glock_dealloc(&gl->gl_rcu);
|
||||
if (atomic_dec_and_test(&sdp->sd_glock_disposal))
|
||||
wake_up(&sdp->sd_glock_wait);
|
||||
wake_up(&sdp->sd_kill_wait);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
@@ -1515,27 +1515,20 @@ fail:
|
||||
}
|
||||
if (test_bit(HIF_HOLDER, &gh2->gh_iflags))
|
||||
continue;
|
||||
if (unlikely((gh->gh_flags & LM_FLAG_PRIORITY) && !insert_pt))
|
||||
insert_pt = &gh2->gh_list;
|
||||
}
|
||||
trace_gfs2_glock_queue(gh, 1);
|
||||
gfs2_glstats_inc(gl, GFS2_LKS_QCOUNT);
|
||||
gfs2_sbstats_inc(gl, GFS2_LKS_QCOUNT);
|
||||
if (likely(insert_pt == NULL)) {
|
||||
list_add_tail(&gh->gh_list, &gl->gl_holders);
|
||||
if (unlikely(gh->gh_flags & LM_FLAG_PRIORITY))
|
||||
goto do_cancel;
|
||||
return;
|
||||
}
|
||||
list_add_tail(&gh->gh_list, insert_pt);
|
||||
do_cancel:
|
||||
gh = list_first_entry(&gl->gl_holders, struct gfs2_holder, gh_list);
|
||||
if (!(gh->gh_flags & LM_FLAG_PRIORITY)) {
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
if (sdp->sd_lockstruct.ls_ops->lm_cancel)
|
||||
sdp->sd_lockstruct.ls_ops->lm_cancel(gl);
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
}
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
if (sdp->sd_lockstruct.ls_ops->lm_cancel)
|
||||
sdp->sd_lockstruct.ls_ops->lm_cancel(gl);
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
return;
|
||||
|
||||
trap_recursive:
|
||||
@@ -2195,7 +2188,7 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
|
||||
flush_workqueue(glock_workqueue);
|
||||
glock_hash_walk(clear_glock, sdp);
|
||||
flush_workqueue(glock_workqueue);
|
||||
wait_event_timeout(sdp->sd_glock_wait,
|
||||
wait_event_timeout(sdp->sd_kill_wait,
|
||||
atomic_read(&sdp->sd_glock_disposal) == 0,
|
||||
HZ * 600);
|
||||
glock_hash_walk(dump_glock_func, sdp);
|
||||
@@ -2227,8 +2220,6 @@ static const char *hflags2str(char *buf, u16 flags, unsigned long iflags)
|
||||
*p++ = 'e';
|
||||
if (flags & LM_FLAG_ANY)
|
||||
*p++ = 'A';
|
||||
if (flags & LM_FLAG_PRIORITY)
|
||||
*p++ = 'p';
|
||||
if (flags & LM_FLAG_NODE_SCOPE)
|
||||
*p++ = 'n';
|
||||
if (flags & GL_ASYNC)
|
||||
|
||||
@@ -68,14 +68,6 @@ enum {
|
||||
* also be granted in SHARED. The preferred state is whichever is compatible
|
||||
* with other granted locks, or the specified state if no other locks exist.
|
||||
*
|
||||
* LM_FLAG_PRIORITY
|
||||
* Override fairness considerations. Suppose a lock is held in a shared state
|
||||
* and there is a pending request for the deferred state. A shared lock
|
||||
* request with the priority flag would be allowed to bypass the deferred
|
||||
* request and directly join the other shared lock. A shared lock request
|
||||
* without the priority flag might be forced to wait until the deferred
|
||||
* requested had acquired and released the lock.
|
||||
*
|
||||
* LM_FLAG_NODE_SCOPE
|
||||
* This holder agrees to share the lock within this node. In other words,
|
||||
* the glock is held in EX mode according to DLM, but local holders on the
|
||||
@@ -86,7 +78,6 @@ enum {
|
||||
#define LM_FLAG_TRY_1CB 0x0002
|
||||
#define LM_FLAG_NOEXP 0x0004
|
||||
#define LM_FLAG_ANY 0x0008
|
||||
#define LM_FLAG_PRIORITY 0x0010
|
||||
#define LM_FLAG_NODE_SCOPE 0x0020
|
||||
#define GL_ASYNC 0x0040
|
||||
#define GL_EXACT 0x0080
|
||||
|
||||
+1
-1
@@ -637,7 +637,7 @@ static void iopen_go_callback(struct gfs2_glock *gl, bool remote)
|
||||
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
|
||||
|
||||
if (!remote || sb_rdonly(sdp->sd_vfs) ||
|
||||
test_bit(SDF_DEACTIVATING, &sdp->sd_flags))
|
||||
test_bit(SDF_KILL, &sdp->sd_flags))
|
||||
return;
|
||||
|
||||
if (gl->gl_demote_state == LM_ST_UNLOCKED &&
|
||||
|
||||
+4
-3
@@ -452,7 +452,7 @@ struct gfs2_quota_data {
|
||||
s64 qd_change_sync;
|
||||
|
||||
unsigned int qd_slot;
|
||||
unsigned int qd_slot_count;
|
||||
unsigned int qd_slot_ref;
|
||||
|
||||
struct buffer_head *qd_bh;
|
||||
struct gfs2_quota_change *qd_bh_qc;
|
||||
@@ -537,6 +537,7 @@ struct gfs2_statfs_change_host {
|
||||
#define GFS2_QUOTA_OFF 0
|
||||
#define GFS2_QUOTA_ACCOUNT 1
|
||||
#define GFS2_QUOTA_ON 2
|
||||
#define GFS2_QUOTA_QUIET 3 /* on but not complaining */
|
||||
|
||||
#define GFS2_DATA_DEFAULT GFS2_DATA_ORDERED
|
||||
#define GFS2_DATA_WRITEBACK 1
|
||||
@@ -606,7 +607,7 @@ enum {
|
||||
SDF_REMOTE_WITHDRAW = 13, /* Performing remote recovery */
|
||||
SDF_WITHDRAW_RECOVERY = 14, /* Wait for journal recovery when we are
|
||||
withdrawing */
|
||||
SDF_DEACTIVATING = 15,
|
||||
SDF_KILL = 15,
|
||||
SDF_EVICTING = 16,
|
||||
SDF_FROZEN = 17,
|
||||
};
|
||||
@@ -716,7 +717,7 @@ struct gfs2_sbd {
|
||||
struct gfs2_glock *sd_rename_gl;
|
||||
struct gfs2_glock *sd_freeze_gl;
|
||||
struct work_struct sd_freeze_work;
|
||||
wait_queue_head_t sd_glock_wait;
|
||||
wait_queue_head_t sd_kill_wait;
|
||||
wait_queue_head_t sd_async_glock_wait;
|
||||
atomic_t sd_glock_disposal;
|
||||
struct completion sd_locking_init;
|
||||
|
||||
+10
-4
@@ -276,10 +276,16 @@ struct inode *gfs2_lookup_simple(struct inode *dip, const char *name)
|
||||
* gfs2_lookup_simple callers expect ENOENT
|
||||
* and do not check for NULL.
|
||||
*/
|
||||
if (inode == NULL)
|
||||
return ERR_PTR(-ENOENT);
|
||||
else
|
||||
return inode;
|
||||
if (IS_ERR_OR_NULL(inode))
|
||||
return inode ? inode : ERR_PTR(-ENOENT);
|
||||
|
||||
/*
|
||||
* Must not call back into the filesystem when allocating
|
||||
* pages in the metadata inode's address space.
|
||||
*/
|
||||
mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
|
||||
|
||||
return inode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -222,11 +222,6 @@ static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags,
|
||||
lkf |= DLM_LKF_NOQUEUEBAST;
|
||||
}
|
||||
|
||||
if (gfs_flags & LM_FLAG_PRIORITY) {
|
||||
lkf |= DLM_LKF_NOORDER;
|
||||
lkf |= DLM_LKF_HEADQUE;
|
||||
}
|
||||
|
||||
if (gfs_flags & LM_FLAG_ANY) {
|
||||
if (req == DLM_LOCK_PR)
|
||||
lkf |= DLM_LKF_ALTCW;
|
||||
|
||||
+30
-39
@@ -1227,6 +1227,21 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
||||
gfs2_log_unlock(sdp);
|
||||
}
|
||||
|
||||
static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp)
|
||||
{
|
||||
return atomic_read(&sdp->sd_log_pinned) +
|
||||
atomic_read(&sdp->sd_log_blks_needed) >=
|
||||
atomic_read(&sdp->sd_log_thresh1);
|
||||
}
|
||||
|
||||
static inline int gfs2_ail_flush_reqd(struct gfs2_sbd *sdp)
|
||||
{
|
||||
return sdp->sd_jdesc->jd_blocks -
|
||||
atomic_read(&sdp->sd_log_blks_free) +
|
||||
atomic_read(&sdp->sd_log_blks_needed) >=
|
||||
atomic_read(&sdp->sd_log_thresh2);
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_log_commit - Commit a transaction to the log
|
||||
* @sdp: the filesystem
|
||||
@@ -1246,9 +1261,7 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
||||
{
|
||||
log_refund(sdp, tr);
|
||||
|
||||
if (atomic_read(&sdp->sd_log_pinned) > atomic_read(&sdp->sd_log_thresh1) ||
|
||||
((sdp->sd_jdesc->jd_blocks - atomic_read(&sdp->sd_log_blks_free)) >
|
||||
atomic_read(&sdp->sd_log_thresh2)))
|
||||
if (gfs2_ail_flush_reqd(sdp) || gfs2_jrnl_flush_reqd(sdp))
|
||||
wake_up(&sdp->sd_logd_waitq);
|
||||
}
|
||||
|
||||
@@ -1271,24 +1284,6 @@ static void gfs2_log_shutdown(struct gfs2_sbd *sdp)
|
||||
gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list));
|
||||
}
|
||||
|
||||
static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp)
|
||||
{
|
||||
return (atomic_read(&sdp->sd_log_pinned) +
|
||||
atomic_read(&sdp->sd_log_blks_needed) >=
|
||||
atomic_read(&sdp->sd_log_thresh1));
|
||||
}
|
||||
|
||||
static inline int gfs2_ail_flush_reqd(struct gfs2_sbd *sdp)
|
||||
{
|
||||
unsigned int used_blocks = sdp->sd_jdesc->jd_blocks - atomic_read(&sdp->sd_log_blks_free);
|
||||
|
||||
if (test_and_clear_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags))
|
||||
return 1;
|
||||
|
||||
return used_blocks + atomic_read(&sdp->sd_log_blks_needed) >=
|
||||
atomic_read(&sdp->sd_log_thresh2);
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_logd - Update log tail as Active Items get flushed to in-place blocks
|
||||
* @data: Pointer to GFS2 superblock
|
||||
@@ -1301,14 +1296,11 @@ int gfs2_logd(void *data)
|
||||
{
|
||||
struct gfs2_sbd *sdp = data;
|
||||
unsigned long t = 1;
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
if (gfs2_withdrawn(sdp))
|
||||
break;
|
||||
|
||||
if (gfs2_withdrawn(sdp)) {
|
||||
msleep_interruptible(HZ);
|
||||
continue;
|
||||
}
|
||||
/* Check for errors writing to the journal */
|
||||
if (sdp->sd_log_error) {
|
||||
gfs2_lm(sdp,
|
||||
@@ -1317,7 +1309,7 @@ int gfs2_logd(void *data)
|
||||
"prevent further damage.\n",
|
||||
sdp->sd_fsname, sdp->sd_log_error);
|
||||
gfs2_withdraw(sdp);
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
|
||||
@@ -1326,7 +1318,9 @@ int gfs2_logd(void *data)
|
||||
GFS2_LFC_LOGD_JFLUSH_REQD);
|
||||
}
|
||||
|
||||
if (gfs2_ail_flush_reqd(sdp)) {
|
||||
if (test_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags) ||
|
||||
gfs2_ail_flush_reqd(sdp)) {
|
||||
clear_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags);
|
||||
gfs2_ail1_start(sdp);
|
||||
gfs2_ail1_wait(sdp);
|
||||
gfs2_ail1_empty(sdp, 0);
|
||||
@@ -1338,17 +1332,14 @@ int gfs2_logd(void *data)
|
||||
|
||||
try_to_freeze();
|
||||
|
||||
do {
|
||||
prepare_to_wait(&sdp->sd_logd_waitq, &wait,
|
||||
TASK_INTERRUPTIBLE);
|
||||
if (!gfs2_ail_flush_reqd(sdp) &&
|
||||
!gfs2_jrnl_flush_reqd(sdp) &&
|
||||
!kthread_should_stop())
|
||||
t = schedule_timeout(t);
|
||||
} while(t && !gfs2_ail_flush_reqd(sdp) &&
|
||||
!gfs2_jrnl_flush_reqd(sdp) &&
|
||||
!kthread_should_stop());
|
||||
finish_wait(&sdp->sd_logd_waitq, &wait);
|
||||
t = wait_event_interruptible_timeout(sdp->sd_logd_waitq,
|
||||
test_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags) ||
|
||||
gfs2_ail_flush_reqd(sdp) ||
|
||||
gfs2_jrnl_flush_reqd(sdp) ||
|
||||
sdp->sd_log_error ||
|
||||
gfs2_withdrawn(sdp) ||
|
||||
kthread_should_stop(),
|
||||
t);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+3
-4
@@ -456,7 +456,7 @@ static bool gfs2_jhead_pg_srch(struct gfs2_jdesc *jd,
|
||||
* Find the folio with 'index' in the journal's mapping. Search the folio for
|
||||
* the journal head if requested (cleanup == false). Release refs on the
|
||||
* folio so the page cache can reclaim it. We grabbed a
|
||||
* reference on this folio twice, first when we did a find_or_create_page()
|
||||
* reference on this folio twice, first when we did a grab_cache_page()
|
||||
* to obtain the folio to add it to the bio and second when we do a
|
||||
* filemap_get_folio() here to get the folio to wait on while I/O on it is being
|
||||
* completed.
|
||||
@@ -481,7 +481,7 @@ static void gfs2_jhead_process_page(struct gfs2_jdesc *jd, unsigned long index,
|
||||
if (!*done)
|
||||
*done = gfs2_jhead_pg_srch(jd, head, &folio->page);
|
||||
|
||||
/* filemap_get_folio() and the earlier find_or_create_page() */
|
||||
/* filemap_get_folio() and the earlier grab_cache_page() */
|
||||
folio_put_refs(folio, 2);
|
||||
}
|
||||
|
||||
@@ -535,8 +535,7 @@ int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head,
|
||||
|
||||
for (; block < je->lblock + je->blocks; block++, dblock++) {
|
||||
if (!page) {
|
||||
page = find_or_create_page(mapping,
|
||||
block >> shift, GFP_NOFS);
|
||||
page = grab_cache_page(mapping, block >> shift);
|
||||
if (!page) {
|
||||
ret = -ENOMEM;
|
||||
done = true;
|
||||
|
||||
+5
-5
@@ -152,9 +152,9 @@ static int __init init_gfs2_fs(void)
|
||||
goto fail_shrinker;
|
||||
|
||||
error = -ENOMEM;
|
||||
gfs_recovery_wq = alloc_workqueue("gfs_recovery",
|
||||
gfs2_recovery_wq = alloc_workqueue("gfs2_recovery",
|
||||
WQ_MEM_RECLAIM | WQ_FREEZABLE, 0);
|
||||
if (!gfs_recovery_wq)
|
||||
if (!gfs2_recovery_wq)
|
||||
goto fail_wq1;
|
||||
|
||||
gfs2_control_wq = alloc_workqueue("gfs2_control",
|
||||
@@ -162,7 +162,7 @@ static int __init init_gfs2_fs(void)
|
||||
if (!gfs2_control_wq)
|
||||
goto fail_wq2;
|
||||
|
||||
gfs2_freeze_wq = alloc_workqueue("freeze_workqueue", 0, 0);
|
||||
gfs2_freeze_wq = alloc_workqueue("gfs2_freeze", 0, 0);
|
||||
|
||||
if (!gfs2_freeze_wq)
|
||||
goto fail_wq3;
|
||||
@@ -194,7 +194,7 @@ fail_mempool:
|
||||
fail_wq3:
|
||||
destroy_workqueue(gfs2_control_wq);
|
||||
fail_wq2:
|
||||
destroy_workqueue(gfs_recovery_wq);
|
||||
destroy_workqueue(gfs2_recovery_wq);
|
||||
fail_wq1:
|
||||
unregister_shrinker(&gfs2_qd_shrinker);
|
||||
fail_shrinker:
|
||||
@@ -234,7 +234,7 @@ static void __exit exit_gfs2_fs(void)
|
||||
gfs2_unregister_debugfs();
|
||||
unregister_filesystem(&gfs2_fs_type);
|
||||
unregister_filesystem(&gfs2meta_fs_type);
|
||||
destroy_workqueue(gfs_recovery_wq);
|
||||
destroy_workqueue(gfs2_recovery_wq);
|
||||
destroy_workqueue(gfs2_control_wq);
|
||||
destroy_workqueue(gfs2_freeze_wq);
|
||||
list_lru_destroy(&gfs2_qd_lru);
|
||||
|
||||
+29
-13
@@ -87,7 +87,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
|
||||
set_bit(SDF_NOJOURNALID, &sdp->sd_flags);
|
||||
gfs2_tune_init(&sdp->sd_tune);
|
||||
|
||||
init_waitqueue_head(&sdp->sd_glock_wait);
|
||||
init_waitqueue_head(&sdp->sd_kill_wait);
|
||||
init_waitqueue_head(&sdp->sd_async_glock_wait);
|
||||
atomic_set(&sdp->sd_glock_disposal, 0);
|
||||
init_completion(&sdp->sd_locking_init);
|
||||
@@ -1103,29 +1103,49 @@ static int init_threads(struct gfs2_sbd *sdp)
|
||||
struct task_struct *p;
|
||||
int error = 0;
|
||||
|
||||
p = kthread_run(gfs2_logd, sdp, "gfs2_logd");
|
||||
p = kthread_create(gfs2_logd, sdp, "gfs2_logd/%s", sdp->sd_fsname);
|
||||
if (IS_ERR(p)) {
|
||||
error = PTR_ERR(p);
|
||||
fs_err(sdp, "can't start logd thread: %d\n", error);
|
||||
fs_err(sdp, "can't create logd thread: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
get_task_struct(p);
|
||||
sdp->sd_logd_process = p;
|
||||
|
||||
p = kthread_run(gfs2_quotad, sdp, "gfs2_quotad");
|
||||
p = kthread_create(gfs2_quotad, sdp, "gfs2_quotad/%s", sdp->sd_fsname);
|
||||
if (IS_ERR(p)) {
|
||||
error = PTR_ERR(p);
|
||||
fs_err(sdp, "can't start quotad thread: %d\n", error);
|
||||
fs_err(sdp, "can't create quotad thread: %d\n", error);
|
||||
goto fail;
|
||||
}
|
||||
get_task_struct(p);
|
||||
sdp->sd_quotad_process = p;
|
||||
|
||||
wake_up_process(sdp->sd_logd_process);
|
||||
wake_up_process(sdp->sd_quotad_process);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
kthread_stop(sdp->sd_logd_process);
|
||||
put_task_struct(sdp->sd_logd_process);
|
||||
sdp->sd_logd_process = NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
void gfs2_destroy_threads(struct gfs2_sbd *sdp)
|
||||
{
|
||||
if (sdp->sd_logd_process) {
|
||||
kthread_stop(sdp->sd_logd_process);
|
||||
put_task_struct(sdp->sd_logd_process);
|
||||
sdp->sd_logd_process = NULL;
|
||||
}
|
||||
if (sdp->sd_quotad_process) {
|
||||
kthread_stop(sdp->sd_quotad_process);
|
||||
put_task_struct(sdp->sd_quotad_process);
|
||||
sdp->sd_quotad_process = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_fill_super - Read in superblock
|
||||
* @sb: The VFS superblock
|
||||
@@ -1276,12 +1296,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
|
||||
if (error) {
|
||||
gfs2_freeze_unlock(&sdp->sd_freeze_gh);
|
||||
if (sdp->sd_quotad_process)
|
||||
kthread_stop(sdp->sd_quotad_process);
|
||||
sdp->sd_quotad_process = NULL;
|
||||
if (sdp->sd_logd_process)
|
||||
kthread_stop(sdp->sd_logd_process);
|
||||
sdp->sd_logd_process = NULL;
|
||||
gfs2_destroy_threads(sdp);
|
||||
fs_err(sdp, "can't make FS RW: %d\n", error);
|
||||
goto fail_per_node;
|
||||
}
|
||||
@@ -1381,6 +1396,7 @@ static const struct constant_table gfs2_param_quota[] = {
|
||||
{"off", GFS2_QUOTA_OFF},
|
||||
{"account", GFS2_QUOTA_ACCOUNT},
|
||||
{"on", GFS2_QUOTA_ON},
|
||||
{"quiet", GFS2_QUOTA_QUIET},
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -1786,9 +1802,9 @@ static void gfs2_kill_sb(struct super_block *sb)
|
||||
/*
|
||||
* Flush and then drain the delete workqueue here (via
|
||||
* destroy_workqueue()) to ensure that any delete work that
|
||||
* may be running will also see the SDF_DEACTIVATING flag.
|
||||
* may be running will also see the SDF_KILL flag.
|
||||
*/
|
||||
set_bit(SDF_DEACTIVATING, &sdp->sd_flags);
|
||||
set_bit(SDF_KILL, &sdp->sd_flags);
|
||||
gfs2_flush_delete_work(sdp);
|
||||
destroy_workqueue(sdp->sd_delete_wq);
|
||||
|
||||
|
||||
+197
-173
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -27,7 +27,7 @@
|
||||
#include "util.h"
|
||||
#include "dir.h"
|
||||
|
||||
struct workqueue_struct *gfs_recovery_wq;
|
||||
struct workqueue_struct *gfs2_recovery_wq;
|
||||
|
||||
int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
|
||||
struct buffer_head **bh)
|
||||
@@ -570,7 +570,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd, bool wait)
|
||||
return -EBUSY;
|
||||
|
||||
/* we have JDF_RECOVERY, queue should always succeed */
|
||||
rv = queue_work(gfs_recovery_wq, &jd->jd_work);
|
||||
rv = queue_work(gfs2_recovery_wq, &jd->jd_work);
|
||||
BUG_ON(!rv);
|
||||
|
||||
if (wait)
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "incore.h"
|
||||
|
||||
extern struct workqueue_struct *gfs_recovery_wq;
|
||||
extern struct workqueue_struct *gfs2_recovery_wq;
|
||||
|
||||
static inline void gfs2_replay_incr_blk(struct gfs2_jdesc *jd, u32 *blk)
|
||||
{
|
||||
|
||||
+9
-19
@@ -546,20 +546,10 @@ void gfs2_make_fs_ro(struct gfs2_sbd *sdp)
|
||||
{
|
||||
int log_write_allowed = test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
|
||||
|
||||
if (!test_bit(SDF_DEACTIVATING, &sdp->sd_flags))
|
||||
if (!test_bit(SDF_KILL, &sdp->sd_flags))
|
||||
gfs2_flush_delete_work(sdp);
|
||||
|
||||
if (!log_write_allowed && current == sdp->sd_quotad_process)
|
||||
fs_warn(sdp, "The quotad daemon is withdrawing.\n");
|
||||
else if (sdp->sd_quotad_process)
|
||||
kthread_stop(sdp->sd_quotad_process);
|
||||
sdp->sd_quotad_process = NULL;
|
||||
|
||||
if (!log_write_allowed && current == sdp->sd_logd_process)
|
||||
fs_warn(sdp, "The logd daemon is withdrawing.\n");
|
||||
else if (sdp->sd_logd_process)
|
||||
kthread_stop(sdp->sd_logd_process);
|
||||
sdp->sd_logd_process = NULL;
|
||||
gfs2_destroy_threads(sdp);
|
||||
|
||||
if (log_write_allowed) {
|
||||
gfs2_quota_sync(sdp->sd_vfs, 0);
|
||||
@@ -580,15 +570,8 @@ void gfs2_make_fs_ro(struct gfs2_sbd *sdp)
|
||||
gfs2_log_is_empty(sdp),
|
||||
HZ * 5);
|
||||
gfs2_assert_warn(sdp, gfs2_log_is_empty(sdp));
|
||||
} else {
|
||||
wait_event_timeout(sdp->sd_log_waitq,
|
||||
gfs2_log_is_empty(sdp),
|
||||
HZ * 5);
|
||||
}
|
||||
gfs2_quota_cleanup(sdp);
|
||||
|
||||
if (!log_write_allowed)
|
||||
sdp->sd_vfs->s_flags |= SB_RDONLY;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -622,6 +605,10 @@ restart:
|
||||
if (!sb_rdonly(sb)) {
|
||||
gfs2_make_fs_ro(sdp);
|
||||
}
|
||||
if (gfs2_withdrawn(sdp)) {
|
||||
gfs2_destroy_threads(sdp);
|
||||
gfs2_quota_cleanup(sdp);
|
||||
}
|
||||
WARN_ON(gfs2_withdrawing(sdp));
|
||||
|
||||
/* At this point, we're through modifying the disk */
|
||||
@@ -1134,6 +1121,9 @@ static int gfs2_show_options(struct seq_file *s, struct dentry *root)
|
||||
case GFS2_QUOTA_ON:
|
||||
state = "on";
|
||||
break;
|
||||
case GFS2_QUOTA_QUIET:
|
||||
state = "quiet";
|
||||
break;
|
||||
default:
|
||||
state = "unknown";
|
||||
break;
|
||||
|
||||
@@ -36,6 +36,7 @@ extern int gfs2_lookup_in_master_dir(struct gfs2_sbd *sdp, char *filename,
|
||||
extern int gfs2_make_fs_rw(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_make_fs_ro(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_online_uevent(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_destroy_threads(struct gfs2_sbd *sdp);
|
||||
extern int gfs2_statfs_init(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
|
||||
s64 dinodes);
|
||||
|
||||
+9
-3
@@ -98,7 +98,10 @@ static ssize_t status_show(struct gfs2_sbd *sdp, char *buf)
|
||||
"sd_log_flush_head: %d\n"
|
||||
"sd_log_flush_tail: %d\n"
|
||||
"sd_log_blks_reserved: %d\n"
|
||||
"sd_log_revokes_available: %d\n",
|
||||
"sd_log_revokes_available: %d\n"
|
||||
"sd_log_pinned: %d\n"
|
||||
"sd_log_thresh1: %d\n"
|
||||
"sd_log_thresh2: %d\n",
|
||||
test_bit(SDF_JOURNAL_CHECKED, &f),
|
||||
test_bit(SDF_JOURNAL_LIVE, &f),
|
||||
(sdp->sd_jdesc ? sdp->sd_jdesc->jd_jid : 0),
|
||||
@@ -118,7 +121,7 @@ static ssize_t status_show(struct gfs2_sbd *sdp, char *buf)
|
||||
test_bit(SDF_WITHDRAW_IN_PROG, &f),
|
||||
test_bit(SDF_REMOTE_WITHDRAW, &f),
|
||||
test_bit(SDF_WITHDRAW_RECOVERY, &f),
|
||||
test_bit(SDF_DEACTIVATING, &f),
|
||||
test_bit(SDF_KILL, &f),
|
||||
sdp->sd_log_error,
|
||||
rwsem_is_locked(&sdp->sd_log_flush_lock),
|
||||
sdp->sd_log_num_revoke,
|
||||
@@ -128,7 +131,10 @@ static ssize_t status_show(struct gfs2_sbd *sdp, char *buf)
|
||||
sdp->sd_log_flush_head,
|
||||
sdp->sd_log_flush_tail,
|
||||
sdp->sd_log_blks_reserved,
|
||||
atomic_read(&sdp->sd_log_revokes_available));
|
||||
atomic_read(&sdp->sd_log_revokes_available),
|
||||
atomic_read(&sdp->sd_log_pinned),
|
||||
atomic_read(&sdp->sd_log_thresh1),
|
||||
atomic_read(&sdp->sd_log_thresh2));
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user