summaryrefslogtreecommitdiffstats
path: root/fs/gfs2/recovery.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-11 10:36:12 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-11 10:36:12 -0700
commit0a33f80a8373eca7f4bea3961d1346c3815fa5ed (patch)
tree16b0c0364340416f1e27bebdd4042ffe0e6fef8f /fs/gfs2/recovery.c
parentc29f5ec022451546be1e0b24c330a0368e63e4a7 (diff)
parent003dec8913d6bebb4ecc989ec04a235cf38f5ea9 (diff)
downloadop-kernel-dev-0a33f80a8373eca7f4bea3961d1346c3815fa5ed.zip
op-kernel-dev-0a33f80a8373eca7f4bea3961d1346c3815fa5ed.tar.gz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw: (25 commits) GFS2: Merge gfs2_get_sb into gfs2_get_sb_meta GFS2: Fix cache coherency between truncate and O_DIRECT read GFS2: Fix locking issue mounting gfs2meta fs GFS2: Remove unused variable GFS2: smbd proccess hangs with flock() call. GFS2: Remove args subdir from gfs2 sysfs files GFS2: Remove lockstruct subdir from gfs2 sysfs files GFS2: Move gfs2_unlink_ok into ops_inode.c GFS2: Move gfs2_readlinki into ops_inode.c GFS2: Move gfs2_rmdiri into ops_inode.c GFS2: Merge mount.c and ops_super.c into super.c GFS2: Clean up some file names GFS2: Be more aggressive in reclaiming unlinked inodes GFS2: Add a rgrp bitmap full flag GFS2: Improve resource group error handling GFS2: Don't warn when delete inode fails on ro filesystem GFS2: Update docs GFS2: Umount recovery race fix GFS2: Remove a couple of unused sysfs entries GFS2: Add commit= mount option ...
Diffstat (limited to 'fs/gfs2/recovery.c')
-rw-r--r--fs/gfs2/recovery.c102
1 files changed, 33 insertions, 69 deletions
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 247e8f7..59d2695 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -13,8 +13,7 @@
#include <linux/buffer_head.h>
#include <linux/gfs2_ondisk.h>
#include <linux/crc32.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
+#include <linux/slow-work.h>
#include "gfs2.h"
#include "incore.h"
@@ -441,18 +440,25 @@ static void gfs2_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
kobject_uevent_env(&sdp->sd_kobj, KOBJ_CHANGE, envp);
}
-/**
- * gfs2_recover_journal - recover a given journal
- * @jd: the struct gfs2_jdesc describing the journal
- *
- * Acquire the journal's lock, check to see if the journal is clean, and
- * do recovery if necessary.
- *
- * Returns: errno
- */
+static int gfs2_recover_get_ref(struct slow_work *work)
+{
+ struct gfs2_jdesc *jd = container_of(work, struct gfs2_jdesc, jd_work);
+ if (test_and_set_bit(JDF_RECOVERY, &jd->jd_flags))
+ return -EBUSY;
+ return 0;
+}
-int gfs2_recover_journal(struct gfs2_jdesc *jd)
+static void gfs2_recover_put_ref(struct slow_work *work)
+{
+ struct gfs2_jdesc *jd = container_of(work, struct gfs2_jdesc, jd_work);
+ clear_bit(JDF_RECOVERY, &jd->jd_flags);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&jd->jd_flags, JDF_RECOVERY);
+}
+
+static void gfs2_recover_work(struct slow_work *work)
{
+ struct gfs2_jdesc *jd = container_of(work, struct gfs2_jdesc, jd_work);
struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
struct gfs2_log_header_host head;
@@ -569,7 +575,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
gfs2_glock_dq_uninit(&j_gh);
fs_info(sdp, "jid=%u: Done\n", jd->jd_jid);
- return 0;
+ return;
fail_gunlock_tr:
gfs2_glock_dq_uninit(&t_gh);
@@ -584,70 +590,28 @@ fail_gunlock_j:
fail:
gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP);
- return error;
}
-static struct gfs2_jdesc *gfs2_jdesc_find_dirty(struct gfs2_sbd *sdp)
-{
- struct gfs2_jdesc *jd;
- int found = 0;
-
- spin_lock(&sdp->sd_jindex_spin);
+struct slow_work_ops gfs2_recover_ops = {
+ .get_ref = gfs2_recover_get_ref,
+ .put_ref = gfs2_recover_put_ref,
+ .execute = gfs2_recover_work,
+};
- list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) {
- if (jd->jd_dirty) {
- jd->jd_dirty = 0;
- found = 1;
- break;
- }
- }
- spin_unlock(&sdp->sd_jindex_spin);
-
- if (!found)
- jd = NULL;
- return jd;
-}
-
-/**
- * gfs2_check_journals - Recover any dirty journals
- * @sdp: the filesystem
- *
- */
-
-static void gfs2_check_journals(struct gfs2_sbd *sdp)
+static int gfs2_recovery_wait(void *word)
{
- struct gfs2_jdesc *jd;
-
- for (;;) {
- jd = gfs2_jdesc_find_dirty(sdp);
- if (!jd)
- break;
-
- if (jd != sdp->sd_jdesc)
- gfs2_recover_journal(jd);
- }
+ schedule();
+ return 0;
}
-/**
- * gfs2_recoverd - Recover dead machine's journals
- * @sdp: Pointer to GFS2 superblock
- *
- */
-
-int gfs2_recoverd(void *data)
+int gfs2_recover_journal(struct gfs2_jdesc *jd)
{
- struct gfs2_sbd *sdp = data;
- unsigned long t;
-
- while (!kthread_should_stop()) {
- gfs2_check_journals(sdp);
- t = gfs2_tune_get(sdp, gt_recoverd_secs) * HZ;
- if (freezing(current))
- refrigerator();
- schedule_timeout_interruptible(t);
- }
-
+ int rv;
+ rv = slow_work_enqueue(&jd->jd_work);
+ if (rv)
+ return rv;
+ wait_on_bit(&jd->jd_flags, JDF_RECOVERY, gfs2_recovery_wait, TASK_UNINTERRUPTIBLE);
return 0;
}
OpenPOWER on IntegriCloud