| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved. | 
| Steven Whitehouse | 3a8a9a1 | 2006-05-18 15:09:15 -0400 | [diff] [blame] | 3 | * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved. | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 4 | * | 
|  | 5 | * This copyrighted material is made available to anyone wishing to use, | 
|  | 6 | * modify, copy, or redistribute it subject to the terms and conditions | 
| Steven Whitehouse | e9fc2aa | 2006-09-01 11:05:15 -0400 | [diff] [blame] | 7 | * of the GNU General Public License version 2. | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 8 | */ | 
|  | 9 |  | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 10 | #include <linux/slab.h> | 
|  | 11 | #include <linux/spinlock.h> | 
|  | 12 | #include <linux/completion.h> | 
|  | 13 | #include <linux/buffer_head.h> | 
|  | 14 | #include <linux/crc32.h> | 
| Steven Whitehouse | 5c676f6 | 2006-02-27 17:23:27 -0500 | [diff] [blame] | 15 | #include <linux/gfs2_ondisk.h> | 
| Fabio Massimo Di Nitto | 7d30859 | 2006-09-19 07:56:29 +0200 | [diff] [blame] | 16 | #include <linux/lm_interface.h> | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 17 | #include <asm/uaccess.h> | 
|  | 18 |  | 
|  | 19 | #include "gfs2.h" | 
| Steven Whitehouse | 5c676f6 | 2006-02-27 17:23:27 -0500 | [diff] [blame] | 20 | #include "incore.h" | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 21 | #include "glock.h" | 
|  | 22 | #include "lm.h" | 
| Steven Whitehouse | 5c676f6 | 2006-02-27 17:23:27 -0500 | [diff] [blame] | 23 | #include "util.h" | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 24 |  | 
| Christoph Lameter | e18b890 | 2006-12-06 20:33:20 -0800 | [diff] [blame] | 25 | struct kmem_cache *gfs2_glock_cachep __read_mostly; | 
|  | 26 | struct kmem_cache *gfs2_inode_cachep __read_mostly; | 
|  | 27 | struct kmem_cache *gfs2_bufdata_cachep __read_mostly; | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 28 |  | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 29 | void gfs2_assert_i(struct gfs2_sbd *sdp) | 
|  | 30 | { | 
|  | 31 | printk(KERN_EMERG "GFS2: fsid=%s: fatal assertion failed\n", | 
|  | 32 | sdp->sd_fsname); | 
|  | 33 | } | 
|  | 34 |  | 
|  | 35 | /** | 
|  | 36 | * gfs2_assert_withdraw_i - Cause the machine to withdraw if @assertion is false | 
|  | 37 | * Returns: -1 if this call withdrew the machine, | 
|  | 38 | *          -2 if it was already withdrawn | 
|  | 39 | */ | 
|  | 40 |  | 
|  | 41 | int gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion, | 
|  | 42 | const char *function, char *file, unsigned int line) | 
|  | 43 | { | 
|  | 44 | int me; | 
|  | 45 | me = gfs2_lm_withdraw(sdp, | 
|  | 46 | "GFS2: fsid=%s: fatal: assertion \"%s\" failed\n" | 
|  | 47 | "GFS2: fsid=%s:   function = %s, file = %s, line = %u\n", | 
|  | 48 | sdp->sd_fsname, assertion, | 
|  | 49 | sdp->sd_fsname, function, file, line); | 
| Steven Whitehouse | 18ec7d5 | 2006-02-08 11:50:51 +0000 | [diff] [blame] | 50 | dump_stack(); | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 51 | return (me) ? -1 : -2; | 
|  | 52 | } | 
|  | 53 |  | 
|  | 54 | /** | 
|  | 55 | * gfs2_assert_warn_i - Print a message to the console if @assertion is false | 
|  | 56 | * Returns: -1 if we printed something | 
|  | 57 | *          -2 if we didn't | 
|  | 58 | */ | 
|  | 59 |  | 
|  | 60 | int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion, | 
|  | 61 | const char *function, char *file, unsigned int line) | 
|  | 62 | { | 
|  | 63 | if (time_before(jiffies, | 
|  | 64 | sdp->sd_last_warning + | 
|  | 65 | gfs2_tune_get(sdp, gt_complain_secs) * HZ)) | 
|  | 66 | return -2; | 
|  | 67 |  | 
|  | 68 | printk(KERN_WARNING | 
|  | 69 | "GFS2: fsid=%s: warning: assertion \"%s\" failed\n" | 
|  | 70 | "GFS2: fsid=%s:   function = %s, file = %s, line = %u\n", | 
|  | 71 | sdp->sd_fsname, assertion, | 
|  | 72 | sdp->sd_fsname, function, file, line); | 
|  | 73 |  | 
|  | 74 | if (sdp->sd_args.ar_debug) | 
|  | 75 | BUG(); | 
| Steven Whitehouse | 18ec7d5 | 2006-02-08 11:50:51 +0000 | [diff] [blame] | 76 | else | 
|  | 77 | dump_stack(); | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 78 |  | 
|  | 79 | sdp->sd_last_warning = jiffies; | 
|  | 80 |  | 
|  | 81 | return -1; | 
|  | 82 | } | 
|  | 83 |  | 
|  | 84 | /** | 
|  | 85 | * gfs2_consist_i - Flag a filesystem consistency error and withdraw | 
|  | 86 | * Returns: -1 if this call withdrew the machine, | 
|  | 87 | *          0 if it was already withdrawn | 
|  | 88 | */ | 
|  | 89 |  | 
|  | 90 | int gfs2_consist_i(struct gfs2_sbd *sdp, int cluster_wide, const char *function, | 
|  | 91 | char *file, unsigned int line) | 
|  | 92 | { | 
|  | 93 | int rv; | 
|  | 94 | rv = gfs2_lm_withdraw(sdp, | 
|  | 95 | "GFS2: fsid=%s: fatal: filesystem consistency error\n" | 
|  | 96 | "GFS2: fsid=%s:   function = %s, file = %s, line = %u\n", | 
|  | 97 | sdp->sd_fsname, | 
|  | 98 | sdp->sd_fsname, function, file, line); | 
|  | 99 | return rv; | 
|  | 100 | } | 
|  | 101 |  | 
|  | 102 | /** | 
|  | 103 | * gfs2_consist_inode_i - Flag an inode consistency error and withdraw | 
|  | 104 | * Returns: -1 if this call withdrew the machine, | 
|  | 105 | *          0 if it was already withdrawn | 
|  | 106 | */ | 
|  | 107 |  | 
|  | 108 | int gfs2_consist_inode_i(struct gfs2_inode *ip, int cluster_wide, | 
|  | 109 | const char *function, char *file, unsigned int line) | 
|  | 110 | { | 
| Steven Whitehouse | feaa7bb | 2006-06-14 15:32:57 -0400 | [diff] [blame] | 111 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 112 | int rv; | 
|  | 113 | rv = gfs2_lm_withdraw(sdp, | 
|  | 114 | "GFS2: fsid=%s: fatal: filesystem consistency error\n" | 
|  | 115 | "GFS2: fsid=%s:   inode = %llu %llu\n" | 
|  | 116 | "GFS2: fsid=%s:   function = %s, file = %s, line = %u\n", | 
|  | 117 | sdp->sd_fsname, | 
| Steven Whitehouse | 382066d | 2006-05-24 10:22:09 -0400 | [diff] [blame] | 118 | sdp->sd_fsname, (unsigned long long)ip->i_num.no_formal_ino, | 
|  | 119 | (unsigned long long)ip->i_num.no_addr, | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 120 | sdp->sd_fsname, function, file, line); | 
|  | 121 | return rv; | 
|  | 122 | } | 
|  | 123 |  | 
|  | 124 | /** | 
|  | 125 | * gfs2_consist_rgrpd_i - Flag a RG consistency error and withdraw | 
|  | 126 | * Returns: -1 if this call withdrew the machine, | 
|  | 127 | *          0 if it was already withdrawn | 
|  | 128 | */ | 
|  | 129 |  | 
|  | 130 | int gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, int cluster_wide, | 
|  | 131 | const char *function, char *file, unsigned int line) | 
|  | 132 | { | 
|  | 133 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 
|  | 134 | int rv; | 
|  | 135 | rv = gfs2_lm_withdraw(sdp, | 
|  | 136 | "GFS2: fsid=%s: fatal: filesystem consistency error\n" | 
|  | 137 | "GFS2: fsid=%s:   RG = %llu\n" | 
|  | 138 | "GFS2: fsid=%s:   function = %s, file = %s, line = %u\n", | 
|  | 139 | sdp->sd_fsname, | 
| Steven Whitehouse | 382066d | 2006-05-24 10:22:09 -0400 | [diff] [blame] | 140 | sdp->sd_fsname, (unsigned long long)rgd->rd_ri.ri_addr, | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 141 | sdp->sd_fsname, function, file, line); | 
|  | 142 | return rv; | 
|  | 143 | } | 
|  | 144 |  | 
|  | 145 | /** | 
|  | 146 | * gfs2_meta_check_ii - Flag a magic number consistency error and withdraw | 
|  | 147 | * Returns: -1 if this call withdrew the machine, | 
|  | 148 | *          -2 if it was already withdrawn | 
|  | 149 | */ | 
|  | 150 |  | 
|  | 151 | int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, | 
|  | 152 | const char *type, const char *function, char *file, | 
|  | 153 | unsigned int line) | 
|  | 154 | { | 
|  | 155 | int me; | 
|  | 156 | me = gfs2_lm_withdraw(sdp, | 
|  | 157 | "GFS2: fsid=%s: fatal: invalid metadata block\n" | 
|  | 158 | "GFS2: fsid=%s:   bh = %llu (%s)\n" | 
|  | 159 | "GFS2: fsid=%s:   function = %s, file = %s, line = %u\n", | 
|  | 160 | sdp->sd_fsname, | 
| Steven Whitehouse | 382066d | 2006-05-24 10:22:09 -0400 | [diff] [blame] | 161 | sdp->sd_fsname, (unsigned long long)bh->b_blocknr, type, | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 162 | sdp->sd_fsname, function, file, line); | 
|  | 163 | return (me) ? -1 : -2; | 
|  | 164 | } | 
|  | 165 |  | 
|  | 166 | /** | 
|  | 167 | * gfs2_metatype_check_ii - Flag a metadata type consistency error and withdraw | 
|  | 168 | * Returns: -1 if this call withdrew the machine, | 
|  | 169 | *          -2 if it was already withdrawn | 
|  | 170 | */ | 
|  | 171 |  | 
|  | 172 | int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, | 
| Steven Whitehouse | cd91549 | 2006-09-04 12:49:07 -0400 | [diff] [blame] | 173 | u16 type, u16 t, const char *function, | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 174 | char *file, unsigned int line) | 
|  | 175 | { | 
|  | 176 | int me; | 
|  | 177 | me = gfs2_lm_withdraw(sdp, | 
|  | 178 | "GFS2: fsid=%s: fatal: invalid metadata block\n" | 
|  | 179 | "GFS2: fsid=%s:   bh = %llu (type: exp=%u, found=%u)\n" | 
|  | 180 | "GFS2: fsid=%s:   function = %s, file = %s, line = %u\n", | 
|  | 181 | sdp->sd_fsname, | 
| Steven Whitehouse | 382066d | 2006-05-24 10:22:09 -0400 | [diff] [blame] | 182 | sdp->sd_fsname, (unsigned long long)bh->b_blocknr, type, t, | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 183 | sdp->sd_fsname, function, file, line); | 
|  | 184 | return (me) ? -1 : -2; | 
|  | 185 | } | 
|  | 186 |  | 
|  | 187 | /** | 
|  | 188 | * gfs2_io_error_i - Flag an I/O error and withdraw | 
|  | 189 | * Returns: -1 if this call withdrew the machine, | 
|  | 190 | *          0 if it was already withdrawn | 
|  | 191 | */ | 
|  | 192 |  | 
|  | 193 | int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file, | 
|  | 194 | unsigned int line) | 
|  | 195 | { | 
|  | 196 | int rv; | 
|  | 197 | rv = gfs2_lm_withdraw(sdp, | 
|  | 198 | "GFS2: fsid=%s: fatal: I/O error\n" | 
|  | 199 | "GFS2: fsid=%s:   function = %s, file = %s, line = %u\n", | 
|  | 200 | sdp->sd_fsname, | 
|  | 201 | sdp->sd_fsname, function, file, line); | 
|  | 202 | return rv; | 
|  | 203 | } | 
|  | 204 |  | 
|  | 205 | /** | 
|  | 206 | * gfs2_io_error_bh_i - Flag a buffer I/O error and withdraw | 
|  | 207 | * Returns: -1 if this call withdrew the machine, | 
|  | 208 | *          0 if it was already withdrawn | 
|  | 209 | */ | 
|  | 210 |  | 
|  | 211 | int gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh, | 
|  | 212 | const char *function, char *file, unsigned int line) | 
|  | 213 | { | 
|  | 214 | int rv; | 
|  | 215 | rv = gfs2_lm_withdraw(sdp, | 
|  | 216 | "GFS2: fsid=%s: fatal: I/O error\n" | 
|  | 217 | "GFS2: fsid=%s:   block = %llu\n" | 
|  | 218 | "GFS2: fsid=%s:   function = %s, file = %s, line = %u\n", | 
|  | 219 | sdp->sd_fsname, | 
| Steven Whitehouse | 382066d | 2006-05-24 10:22:09 -0400 | [diff] [blame] | 220 | sdp->sd_fsname, (unsigned long long)bh->b_blocknr, | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 221 | sdp->sd_fsname, function, file, line); | 
|  | 222 | return rv; | 
|  | 223 | } | 
|  | 224 |  | 
| David Teigland | b3b94fa | 2006-01-16 16:50:04 +0000 | [diff] [blame] | 225 | void gfs2_icbit_munge(struct gfs2_sbd *sdp, unsigned char **bitmap, | 
|  | 226 | unsigned int bit, int new_value) | 
|  | 227 | { | 
|  | 228 | unsigned int c, o, b = bit; | 
|  | 229 | int old_value; | 
|  | 230 |  | 
|  | 231 | c = b / (8 * PAGE_SIZE); | 
|  | 232 | b %= 8 * PAGE_SIZE; | 
|  | 233 | o = b / 8; | 
|  | 234 | b %= 8; | 
|  | 235 |  | 
|  | 236 | old_value = (bitmap[c][o] & (1 << b)); | 
|  | 237 | gfs2_assert_withdraw(sdp, !old_value != !new_value); | 
|  | 238 |  | 
|  | 239 | if (new_value) | 
|  | 240 | bitmap[c][o] |= 1 << b; | 
|  | 241 | else | 
|  | 242 | bitmap[c][o] &= ~(1 << b); | 
|  | 243 | } | 
|  | 244 |  |