nilfs2: fix lock order reversal in nilfs_clean_segments ioctl
[safe/jmp/linux-2.6] / fs / gfs2 / recovery.c
index 6fb07d6..247e8f7 100644 (file)
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
-#include <linux/lm_interface.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
 
 #include "gfs2.h"
 #include "incore.h"
 #include "bmap.h"
 #include "glock.h"
 #include "glops.h"
-#include "lm.h"
 #include "lops.h"
 #include "meta_io.h"
 #include "recovery.h"
@@ -69,7 +69,7 @@ int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where)
                return 0;
        }
 
-       rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_KERNEL);
+       rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_NOFS);
        if (!rr)
                return -ENOMEM;
 
@@ -150,7 +150,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
                          struct gfs2_log_header_host *head)
 {
        struct buffer_head *bh;
-       struct gfs2_log_header_host lh;
+       struct gfs2_log_header_host uninitialized_var(lh);
        const u32 nothing = 0;
        u32 hash;
        int error;
@@ -425,8 +425,24 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea
        return error;
 }
 
+
+static void gfs2_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
+                               unsigned int message)
+{
+       char env_jid[20];
+       char env_status[20];
+       char *envp[] = { env_jid, env_status, NULL };
+       struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+        ls->ls_recover_jid_done = jid;
+        ls->ls_recover_jid_status = message;
+       sprintf(env_jid, "JID=%d", jid);
+       sprintf(env_status, "RECOVERY=%s",
+               message == LM_RD_SUCCESS ? "Done" : "Failed");
+        kobject_uevent_env(&sdp->sd_kobj, KOBJ_CHANGE, envp);
+}
+
 /**
- * gfs2_recover_journal - recovery a given journal
+ * 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
@@ -496,7 +512,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
 
                error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED,
                                           LM_FLAG_NOEXP | LM_FLAG_PRIORITY |
-                                          GL_NOCANCEL | GL_NOCACHE, &t_gh);
+                                          GL_NOCACHE, &t_gh);
                if (error)
                        goto fail_gunlock_ji;
 
@@ -547,7 +563,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
        if (jd->jd_jid != sdp->sd_lockstruct.ls_jid)
                gfs2_glock_dq_uninit(&ji_gh);
 
-       gfs2_lm_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS);
+       gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS);
 
        if (jd->jd_jid != sdp->sd_lockstruct.ls_jid)
                gfs2_glock_dq_uninit(&j_gh);
@@ -567,17 +583,39 @@ fail_gunlock_j:
        fs_info(sdp, "jid=%u: %s\n", jd->jd_jid, (error) ? "Failed" : "Done");
 
 fail:
-       gfs2_lm_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP);
+       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);
+
+       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
  *
  */
 
-void gfs2_check_journals(struct gfs2_sbd *sdp)
+static void gfs2_check_journals(struct gfs2_sbd *sdp)
 {
        struct gfs2_jdesc *jd;
 
@@ -591,3 +629,25 @@ void gfs2_check_journals(struct gfs2_sbd *sdp)
        }
 }
 
+/**
+ * gfs2_recoverd - Recover dead machine's journals
+ * @sdp: Pointer to GFS2 superblock
+ *
+ */
+
+int gfs2_recoverd(void *data)
+{
+       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);
+       }
+
+       return 0;
+}
+