1*b3b94faaSDavid Teigland /* 2*b3b94faaSDavid Teigland * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 3*b3b94faaSDavid Teigland * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. 4*b3b94faaSDavid Teigland * 5*b3b94faaSDavid Teigland * This copyrighted material is made available to anyone wishing to use, 6*b3b94faaSDavid Teigland * modify, copy, or redistribute it subject to the terms and conditions 7*b3b94faaSDavid Teigland * of the GNU General Public License v.2. 8*b3b94faaSDavid Teigland */ 9*b3b94faaSDavid Teigland 10*b3b94faaSDavid Teigland #include <linux/sched.h> 11*b3b94faaSDavid Teigland #include <linux/slab.h> 12*b3b94faaSDavid Teigland #include <linux/spinlock.h> 13*b3b94faaSDavid Teigland #include <linux/completion.h> 14*b3b94faaSDavid Teigland #include <linux/buffer_head.h> 15*b3b94faaSDavid Teigland #include <asm/semaphore.h> 16*b3b94faaSDavid Teigland 17*b3b94faaSDavid Teigland #include "gfs2.h" 18*b3b94faaSDavid Teigland #include "bmap.h" 19*b3b94faaSDavid Teigland #include "glock.h" 20*b3b94faaSDavid Teigland #include "glops.h" 21*b3b94faaSDavid Teigland #include "lm.h" 22*b3b94faaSDavid Teigland #include "lops.h" 23*b3b94faaSDavid Teigland #include "meta_io.h" 24*b3b94faaSDavid Teigland #include "recovery.h" 25*b3b94faaSDavid Teigland #include "super.h" 26*b3b94faaSDavid Teigland 27*b3b94faaSDavid Teigland int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk, 28*b3b94faaSDavid Teigland struct buffer_head **bh) 29*b3b94faaSDavid Teigland { 30*b3b94faaSDavid Teigland struct gfs2_glock *gl = jd->jd_inode->i_gl; 31*b3b94faaSDavid Teigland int new = 0; 32*b3b94faaSDavid Teigland uint64_t dblock; 33*b3b94faaSDavid Teigland uint32_t extlen; 34*b3b94faaSDavid Teigland int error; 35*b3b94faaSDavid Teigland 36*b3b94faaSDavid Teigland error = gfs2_block_map(jd->jd_inode, blk, &new, &dblock, &extlen); 37*b3b94faaSDavid Teigland if (error) 38*b3b94faaSDavid Teigland return error; 39*b3b94faaSDavid Teigland if (!dblock) { 40*b3b94faaSDavid Teigland gfs2_consist_inode(jd->jd_inode); 41*b3b94faaSDavid Teigland return -EIO; 42*b3b94faaSDavid Teigland } 43*b3b94faaSDavid Teigland 44*b3b94faaSDavid Teigland gfs2_meta_ra(gl, dblock, extlen); 45*b3b94faaSDavid Teigland error = gfs2_meta_read(gl, dblock, DIO_START | DIO_WAIT, bh); 46*b3b94faaSDavid Teigland 47*b3b94faaSDavid Teigland return error; 48*b3b94faaSDavid Teigland } 49*b3b94faaSDavid Teigland 50*b3b94faaSDavid Teigland int gfs2_revoke_add(struct gfs2_sbd *sdp, uint64_t blkno, unsigned int where) 51*b3b94faaSDavid Teigland { 52*b3b94faaSDavid Teigland struct list_head *head = &sdp->sd_revoke_list; 53*b3b94faaSDavid Teigland struct gfs2_revoke_replay *rr; 54*b3b94faaSDavid Teigland int found = 0; 55*b3b94faaSDavid Teigland 56*b3b94faaSDavid Teigland list_for_each_entry(rr, head, rr_list) { 57*b3b94faaSDavid Teigland if (rr->rr_blkno == blkno) { 58*b3b94faaSDavid Teigland found = 1; 59*b3b94faaSDavid Teigland break; 60*b3b94faaSDavid Teigland } 61*b3b94faaSDavid Teigland } 62*b3b94faaSDavid Teigland 63*b3b94faaSDavid Teigland if (found) { 64*b3b94faaSDavid Teigland rr->rr_where = where; 65*b3b94faaSDavid Teigland return 0; 66*b3b94faaSDavid Teigland } 67*b3b94faaSDavid Teigland 68*b3b94faaSDavid Teigland rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_KERNEL); 69*b3b94faaSDavid Teigland if (!rr) 70*b3b94faaSDavid Teigland return -ENOMEM; 71*b3b94faaSDavid Teigland 72*b3b94faaSDavid Teigland rr->rr_blkno = blkno; 73*b3b94faaSDavid Teigland rr->rr_where = where; 74*b3b94faaSDavid Teigland list_add(&rr->rr_list, head); 75*b3b94faaSDavid Teigland 76*b3b94faaSDavid Teigland return 1; 77*b3b94faaSDavid Teigland } 78*b3b94faaSDavid Teigland 79*b3b94faaSDavid Teigland int gfs2_revoke_check(struct gfs2_sbd *sdp, uint64_t blkno, unsigned int where) 80*b3b94faaSDavid Teigland { 81*b3b94faaSDavid Teigland struct gfs2_revoke_replay *rr; 82*b3b94faaSDavid Teigland int wrap, a, b, revoke; 83*b3b94faaSDavid Teigland int found = 0; 84*b3b94faaSDavid Teigland 85*b3b94faaSDavid Teigland list_for_each_entry(rr, &sdp->sd_revoke_list, rr_list) { 86*b3b94faaSDavid Teigland if (rr->rr_blkno == blkno) { 87*b3b94faaSDavid Teigland found = 1; 88*b3b94faaSDavid Teigland break; 89*b3b94faaSDavid Teigland } 90*b3b94faaSDavid Teigland } 91*b3b94faaSDavid Teigland 92*b3b94faaSDavid Teigland if (!found) 93*b3b94faaSDavid Teigland return 0; 94*b3b94faaSDavid Teigland 95*b3b94faaSDavid Teigland wrap = (rr->rr_where < sdp->sd_replay_tail); 96*b3b94faaSDavid Teigland a = (sdp->sd_replay_tail < where); 97*b3b94faaSDavid Teigland b = (where < rr->rr_where); 98*b3b94faaSDavid Teigland revoke = (wrap) ? (a || b) : (a && b); 99*b3b94faaSDavid Teigland 100*b3b94faaSDavid Teigland return revoke; 101*b3b94faaSDavid Teigland } 102*b3b94faaSDavid Teigland 103*b3b94faaSDavid Teigland void gfs2_revoke_clean(struct gfs2_sbd *sdp) 104*b3b94faaSDavid Teigland { 105*b3b94faaSDavid Teigland struct list_head *head = &sdp->sd_revoke_list; 106*b3b94faaSDavid Teigland struct gfs2_revoke_replay *rr; 107*b3b94faaSDavid Teigland 108*b3b94faaSDavid Teigland while (!list_empty(head)) { 109*b3b94faaSDavid Teigland rr = list_entry(head->next, struct gfs2_revoke_replay, rr_list); 110*b3b94faaSDavid Teigland list_del(&rr->rr_list); 111*b3b94faaSDavid Teigland kfree(rr); 112*b3b94faaSDavid Teigland } 113*b3b94faaSDavid Teigland } 114*b3b94faaSDavid Teigland 115*b3b94faaSDavid Teigland /** 116*b3b94faaSDavid Teigland * get_log_header - read the log header for a given segment 117*b3b94faaSDavid Teigland * @jd: the journal 118*b3b94faaSDavid Teigland * @blk: the block to look at 119*b3b94faaSDavid Teigland * @lh: the log header to return 120*b3b94faaSDavid Teigland * 121*b3b94faaSDavid Teigland * Read the log header for a given segement in a given journal. Do a few 122*b3b94faaSDavid Teigland * sanity checks on it. 123*b3b94faaSDavid Teigland * 124*b3b94faaSDavid Teigland * Returns: 0 on success, 125*b3b94faaSDavid Teigland * 1 if the header was invalid or incomplete, 126*b3b94faaSDavid Teigland * errno on error 127*b3b94faaSDavid Teigland */ 128*b3b94faaSDavid Teigland 129*b3b94faaSDavid Teigland static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk, 130*b3b94faaSDavid Teigland struct gfs2_log_header *head) 131*b3b94faaSDavid Teigland { 132*b3b94faaSDavid Teigland struct buffer_head *bh; 133*b3b94faaSDavid Teigland struct gfs2_log_header lh; 134*b3b94faaSDavid Teigland uint32_t hash; 135*b3b94faaSDavid Teigland int error; 136*b3b94faaSDavid Teigland 137*b3b94faaSDavid Teigland error = gfs2_replay_read_block(jd, blk, &bh); 138*b3b94faaSDavid Teigland if (error) 139*b3b94faaSDavid Teigland return error; 140*b3b94faaSDavid Teigland 141*b3b94faaSDavid Teigland memcpy(&lh, bh->b_data, sizeof(struct gfs2_log_header)); 142*b3b94faaSDavid Teigland lh.lh_hash = 0; 143*b3b94faaSDavid Teigland hash = gfs2_disk_hash((char *)&lh, sizeof(struct gfs2_log_header)); 144*b3b94faaSDavid Teigland gfs2_log_header_in(&lh, bh->b_data); 145*b3b94faaSDavid Teigland 146*b3b94faaSDavid Teigland brelse(bh); 147*b3b94faaSDavid Teigland 148*b3b94faaSDavid Teigland if (lh.lh_header.mh_magic != GFS2_MAGIC || 149*b3b94faaSDavid Teigland lh.lh_header.mh_type != GFS2_METATYPE_LH || 150*b3b94faaSDavid Teigland lh.lh_blkno != blk || 151*b3b94faaSDavid Teigland lh.lh_hash != hash) 152*b3b94faaSDavid Teigland return 1; 153*b3b94faaSDavid Teigland 154*b3b94faaSDavid Teigland *head = lh; 155*b3b94faaSDavid Teigland 156*b3b94faaSDavid Teigland return 0; 157*b3b94faaSDavid Teigland } 158*b3b94faaSDavid Teigland 159*b3b94faaSDavid Teigland /** 160*b3b94faaSDavid Teigland * find_good_lh - find a good log header 161*b3b94faaSDavid Teigland * @jd: the journal 162*b3b94faaSDavid Teigland * @blk: the segment to start searching from 163*b3b94faaSDavid Teigland * @lh: the log header to fill in 164*b3b94faaSDavid Teigland * @forward: if true search forward in the log, else search backward 165*b3b94faaSDavid Teigland * 166*b3b94faaSDavid Teigland * Call get_log_header() to get a log header for a segment, but if the 167*b3b94faaSDavid Teigland * segment is bad, either scan forward or backward until we find a good one. 168*b3b94faaSDavid Teigland * 169*b3b94faaSDavid Teigland * Returns: errno 170*b3b94faaSDavid Teigland */ 171*b3b94faaSDavid Teigland 172*b3b94faaSDavid Teigland static int find_good_lh(struct gfs2_jdesc *jd, unsigned int *blk, 173*b3b94faaSDavid Teigland struct gfs2_log_header *head) 174*b3b94faaSDavid Teigland { 175*b3b94faaSDavid Teigland unsigned int orig_blk = *blk; 176*b3b94faaSDavid Teigland int error; 177*b3b94faaSDavid Teigland 178*b3b94faaSDavid Teigland for (;;) { 179*b3b94faaSDavid Teigland error = get_log_header(jd, *blk, head); 180*b3b94faaSDavid Teigland if (error <= 0) 181*b3b94faaSDavid Teigland return error; 182*b3b94faaSDavid Teigland 183*b3b94faaSDavid Teigland if (++*blk == jd->jd_blocks) 184*b3b94faaSDavid Teigland *blk = 0; 185*b3b94faaSDavid Teigland 186*b3b94faaSDavid Teigland if (*blk == orig_blk) { 187*b3b94faaSDavid Teigland gfs2_consist_inode(jd->jd_inode); 188*b3b94faaSDavid Teigland return -EIO; 189*b3b94faaSDavid Teigland } 190*b3b94faaSDavid Teigland } 191*b3b94faaSDavid Teigland } 192*b3b94faaSDavid Teigland 193*b3b94faaSDavid Teigland /** 194*b3b94faaSDavid Teigland * jhead_scan - make sure we've found the head of the log 195*b3b94faaSDavid Teigland * @jd: the journal 196*b3b94faaSDavid Teigland * @head: this is filled in with the log descriptor of the head 197*b3b94faaSDavid Teigland * 198*b3b94faaSDavid Teigland * At this point, seg and lh should be either the head of the log or just 199*b3b94faaSDavid Teigland * before. Scan forward until we find the head. 200*b3b94faaSDavid Teigland * 201*b3b94faaSDavid Teigland * Returns: errno 202*b3b94faaSDavid Teigland */ 203*b3b94faaSDavid Teigland 204*b3b94faaSDavid Teigland static int jhead_scan(struct gfs2_jdesc *jd, struct gfs2_log_header *head) 205*b3b94faaSDavid Teigland { 206*b3b94faaSDavid Teigland unsigned int blk = head->lh_blkno; 207*b3b94faaSDavid Teigland struct gfs2_log_header lh; 208*b3b94faaSDavid Teigland int error; 209*b3b94faaSDavid Teigland 210*b3b94faaSDavid Teigland for (;;) { 211*b3b94faaSDavid Teigland if (++blk == jd->jd_blocks) 212*b3b94faaSDavid Teigland blk = 0; 213*b3b94faaSDavid Teigland 214*b3b94faaSDavid Teigland error = get_log_header(jd, blk, &lh); 215*b3b94faaSDavid Teigland if (error < 0) 216*b3b94faaSDavid Teigland return error; 217*b3b94faaSDavid Teigland if (error == 1) 218*b3b94faaSDavid Teigland continue; 219*b3b94faaSDavid Teigland 220*b3b94faaSDavid Teigland if (lh.lh_sequence == head->lh_sequence) { 221*b3b94faaSDavid Teigland gfs2_consist_inode(jd->jd_inode); 222*b3b94faaSDavid Teigland return -EIO; 223*b3b94faaSDavid Teigland } 224*b3b94faaSDavid Teigland if (lh.lh_sequence < head->lh_sequence) 225*b3b94faaSDavid Teigland break; 226*b3b94faaSDavid Teigland 227*b3b94faaSDavid Teigland *head = lh; 228*b3b94faaSDavid Teigland } 229*b3b94faaSDavid Teigland 230*b3b94faaSDavid Teigland return 0; 231*b3b94faaSDavid Teigland } 232*b3b94faaSDavid Teigland 233*b3b94faaSDavid Teigland /** 234*b3b94faaSDavid Teigland * gfs2_find_jhead - find the head of a log 235*b3b94faaSDavid Teigland * @jd: the journal 236*b3b94faaSDavid Teigland * @head: the log descriptor for the head of the log is returned here 237*b3b94faaSDavid Teigland * 238*b3b94faaSDavid Teigland * Do a binary search of a journal and find the valid log entry with the 239*b3b94faaSDavid Teigland * highest sequence number. (i.e. the log head) 240*b3b94faaSDavid Teigland * 241*b3b94faaSDavid Teigland * Returns: errno 242*b3b94faaSDavid Teigland */ 243*b3b94faaSDavid Teigland 244*b3b94faaSDavid Teigland int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header *head) 245*b3b94faaSDavid Teigland { 246*b3b94faaSDavid Teigland struct gfs2_log_header lh_1, lh_m; 247*b3b94faaSDavid Teigland uint32_t blk_1, blk_2, blk_m; 248*b3b94faaSDavid Teigland int error; 249*b3b94faaSDavid Teigland 250*b3b94faaSDavid Teigland blk_1 = 0; 251*b3b94faaSDavid Teigland blk_2 = jd->jd_blocks - 1; 252*b3b94faaSDavid Teigland 253*b3b94faaSDavid Teigland for (;;) { 254*b3b94faaSDavid Teigland blk_m = (blk_1 + blk_2) / 2; 255*b3b94faaSDavid Teigland 256*b3b94faaSDavid Teigland error = find_good_lh(jd, &blk_1, &lh_1); 257*b3b94faaSDavid Teigland if (error) 258*b3b94faaSDavid Teigland return error; 259*b3b94faaSDavid Teigland 260*b3b94faaSDavid Teigland error = find_good_lh(jd, &blk_m, &lh_m); 261*b3b94faaSDavid Teigland if (error) 262*b3b94faaSDavid Teigland return error; 263*b3b94faaSDavid Teigland 264*b3b94faaSDavid Teigland if (blk_1 == blk_m || blk_m == blk_2) 265*b3b94faaSDavid Teigland break; 266*b3b94faaSDavid Teigland 267*b3b94faaSDavid Teigland if (lh_1.lh_sequence <= lh_m.lh_sequence) 268*b3b94faaSDavid Teigland blk_1 = blk_m; 269*b3b94faaSDavid Teigland else 270*b3b94faaSDavid Teigland blk_2 = blk_m; 271*b3b94faaSDavid Teigland } 272*b3b94faaSDavid Teigland 273*b3b94faaSDavid Teigland error = jhead_scan(jd, &lh_1); 274*b3b94faaSDavid Teigland if (error) 275*b3b94faaSDavid Teigland return error; 276*b3b94faaSDavid Teigland 277*b3b94faaSDavid Teigland *head = lh_1; 278*b3b94faaSDavid Teigland 279*b3b94faaSDavid Teigland return error; 280*b3b94faaSDavid Teigland } 281*b3b94faaSDavid Teigland 282*b3b94faaSDavid Teigland /** 283*b3b94faaSDavid Teigland * foreach_descriptor - go through the active part of the log 284*b3b94faaSDavid Teigland * @jd: the journal 285*b3b94faaSDavid Teigland * @start: the first log header in the active region 286*b3b94faaSDavid Teigland * @end: the last log header (don't process the contents of this entry)) 287*b3b94faaSDavid Teigland * 288*b3b94faaSDavid Teigland * Call a given function once for every log descriptor in the active 289*b3b94faaSDavid Teigland * portion of the log. 290*b3b94faaSDavid Teigland * 291*b3b94faaSDavid Teigland * Returns: errno 292*b3b94faaSDavid Teigland */ 293*b3b94faaSDavid Teigland 294*b3b94faaSDavid Teigland static int foreach_descriptor(struct gfs2_jdesc *jd, unsigned int start, 295*b3b94faaSDavid Teigland unsigned int end, int pass) 296*b3b94faaSDavid Teigland { 297*b3b94faaSDavid Teigland struct gfs2_sbd *sdp = jd->jd_inode->i_sbd; 298*b3b94faaSDavid Teigland struct buffer_head *bh; 299*b3b94faaSDavid Teigland struct gfs2_log_descriptor *ld; 300*b3b94faaSDavid Teigland int error = 0; 301*b3b94faaSDavid Teigland u32 length; 302*b3b94faaSDavid Teigland __be64 *ptr; 303*b3b94faaSDavid Teigland unsigned int offset = sizeof(struct gfs2_log_descriptor); 304*b3b94faaSDavid Teigland offset += (sizeof(__be64)-1); 305*b3b94faaSDavid Teigland offset &= ~(sizeof(__be64)-1); 306*b3b94faaSDavid Teigland 307*b3b94faaSDavid Teigland while (start != end) { 308*b3b94faaSDavid Teigland error = gfs2_replay_read_block(jd, start, &bh); 309*b3b94faaSDavid Teigland if (error) 310*b3b94faaSDavid Teigland return error; 311*b3b94faaSDavid Teigland if (gfs2_meta_check(sdp, bh)) { 312*b3b94faaSDavid Teigland brelse(bh); 313*b3b94faaSDavid Teigland return -EIO; 314*b3b94faaSDavid Teigland } 315*b3b94faaSDavid Teigland ld = (struct gfs2_log_descriptor *)bh->b_data; 316*b3b94faaSDavid Teigland length = be32_to_cpu(ld->ld_length); 317*b3b94faaSDavid Teigland 318*b3b94faaSDavid Teigland if (be16_to_cpu(ld->ld_header.mh_type) == GFS2_METATYPE_LH) { 319*b3b94faaSDavid Teigland struct gfs2_log_header lh; 320*b3b94faaSDavid Teigland error = get_log_header(jd, start, &lh); 321*b3b94faaSDavid Teigland if (!error) { 322*b3b94faaSDavid Teigland gfs2_replay_incr_blk(sdp, &start); 323*b3b94faaSDavid Teigland continue; 324*b3b94faaSDavid Teigland } 325*b3b94faaSDavid Teigland if (error == 1) { 326*b3b94faaSDavid Teigland gfs2_consist_inode(jd->jd_inode); 327*b3b94faaSDavid Teigland error = -EIO; 328*b3b94faaSDavid Teigland } 329*b3b94faaSDavid Teigland brelse(bh); 330*b3b94faaSDavid Teigland return error; 331*b3b94faaSDavid Teigland } else if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_LD)) { 332*b3b94faaSDavid Teigland brelse(bh); 333*b3b94faaSDavid Teigland return -EIO; 334*b3b94faaSDavid Teigland } 335*b3b94faaSDavid Teigland ptr = (__be64 *)(bh->b_data + offset); 336*b3b94faaSDavid Teigland error = lops_scan_elements(jd, start, ld, ptr, pass); 337*b3b94faaSDavid Teigland if (error) { 338*b3b94faaSDavid Teigland brelse(bh); 339*b3b94faaSDavid Teigland return error; 340*b3b94faaSDavid Teigland } 341*b3b94faaSDavid Teigland 342*b3b94faaSDavid Teigland while (length--) 343*b3b94faaSDavid Teigland gfs2_replay_incr_blk(sdp, &start); 344*b3b94faaSDavid Teigland 345*b3b94faaSDavid Teigland brelse(bh); 346*b3b94faaSDavid Teigland } 347*b3b94faaSDavid Teigland 348*b3b94faaSDavid Teigland return 0; 349*b3b94faaSDavid Teigland } 350*b3b94faaSDavid Teigland 351*b3b94faaSDavid Teigland /** 352*b3b94faaSDavid Teigland * clean_journal - mark a dirty journal as being clean 353*b3b94faaSDavid Teigland * @sdp: the filesystem 354*b3b94faaSDavid Teigland * @jd: the journal 355*b3b94faaSDavid Teigland * @gl: the journal's glock 356*b3b94faaSDavid Teigland * @head: the head journal to start from 357*b3b94faaSDavid Teigland * 358*b3b94faaSDavid Teigland * Returns: errno 359*b3b94faaSDavid Teigland */ 360*b3b94faaSDavid Teigland 361*b3b94faaSDavid Teigland static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header *head) 362*b3b94faaSDavid Teigland { 363*b3b94faaSDavid Teigland struct gfs2_inode *ip = jd->jd_inode; 364*b3b94faaSDavid Teigland struct gfs2_sbd *sdp = ip->i_sbd; 365*b3b94faaSDavid Teigland unsigned int lblock; 366*b3b94faaSDavid Teigland int new = 0; 367*b3b94faaSDavid Teigland uint64_t dblock; 368*b3b94faaSDavid Teigland struct gfs2_log_header *lh; 369*b3b94faaSDavid Teigland uint32_t hash; 370*b3b94faaSDavid Teigland struct buffer_head *bh; 371*b3b94faaSDavid Teigland int error; 372*b3b94faaSDavid Teigland 373*b3b94faaSDavid Teigland lblock = head->lh_blkno; 374*b3b94faaSDavid Teigland gfs2_replay_incr_blk(sdp, &lblock); 375*b3b94faaSDavid Teigland error = gfs2_block_map(ip, lblock, &new, &dblock, NULL); 376*b3b94faaSDavid Teigland if (error) 377*b3b94faaSDavid Teigland return error; 378*b3b94faaSDavid Teigland if (!dblock) { 379*b3b94faaSDavid Teigland gfs2_consist_inode(ip); 380*b3b94faaSDavid Teigland return -EIO; 381*b3b94faaSDavid Teigland } 382*b3b94faaSDavid Teigland 383*b3b94faaSDavid Teigland bh = sb_getblk(sdp->sd_vfs, dblock); 384*b3b94faaSDavid Teigland lock_buffer(bh); 385*b3b94faaSDavid Teigland memset(bh->b_data, 0, bh->b_size); 386*b3b94faaSDavid Teigland set_buffer_uptodate(bh); 387*b3b94faaSDavid Teigland clear_buffer_dirty(bh); 388*b3b94faaSDavid Teigland unlock_buffer(bh); 389*b3b94faaSDavid Teigland 390*b3b94faaSDavid Teigland lh = (struct gfs2_log_header *)bh->b_data; 391*b3b94faaSDavid Teigland memset(lh, 0, sizeof(struct gfs2_log_header)); 392*b3b94faaSDavid Teigland lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); 393*b3b94faaSDavid Teigland lh->lh_header.mh_type = cpu_to_be16(GFS2_METATYPE_LH); 394*b3b94faaSDavid Teigland lh->lh_header.mh_format = cpu_to_be16(GFS2_FORMAT_LH); 395*b3b94faaSDavid Teigland lh->lh_sequence = cpu_to_be64(head->lh_sequence + 1); 396*b3b94faaSDavid Teigland lh->lh_flags = cpu_to_be32(GFS2_LOG_HEAD_UNMOUNT); 397*b3b94faaSDavid Teigland lh->lh_blkno = cpu_to_be32(lblock); 398*b3b94faaSDavid Teigland hash = gfs2_disk_hash((const char *)lh, sizeof(struct gfs2_log_header)); 399*b3b94faaSDavid Teigland lh->lh_hash = cpu_to_be32(hash); 400*b3b94faaSDavid Teigland 401*b3b94faaSDavid Teigland set_buffer_dirty(bh); 402*b3b94faaSDavid Teigland if (sync_dirty_buffer(bh)) 403*b3b94faaSDavid Teigland gfs2_io_error_bh(sdp, bh); 404*b3b94faaSDavid Teigland brelse(bh); 405*b3b94faaSDavid Teigland 406*b3b94faaSDavid Teigland return error; 407*b3b94faaSDavid Teigland } 408*b3b94faaSDavid Teigland 409*b3b94faaSDavid Teigland /** 410*b3b94faaSDavid Teigland * gfs2_recover_journal - recovery a given journal 411*b3b94faaSDavid Teigland * @jd: the struct gfs2_jdesc describing the journal 412*b3b94faaSDavid Teigland * @wait: Don't return until the journal is clean (or an error is encountered) 413*b3b94faaSDavid Teigland * 414*b3b94faaSDavid Teigland * Acquire the journal's lock, check to see if the journal is clean, and 415*b3b94faaSDavid Teigland * do recovery if necessary. 416*b3b94faaSDavid Teigland * 417*b3b94faaSDavid Teigland * Returns: errno 418*b3b94faaSDavid Teigland */ 419*b3b94faaSDavid Teigland 420*b3b94faaSDavid Teigland int gfs2_recover_journal(struct gfs2_jdesc *jd, int wait) 421*b3b94faaSDavid Teigland { 422*b3b94faaSDavid Teigland struct gfs2_sbd *sdp = jd->jd_inode->i_sbd; 423*b3b94faaSDavid Teigland struct gfs2_log_header head; 424*b3b94faaSDavid Teigland struct gfs2_holder j_gh, ji_gh, t_gh; 425*b3b94faaSDavid Teigland unsigned long t; 426*b3b94faaSDavid Teigland int ro = 0; 427*b3b94faaSDavid Teigland unsigned int pass; 428*b3b94faaSDavid Teigland int error; 429*b3b94faaSDavid Teigland 430*b3b94faaSDavid Teigland fs_info(sdp, "jid=%u: Trying to acquire journal lock...\n", jd->jd_jid); 431*b3b94faaSDavid Teigland 432*b3b94faaSDavid Teigland /* Aquire the journal lock so we can do recovery */ 433*b3b94faaSDavid Teigland 434*b3b94faaSDavid Teigland error = gfs2_glock_nq_num(sdp, 435*b3b94faaSDavid Teigland jd->jd_jid, &gfs2_journal_glops, 436*b3b94faaSDavid Teigland LM_ST_EXCLUSIVE, 437*b3b94faaSDavid Teigland LM_FLAG_NOEXP | 438*b3b94faaSDavid Teigland ((wait) ? 0 : LM_FLAG_TRY) | 439*b3b94faaSDavid Teigland GL_NOCACHE, &j_gh); 440*b3b94faaSDavid Teigland switch (error) { 441*b3b94faaSDavid Teigland case 0: 442*b3b94faaSDavid Teigland break; 443*b3b94faaSDavid Teigland 444*b3b94faaSDavid Teigland case GLR_TRYFAILED: 445*b3b94faaSDavid Teigland fs_info(sdp, "jid=%u: Busy\n", jd->jd_jid); 446*b3b94faaSDavid Teigland error = 0; 447*b3b94faaSDavid Teigland 448*b3b94faaSDavid Teigland default: 449*b3b94faaSDavid Teigland goto fail; 450*b3b94faaSDavid Teigland }; 451*b3b94faaSDavid Teigland 452*b3b94faaSDavid Teigland error = gfs2_glock_nq_init(jd->jd_inode->i_gl, LM_ST_SHARED, 453*b3b94faaSDavid Teigland LM_FLAG_NOEXP, &ji_gh); 454*b3b94faaSDavid Teigland if (error) 455*b3b94faaSDavid Teigland goto fail_gunlock_j; 456*b3b94faaSDavid Teigland 457*b3b94faaSDavid Teigland fs_info(sdp, "jid=%u: Looking at journal...\n", jd->jd_jid); 458*b3b94faaSDavid Teigland 459*b3b94faaSDavid Teigland error = gfs2_jdesc_check(jd); 460*b3b94faaSDavid Teigland if (error) 461*b3b94faaSDavid Teigland goto fail_gunlock_ji; 462*b3b94faaSDavid Teigland 463*b3b94faaSDavid Teigland error = gfs2_find_jhead(jd, &head); 464*b3b94faaSDavid Teigland if (error) 465*b3b94faaSDavid Teigland goto fail_gunlock_ji; 466*b3b94faaSDavid Teigland 467*b3b94faaSDavid Teigland if (!(head.lh_flags & GFS2_LOG_HEAD_UNMOUNT)) { 468*b3b94faaSDavid Teigland fs_info(sdp, "jid=%u: Acquiring the transaction lock...\n", 469*b3b94faaSDavid Teigland jd->jd_jid); 470*b3b94faaSDavid Teigland 471*b3b94faaSDavid Teigland t = jiffies; 472*b3b94faaSDavid Teigland 473*b3b94faaSDavid Teigland /* Acquire a shared hold on the transaction lock */ 474*b3b94faaSDavid Teigland 475*b3b94faaSDavid Teigland error = gfs2_glock_nq_init(sdp->sd_trans_gl, 476*b3b94faaSDavid Teigland LM_ST_SHARED, 477*b3b94faaSDavid Teigland LM_FLAG_NOEXP | 478*b3b94faaSDavid Teigland LM_FLAG_PRIORITY | 479*b3b94faaSDavid Teigland GL_NEVER_RECURSE | 480*b3b94faaSDavid Teigland GL_NOCANCEL | 481*b3b94faaSDavid Teigland GL_NOCACHE, 482*b3b94faaSDavid Teigland &t_gh); 483*b3b94faaSDavid Teigland if (error) 484*b3b94faaSDavid Teigland goto fail_gunlock_ji; 485*b3b94faaSDavid Teigland 486*b3b94faaSDavid Teigland if (test_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags)) { 487*b3b94faaSDavid Teigland if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) 488*b3b94faaSDavid Teigland ro = 1; 489*b3b94faaSDavid Teigland } else { 490*b3b94faaSDavid Teigland if (sdp->sd_vfs->s_flags & MS_RDONLY) 491*b3b94faaSDavid Teigland ro = 1; 492*b3b94faaSDavid Teigland } 493*b3b94faaSDavid Teigland 494*b3b94faaSDavid Teigland if (ro) { 495*b3b94faaSDavid Teigland fs_warn(sdp, "jid=%u: Can't replay: read-only FS\n", 496*b3b94faaSDavid Teigland jd->jd_jid); 497*b3b94faaSDavid Teigland error = -EROFS; 498*b3b94faaSDavid Teigland goto fail_gunlock_tr; 499*b3b94faaSDavid Teigland } 500*b3b94faaSDavid Teigland 501*b3b94faaSDavid Teigland fs_info(sdp, "jid=%u: Replaying journal...\n", jd->jd_jid); 502*b3b94faaSDavid Teigland 503*b3b94faaSDavid Teigland for (pass = 0; pass < 2; pass++) { 504*b3b94faaSDavid Teigland lops_before_scan(jd, &head, pass); 505*b3b94faaSDavid Teigland error = foreach_descriptor(jd, head.lh_tail, 506*b3b94faaSDavid Teigland head.lh_blkno, pass); 507*b3b94faaSDavid Teigland lops_after_scan(jd, error, pass); 508*b3b94faaSDavid Teigland if (error) 509*b3b94faaSDavid Teigland goto fail_gunlock_tr; 510*b3b94faaSDavid Teigland } 511*b3b94faaSDavid Teigland 512*b3b94faaSDavid Teigland error = clean_journal(jd, &head); 513*b3b94faaSDavid Teigland if (error) 514*b3b94faaSDavid Teigland goto fail_gunlock_tr; 515*b3b94faaSDavid Teigland 516*b3b94faaSDavid Teigland gfs2_glock_dq_uninit(&t_gh); 517*b3b94faaSDavid Teigland 518*b3b94faaSDavid Teigland t = DIV_RU(jiffies - t, HZ); 519*b3b94faaSDavid Teigland 520*b3b94faaSDavid Teigland fs_info(sdp, "jid=%u: Journal replayed in %lus\n", 521*b3b94faaSDavid Teigland jd->jd_jid, t); 522*b3b94faaSDavid Teigland } 523*b3b94faaSDavid Teigland 524*b3b94faaSDavid Teigland gfs2_glock_dq_uninit(&ji_gh); 525*b3b94faaSDavid Teigland 526*b3b94faaSDavid Teigland gfs2_lm_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS); 527*b3b94faaSDavid Teigland 528*b3b94faaSDavid Teigland gfs2_glock_dq_uninit(&j_gh); 529*b3b94faaSDavid Teigland 530*b3b94faaSDavid Teigland fs_info(sdp, "jid=%u: Done\n", jd->jd_jid); 531*b3b94faaSDavid Teigland 532*b3b94faaSDavid Teigland return 0; 533*b3b94faaSDavid Teigland 534*b3b94faaSDavid Teigland fail_gunlock_tr: 535*b3b94faaSDavid Teigland gfs2_glock_dq_uninit(&t_gh); 536*b3b94faaSDavid Teigland 537*b3b94faaSDavid Teigland fail_gunlock_ji: 538*b3b94faaSDavid Teigland gfs2_glock_dq_uninit(&ji_gh); 539*b3b94faaSDavid Teigland 540*b3b94faaSDavid Teigland fail_gunlock_j: 541*b3b94faaSDavid Teigland gfs2_glock_dq_uninit(&j_gh); 542*b3b94faaSDavid Teigland 543*b3b94faaSDavid Teigland fs_info(sdp, "jid=%u: %s\n", jd->jd_jid, (error) ? "Failed" : "Done"); 544*b3b94faaSDavid Teigland 545*b3b94faaSDavid Teigland fail: 546*b3b94faaSDavid Teigland gfs2_lm_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP); 547*b3b94faaSDavid Teigland 548*b3b94faaSDavid Teigland return error; 549*b3b94faaSDavid Teigland } 550*b3b94faaSDavid Teigland 551*b3b94faaSDavid Teigland /** 552*b3b94faaSDavid Teigland * gfs2_check_journals - Recover any dirty journals 553*b3b94faaSDavid Teigland * @sdp: the filesystem 554*b3b94faaSDavid Teigland * 555*b3b94faaSDavid Teigland */ 556*b3b94faaSDavid Teigland 557*b3b94faaSDavid Teigland void gfs2_check_journals(struct gfs2_sbd *sdp) 558*b3b94faaSDavid Teigland { 559*b3b94faaSDavid Teigland struct gfs2_jdesc *jd; 560*b3b94faaSDavid Teigland 561*b3b94faaSDavid Teigland for (;;) { 562*b3b94faaSDavid Teigland jd = gfs2_jdesc_find_dirty(sdp); 563*b3b94faaSDavid Teigland if (!jd) 564*b3b94faaSDavid Teigland break; 565*b3b94faaSDavid Teigland 566*b3b94faaSDavid Teigland if (jd != sdp->sd_jdesc) 567*b3b94faaSDavid Teigland gfs2_recover_journal(jd, NO_WAIT); 568*b3b94faaSDavid Teigland } 569*b3b94faaSDavid Teigland } 570*b3b94faaSDavid Teigland 571