Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / fs / gfs2 / recovery.c
index d0c806b..b249e29 100644 (file)
@@ -7,7 +7,6 @@
  * of the GNU General Public License version 2.
  */
 
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
@@ -117,6 +116,22 @@ void gfs2_revoke_clean(struct gfs2_sbd *sdp)
        }
 }
 
+static int gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf)
+{
+       const struct gfs2_log_header *str = buf;
+
+       if (str->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) ||
+           str->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH))
+               return 1;
+
+       lh->lh_sequence = be64_to_cpu(str->lh_sequence);
+       lh->lh_flags = be32_to_cpu(str->lh_flags);
+       lh->lh_tail = be32_to_cpu(str->lh_tail);
+       lh->lh_blkno = be32_to_cpu(str->lh_blkno);
+       lh->lh_hash = be32_to_cpu(str->lh_hash);
+       return 0;
+}
+
 /**
  * get_log_header - read the log header for a given segment
  * @jd: the journal
@@ -148,12 +163,10 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
                                             sizeof(u32));
        hash = crc32_le(hash, (unsigned char const *)&nothing, sizeof(nothing));
        hash ^= (u32)~0;
-       gfs2_log_header_in(&lh, bh->b_data);
+       error = gfs2_log_header_in(&lh, bh->b_data);
        brelse(bh);
 
-       if (lh.lh_header.mh_magic != GFS2_MAGIC ||
-           lh.lh_header.mh_type != GFS2_METATYPE_LH ||
-           lh.lh_blkno != blk || lh.lh_hash != hash)
+       if (error || lh.lh_blkno != blk || lh.lh_hash != hash)
                return 1;
 
        *head = lh;
@@ -378,7 +391,7 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea
        lblock = head->lh_blkno;
        gfs2_replay_incr_blk(sdp, &lblock);
        bh_map.b_size = 1 << ip->i_inode.i_blkbits;
-       error = gfs2_block_map(&ip->i_inode, lblock, 0, &bh_map);
+       error = gfs2_block_map(&ip->i_inode, lblock, &bh_map, 0);
        if (error)
                return error;
        if (!bh_map.b_blocknr) {
@@ -456,7 +469,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
                };
 
                error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
-                                          LM_FLAG_NOEXP, &ji_gh);
+                                          LM_FLAG_NOEXP | GL_NOCACHE, &ji_gh);
                if (error)
                        goto fail_gunlock_j;
        } else {
@@ -491,13 +504,21 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
                        if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
                                ro = 1;
                } else {
-                       if (sdp->sd_vfs->s_flags & MS_RDONLY)
-                               ro = 1;
+                       if (sdp->sd_vfs->s_flags & MS_RDONLY) {
+                               /* check if device itself is read-only */
+                               ro = bdev_read_only(sdp->sd_vfs->s_bdev);
+                               if (!ro) {
+                                       fs_info(sdp, "recovery required on "
+                                               "read-only filesystem.\n");
+                                       fs_info(sdp, "write access will be "
+                                               "enabled during recovery.\n");
+                               }
+                       }
                }
 
                if (ro) {
-                       fs_warn(sdp, "jid=%u: Can't replay: read-only FS\n",
-                               jd->jd_jid);
+                       fs_warn(sdp, "jid=%u: Can't replay: read-only block "
+                               "device\n", jd->jd_jid);
                        error = -EROFS;
                        goto fail_gunlock_tr;
                }