1 /* 2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 3 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 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 7 * of the GNU General Public License version 2. 8 */ 9 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> 15 #include <linux/gfs2_ondisk.h> 16 #include <linux/lm_interface.h> 17 #include <asm/uaccess.h> 18 19 #include "gfs2.h" 20 #include "incore.h" 21 #include "glock.h" 22 #include "util.h" 23 24 struct kmem_cache *gfs2_glock_cachep __read_mostly; 25 struct kmem_cache *gfs2_inode_cachep __read_mostly; 26 struct kmem_cache *gfs2_bufdata_cachep __read_mostly; 27 struct kmem_cache *gfs2_rgrpd_cachep __read_mostly; 28 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 int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...) 36 { 37 va_list args; 38 39 if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags)) 40 return 0; 41 42 va_start(args, fmt); 43 vprintk(fmt, args); 44 va_end(args); 45 46 fs_err(sdp, "about to withdraw this file system\n"); 47 BUG_ON(sdp->sd_args.ar_debug); 48 49 fs_err(sdp, "telling LM to withdraw\n"); 50 gfs2_withdraw_lockproto(&sdp->sd_lockstruct); 51 fs_err(sdp, "withdrawn\n"); 52 dump_stack(); 53 54 return -1; 55 } 56 57 /** 58 * gfs2_assert_withdraw_i - Cause the machine to withdraw if @assertion is false 59 * Returns: -1 if this call withdrew the machine, 60 * -2 if it was already withdrawn 61 */ 62 63 int gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion, 64 const char *function, char *file, unsigned int line) 65 { 66 int me; 67 me = gfs2_lm_withdraw(sdp, 68 "GFS2: fsid=%s: fatal: assertion \"%s\" failed\n" 69 "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", 70 sdp->sd_fsname, assertion, 71 sdp->sd_fsname, function, file, line); 72 dump_stack(); 73 return (me) ? -1 : -2; 74 } 75 76 /** 77 * gfs2_assert_warn_i - Print a message to the console if @assertion is false 78 * Returns: -1 if we printed something 79 * -2 if we didn't 80 */ 81 82 int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion, 83 const char *function, char *file, unsigned int line) 84 { 85 if (time_before(jiffies, 86 sdp->sd_last_warning + 87 gfs2_tune_get(sdp, gt_complain_secs) * HZ)) 88 return -2; 89 90 printk(KERN_WARNING 91 "GFS2: fsid=%s: warning: assertion \"%s\" failed\n" 92 "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", 93 sdp->sd_fsname, assertion, 94 sdp->sd_fsname, function, file, line); 95 96 if (sdp->sd_args.ar_debug) 97 BUG(); 98 else 99 dump_stack(); 100 101 sdp->sd_last_warning = jiffies; 102 103 return -1; 104 } 105 106 /** 107 * gfs2_consist_i - Flag a filesystem consistency error and withdraw 108 * Returns: -1 if this call withdrew the machine, 109 * 0 if it was already withdrawn 110 */ 111 112 int gfs2_consist_i(struct gfs2_sbd *sdp, int cluster_wide, const char *function, 113 char *file, unsigned int line) 114 { 115 int rv; 116 rv = gfs2_lm_withdraw(sdp, 117 "GFS2: fsid=%s: fatal: filesystem consistency error\n" 118 "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", 119 sdp->sd_fsname, 120 sdp->sd_fsname, function, file, line); 121 return rv; 122 } 123 124 /** 125 * gfs2_consist_inode_i - Flag an inode 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_inode_i(struct gfs2_inode *ip, int cluster_wide, 131 const char *function, char *file, unsigned int line) 132 { 133 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 134 int rv; 135 rv = gfs2_lm_withdraw(sdp, 136 "GFS2: fsid=%s: fatal: filesystem consistency error\n" 137 "GFS2: fsid=%s: inode = %llu %llu\n" 138 "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", 139 sdp->sd_fsname, 140 sdp->sd_fsname, (unsigned long long)ip->i_no_formal_ino, 141 (unsigned long long)ip->i_no_addr, 142 sdp->sd_fsname, function, file, line); 143 return rv; 144 } 145 146 /** 147 * gfs2_consist_rgrpd_i - Flag a RG consistency error and withdraw 148 * Returns: -1 if this call withdrew the machine, 149 * 0 if it was already withdrawn 150 */ 151 152 int gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, int cluster_wide, 153 const char *function, char *file, unsigned int line) 154 { 155 struct gfs2_sbd *sdp = rgd->rd_sbd; 156 int rv; 157 rv = gfs2_lm_withdraw(sdp, 158 "GFS2: fsid=%s: fatal: filesystem consistency error\n" 159 "GFS2: fsid=%s: RG = %llu\n" 160 "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", 161 sdp->sd_fsname, 162 sdp->sd_fsname, (unsigned long long)rgd->rd_addr, 163 sdp->sd_fsname, function, file, line); 164 return rv; 165 } 166 167 /** 168 * gfs2_meta_check_ii - Flag a magic number consistency error and withdraw 169 * Returns: -1 if this call withdrew the machine, 170 * -2 if it was already withdrawn 171 */ 172 173 int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, 174 const char *type, const char *function, char *file, 175 unsigned int line) 176 { 177 int me; 178 me = gfs2_lm_withdraw(sdp, 179 "GFS2: fsid=%s: fatal: invalid metadata block\n" 180 "GFS2: fsid=%s: bh = %llu (%s)\n" 181 "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", 182 sdp->sd_fsname, 183 sdp->sd_fsname, (unsigned long long)bh->b_blocknr, type, 184 sdp->sd_fsname, function, file, line); 185 return (me) ? -1 : -2; 186 } 187 188 /** 189 * gfs2_metatype_check_ii - Flag a metadata type consistency error and withdraw 190 * Returns: -1 if this call withdrew the machine, 191 * -2 if it was already withdrawn 192 */ 193 194 int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, 195 u16 type, u16 t, const char *function, 196 char *file, unsigned int line) 197 { 198 int me; 199 me = gfs2_lm_withdraw(sdp, 200 "GFS2: fsid=%s: fatal: invalid metadata block\n" 201 "GFS2: fsid=%s: bh = %llu (type: exp=%u, found=%u)\n" 202 "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", 203 sdp->sd_fsname, 204 sdp->sd_fsname, (unsigned long long)bh->b_blocknr, type, t, 205 sdp->sd_fsname, function, file, line); 206 return (me) ? -1 : -2; 207 } 208 209 /** 210 * gfs2_io_error_i - Flag an I/O error and withdraw 211 * Returns: -1 if this call withdrew the machine, 212 * 0 if it was already withdrawn 213 */ 214 215 int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file, 216 unsigned int line) 217 { 218 int rv; 219 rv = gfs2_lm_withdraw(sdp, 220 "GFS2: fsid=%s: fatal: I/O error\n" 221 "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", 222 sdp->sd_fsname, 223 sdp->sd_fsname, function, file, line); 224 return rv; 225 } 226 227 /** 228 * gfs2_io_error_bh_i - Flag a buffer I/O error and withdraw 229 * Returns: -1 if this call withdrew the machine, 230 * 0 if it was already withdrawn 231 */ 232 233 int gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh, 234 const char *function, char *file, unsigned int line) 235 { 236 int rv; 237 rv = gfs2_lm_withdraw(sdp, 238 "GFS2: fsid=%s: fatal: I/O error\n" 239 "GFS2: fsid=%s: block = %llu\n" 240 "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", 241 sdp->sd_fsname, 242 sdp->sd_fsname, (unsigned long long)bh->b_blocknr, 243 sdp->sd_fsname, function, file, line); 244 return rv; 245 } 246 247 void gfs2_icbit_munge(struct gfs2_sbd *sdp, unsigned char **bitmap, 248 unsigned int bit, int new_value) 249 { 250 unsigned int c, o, b = bit; 251 int old_value; 252 253 c = b / (8 * PAGE_SIZE); 254 b %= 8 * PAGE_SIZE; 255 o = b / 8; 256 b %= 8; 257 258 old_value = (bitmap[c][o] & (1 << b)); 259 gfs2_assert_withdraw(sdp, !old_value != !new_value); 260 261 if (new_value) 262 bitmap[c][o] |= 1 << b; 263 else 264 bitmap[c][o] &= ~(1 << b); 265 } 266 267