| /* |
| * Copyright 1996-2004 by Hans Reiser, licensing governed by |
| * reiserfsprogs/README |
| */ |
| |
| #define _GNU_SOURCE |
| |
| #include "includes.h" |
| #include <stdarg.h> |
| #include <limits.h> |
| #include <printf.h> |
| #include <limits.h> |
| #include <time.h> |
| |
| #if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H) |
| # include <uuid/uuid.h> |
| #endif |
| |
| #ifndef HAVE_REGISTER_PRINTF_SPECIFIER |
| #define register_printf_specifier(x, y, z) register_printf_function(x, y, z) |
| static int arginfo_ptr(const struct printf_info *info, size_t n, int *argtypes) |
| #else |
| static int arginfo_ptr(const struct printf_info *info, size_t n, |
| int *argtypes, int *size) |
| #endif |
| { |
| if (n > 0) { |
| argtypes[0] = PA_FLAG_PTR; |
| #ifdef HAVE_REGISTER_PRINTF_SPECIFIER |
| size[0] = sizeof(void *); |
| #endif |
| } |
| return 1; |
| } |
| |
| #define FPRINTF \ |
| if (len == -1) {\ |
| return -1;\ |
| }\ |
| len = fprintf (stream, "%*s",\ |
| info->left ? -info->width : info->width, buffer);\ |
| free (buffer);\ |
| return len;\ |
| |
| |
| /* %b */ |
| static int print_block_head(FILE * stream, |
| const struct printf_info *info, |
| const void *const *args) |
| { |
| const struct buffer_head *bh; |
| char *buffer; |
| int len; |
| |
| bh = *((const struct buffer_head **)(args[0])); |
| len = asprintf(&buffer, "level=%d, nr_items=%d, free_space=%d rdkey", |
| B_LEVEL(bh), B_NR_ITEMS(bh), B_FREE_SPACE(bh)); |
| FPRINTF; |
| } |
| |
| /* %K */ |
| static int print_short_key(FILE * stream, |
| const struct printf_info *info, |
| const void *const *args) |
| { |
| const struct reiserfs_key *key; |
| char *buffer; |
| int len; |
| |
| key = *((const struct reiserfs_key **)(args[0])); |
| len = asprintf(&buffer, "[%u %u]", get_key_dirid(key), |
| get_key_objectid(key)); |
| FPRINTF; |
| } |
| |
| /* %k */ |
| static int print_key(FILE * stream, |
| const struct printf_info *info, const void *const *args) |
| { |
| const struct reiserfs_key *key; |
| char *buffer; |
| int len; |
| |
| key = *((const struct reiserfs_key **)(args[0])); |
| len = asprintf(&buffer, "[%u %u 0x%Lx %s (%d)]", |
| get_key_dirid(key), get_key_objectid(key), |
| (unsigned long long)get_offset(key), key_of_what(key), |
| get_type(key)); |
| FPRINTF; |
| } |
| |
| /* %H */ |
| static int print_item_head(FILE * stream, |
| const struct printf_info *info, |
| const void *const *args) |
| { |
| const struct item_head *ih; |
| char *buffer; |
| int len; |
| |
| ih = *((const struct item_head **)(args[0])); |
| len = asprintf(&buffer, "%u %u 0x%Lx %s (%d), " |
| "len %u, location %u entry count %u, fsck need %u, format %s", |
| get_key_dirid(&ih->ih_key), |
| get_key_objectid(&ih->ih_key), |
| (unsigned long long)get_offset(&ih->ih_key), |
| key_of_what(&ih->ih_key), get_type(&ih->ih_key), |
| get_ih_item_len(ih), get_ih_location(ih), |
| get_ih_entry_count(ih), get_ih_flags(ih), |
| get_ih_key_format(ih) == |
| KEY_FORMAT_2 ? "new" |
| : ((get_ih_key_format(ih) == |
| KEY_FORMAT_1) ? "old" : "BAD")); |
| FPRINTF; |
| } |
| |
| static int print_disk_child(FILE * stream, |
| const struct printf_info *info, |
| const void *const *args) |
| { |
| const struct disk_child *dc; |
| char *buffer; |
| int len; |
| |
| dc = *((const struct disk_child **)(args[0])); |
| len = |
| asprintf(&buffer, "[dc_number=%u, dc_size=%u]", |
| get_dc_child_blocknr(dc), get_dc_child_size(dc)); |
| FPRINTF; |
| } |
| |
| char ftypelet(mode_t mode) |
| { |
| if (S_ISBLK(mode)) |
| return 'b'; |
| if (S_ISCHR(mode)) |
| return 'c'; |
| if (S_ISDIR(mode)) |
| return 'd'; |
| if (S_ISREG(mode)) |
| return '-'; |
| if (S_ISFIFO(mode)) |
| return 'p'; |
| if (S_ISLNK(mode)) |
| return 'l'; |
| if (S_ISSOCK(mode)) |
| return 's'; |
| return '?'; |
| } |
| |
| static int rwx(FILE * stream, mode_t mode) |
| { |
| return fprintf(stream, "%c%c%c", |
| (mode & S_IRUSR) ? 'r' : '-', |
| (mode & S_IWUSR) ? 'w' : '-', |
| (mode & S_IXUSR) ? 'x' : '-'); |
| } |
| |
| /* %M */ |
| static int print_sd_mode(FILE * stream, |
| const struct printf_info *info, |
| const void *const *args) |
| { |
| int len = 0; |
| __u16 mode; |
| |
| mode = *(mode_t *) args[0]; |
| len = fprintf(stream, "%c", ftypelet(mode)); |
| len += rwx(stream, (mode & 0700) << 0); |
| len += rwx(stream, (mode & 0070) << 3); |
| len += rwx(stream, (mode & 0007) << 6); |
| return len; |
| } |
| |
| /* %U */ |
| static int print_sd_uuid(FILE * stream, |
| const struct printf_info *info, |
| const void *const *args) |
| { |
| #if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H) |
| const unsigned char *uuid = *((const unsigned char **)(args[0])); |
| char buf[37]; |
| |
| buf[36] = '\0'; |
| uuid_unparse(uuid, buf); |
| return fprintf(stream, "%s", buf); |
| #else |
| return fprintf(stream, "<no libuuid installed>"); |
| #endif |
| } |
| |
| void reiserfs_warning(FILE * fp, const char *fmt, ...) |
| { |
| static int registered = 0; |
| va_list args; |
| |
| if (!registered) { |
| registered = 1; |
| |
| register_printf_specifier('K', print_short_key, arginfo_ptr); |
| register_printf_specifier('k', print_key, arginfo_ptr); |
| register_printf_specifier('H', print_item_head, arginfo_ptr); |
| register_printf_specifier('b', print_block_head, arginfo_ptr); |
| register_printf_specifier('y', print_disk_child, arginfo_ptr); |
| register_printf_specifier('M', print_sd_mode, arginfo_ptr); |
| register_printf_specifier('U', print_sd_uuid, arginfo_ptr); |
| } |
| |
| va_start(args, fmt); |
| vfprintf(fp, fmt, args); |
| va_end(args); |
| } |
| |
| static void print_directory_item(FILE *fp, reiserfs_filsys_t fs, |
| struct buffer_head *bh, struct item_head *ih) |
| { |
| int i; |
| int namelen; |
| struct reiserfs_de_head *deh; |
| char *name; |
| /* static char namebuf [80];*/ |
| |
| if (!I_IS_DIRECTORY_ITEM(ih)) |
| return; |
| |
| //printk ("\n%2%-25s%-30s%-15s%-15s%-15s\n", " Name", "length", "Object key", "Hash", "Gen number", "Status"); |
| reiserfs_warning(fp, "%3s: %-25s%s%-22s%-12s%s\n", "###", "Name", |
| "length", " Object key", " Hash", "Gen number"); |
| deh = B_I_DEH(bh, ih); |
| for (i = 0; i < get_ih_entry_count(ih); i++, deh++) { |
| if (dir_entry_bad_location(deh, ih, i == 0 ? 1 : 0)) { |
| reiserfs_warning(fp, |
| "%3d: wrong entry location %u, deh_offset %u\n", |
| i, get_deh_location(deh), |
| get_deh_offset(deh)); |
| continue; |
| } |
| if (i |
| && dir_entry_bad_location(deh - 1, ih, |
| ((i - 1) == 0) ? 1 : 0)) |
| /* previous entry has bad location so we can not calculate entry |
| length */ |
| namelen = 25; |
| else |
| namelen = name_in_entry_length(ih, deh, i); |
| |
| name = name_in_entry(deh, i); |
| reiserfs_warning(fp, |
| "%3d: \"%-25.*s\"(%3d)%20K%12d%5d, loc %u, state %x %s\n", |
| i, namelen, name, namelen, |
| (struct reiserfs_key *)&(deh->deh2_dir_id), |
| GET_HASH_VALUE(get_deh_offset(deh)), |
| GET_GENERATION_NUMBER(get_deh_offset(deh)), |
| get_deh_location(deh), get_deh_state(deh), |
| code2name(find_hash_in_use |
| (name, namelen, get_deh_offset(deh), |
| fs ? get_sb_hash_code(fs-> |
| fs_ondisk_sb) |
| : UNSET_HASH))); |
| /*fs ? (is_properly_hashed (fs, name, namelen, deh_offset (deh)) ? "" : "(BROKEN)") : "??"); */ |
| } |
| } |
| |
| // |
| // printing of indirect item |
| // |
| static void start_new_sequence(__u32 * start, int *len, __u32 new) |
| { |
| *start = new; |
| *len = 1; |
| } |
| |
| static int sequence_finished(__u32 start, int *len, __u32 new) |
| { |
| if (start == INT_MAX) |
| return 1; |
| |
| if (start == 0 && new == 0) { |
| (*len)++; |
| return 0; |
| } |
| if (start != 0 && (start + *len) == new) { |
| (*len)++; |
| return 0; |
| } |
| return 1; |
| } |
| |
| static void print_sequence(FILE * fp, __u32 start, int len) |
| { |
| if (start == INT_MAX) |
| return; |
| |
| if (len == 1) |
| reiserfs_warning(fp, " %u", start); |
| else |
| reiserfs_warning(fp, " %u(%d)", start, len); |
| } |
| |
| void print_indirect_item(FILE * fp, struct buffer_head *bh, int item_num) |
| { |
| struct item_head *ih; |
| unsigned int j; |
| __le32 *unp; |
| __u32 prev = INT_MAX; |
| int num = 0; |
| |
| ih = item_head(bh, item_num); |
| unp = (__le32 *) ih_item_body(bh, ih); |
| |
| if (get_ih_item_len(ih) % UNFM_P_SIZE) |
| reiserfs_warning(fp, "print_indirect_item: invalid item len"); |
| |
| reiserfs_warning(fp, "%d pointer%s\n[", I_UNFM_NUM(ih), |
| I_UNFM_NUM(ih) != 1 ? "s" : ""); |
| for (j = 0; j < I_UNFM_NUM(ih); j++) { |
| if (sequence_finished(prev, &num, d32_get(unp, j))) { |
| print_sequence(fp, prev, num); |
| start_new_sequence(&prev, &num, d32_get(unp, j)); |
| } |
| } |
| print_sequence(fp, prev, num); |
| reiserfs_warning(fp, "]\n"); |
| } |
| |
| static char timebuf[256]; |
| |
| static char *timestamp(time_t t) |
| { |
| strftime(timebuf, 256, "%d/%Y %T", localtime(&t)); |
| return timebuf; |
| } |
| |
| static int print_stat_data(FILE * fp, struct buffer_head *bh, |
| struct item_head *ih, int alltimes) |
| { |
| int retval; |
| |
| /* we cannot figure out if it is new stat data or old by key_format |
| macro. Stat data's key looks identical in both formats */ |
| if (get_ih_key_format(ih) == KEY_FORMAT_1) { |
| struct stat_data_v1 *sd_v1 = |
| (struct stat_data_v1 *)ih_item_body(bh, ih); |
| reiserfs_warning(fp, |
| "(OLD SD), mode %M, size %u, nlink %u, uid %u, FDB %u, mtime %s blocks %u", |
| sd_v1_mode(sd_v1), sd_v1_size(sd_v1), |
| sd_v1_nlink(sd_v1), sd_v1_uid(sd_v1), |
| sd_v1_first_direct_byte(sd_v1), |
| timestamp(sd_v1_mtime(sd_v1)), |
| sd_v1_blocks(sd_v1)); |
| retval = (S_ISLNK(sd_v1_mode(sd_v1))) ? 1 : 0; |
| if (alltimes) |
| reiserfs_warning(fp, "%s %s\n", |
| timestamp(sd_v1_ctime(sd_v1)), |
| timestamp(sd_v1_atime(sd_v1))); |
| } else { |
| struct stat_data *sd = (struct stat_data *)ih_item_body(bh, ih); |
| reiserfs_warning(fp, |
| "(NEW SD), mode %M, size %Lu, nlink %u, mtime %s blocks %u, uid %u", |
| sd_v2_mode(sd), sd_v2_size(sd), |
| sd_v2_nlink(sd), timestamp(sd_v2_mtime(sd)), |
| sd_v2_blocks(sd), sd_v2_uid(sd)); |
| retval = (S_ISLNK(sd_v2_mode(sd))) ? 1 : 0; |
| if (alltimes) |
| reiserfs_warning(fp, "%s %s\n", |
| timestamp(sd_v2_ctime(sd)), |
| timestamp(sd_v2_atime(sd))); |
| } |
| |
| reiserfs_warning(fp, "\n"); |
| return retval; |
| } |
| |
| /* used by debugreiserfs/scan.c */ |
| void reiserfs_print_item(FILE * fp, struct buffer_head *bh, |
| struct item_head *ih) |
| { |
| reiserfs_warning(fp, "block %lu, item %d: %H\n", |
| bh->b_blocknr, |
| (ih - |
| item_head(bh, 0)) / sizeof(struct item_head), |
| ih); |
| if (is_stat_data_ih(ih)) { |
| print_stat_data(fp, bh, ih, 0 /*all times */ ); |
| return; |
| } |
| if (is_indirect_ih(ih)) { |
| print_indirect_item(fp, bh, ih - item_head(bh, 0)); |
| return; |
| } |
| if (is_direct_ih(ih)) { |
| reiserfs_warning(fp, |
| "direct item: block %lu, start %d, %d bytes\n", |
| bh->b_blocknr, get_ih_location(ih), |
| get_ih_item_len(ih)); |
| return; |
| } |
| |
| print_directory_item(fp, NULL, bh, ih); |
| } |
| |
| /* this prints internal nodes (4 keys/items in line) (dc_number, |
| dc_size)[k_dirid, k_objectid, k_offset, k_uniqueness](dc_number, |
| dc_size)...*/ |
| static int print_internal(FILE * fp, const struct buffer_head *bh, int first, |
| int last) |
| { |
| struct reiserfs_key *key; |
| struct disk_child *dc; |
| int i; |
| int from, to; |
| |
| if (!is_internal_node(bh)) |
| return 1; |
| |
| if (first == -1) { |
| from = 0; |
| to = B_NR_ITEMS(bh); |
| } else { |
| from = first; |
| to = last < B_NR_ITEMS(bh) ? last : B_NR_ITEMS(bh); |
| } |
| |
| reiserfs_warning(fp, "INTERNAL NODE (%lu) contains %b\n", bh->b_blocknr, |
| bh); |
| |
| dc = B_N_CHILD(bh, from); |
| reiserfs_warning(fp, "PTR %d: %y ", from, dc); |
| |
| for (i = from, key = internal_key(bh, from), dc++; i < to; |
| i++, key++, dc++) { |
| reiserfs_warning(fp, "KEY %d: %20k PTR %d: %20y ", i, key, |
| i + 1, dc); |
| if (i && i % 4 == 0) |
| reiserfs_warning(fp, "\n"); |
| } |
| reiserfs_warning(fp, "\n"); |
| return 0; |
| } |
| |
| static int is_symlink = 0; |
| static int print_leaf(FILE * fp, reiserfs_filsys_t fs, struct buffer_head *bh, |
| int print_mode, int first, int last) |
| { |
| struct item_head *ih; |
| int i; |
| int from, to; |
| int real_nr, nr; |
| |
| if (!is_tree_node(bh, DISK_LEAF_NODE_LEVEL)) |
| return 1; |
| |
| ih = item_head(bh, 0); |
| real_nr = leaf_count_ih(bh->b_data, bh->b_size); |
| nr = get_blkh_nr_items((struct block_head *)bh->b_data); |
| |
| reiserfs_warning(fp, |
| "\n===================================================================\n"); |
| reiserfs_warning(fp, "LEAF NODE (%lu) contains %b (real items %d)\n", |
| bh->b_blocknr, bh, real_nr); |
| |
| if (!(print_mode & PRINT_TREE_DETAILS)) { |
| reiserfs_warning(fp, "FIRST ITEM_KEY: %k, LAST ITEM KEY: %k\n", |
| &(ih->ih_key), &((ih + real_nr - 1)->ih_key)); |
| return 0; |
| } |
| |
| if (first < 0 || first > real_nr - 1) |
| from = 0; |
| else |
| from = first; |
| |
| if (last < 0 || last > real_nr) |
| to = real_nr; |
| else |
| to = last; |
| |
| reiserfs_warning(fp, |
| "-------------------------------------------------------------------------------\n" |
| "|###|type|ilen|f/sp| loc|fmt|fsck| key |\n" |
| "| | | |e/cn| | |need| |\n"); |
| for (i = from; i < to; i++) { |
| reiserfs_warning(fp, |
| "-------------------------------------------------------------------------------\n" |
| "|%3d|%30H|%s\n", i, ih + i, |
| i >= nr ? " DELETED" : ""); |
| |
| if (I_IS_STAT_DATA_ITEM(ih + i)) { |
| is_symlink = |
| print_stat_data(fp, bh, ih + i, 0 /*all times */ ); |
| continue; |
| } |
| |
| if (I_IS_DIRECTORY_ITEM(ih + i)) { |
| print_directory_item(fp, fs, bh, ih + i); |
| continue; |
| } |
| |
| if (I_IS_INDIRECT_ITEM(ih + i)) { |
| print_indirect_item(fp, bh, i); |
| continue; |
| } |
| |
| if (I_IS_DIRECT_ITEM(ih + i)) { |
| int j = 0; |
| if (is_symlink || print_mode & PRINT_DIRECT_ITEMS) { |
| reiserfs_warning(fp, "\""); |
| while (j < get_ih_item_len(&ih[i])) { |
| if (ih_item_body(bh, ih + i)[j] == 10) |
| reiserfs_warning(fp, "\\n"); |
| else |
| reiserfs_warning(fp, "%c", |
| ih_item_body(bh, |
| ih + |
| i) |
| [j]); |
| j++; |
| } |
| reiserfs_warning(fp, "\"\n"); |
| } |
| continue; |
| } |
| } |
| reiserfs_warning(fp, |
| "===================================================================\n"); |
| return 0; |
| } |
| |
| void print_journal_params(FILE * fp, struct journal_params *jp) |
| { |
| reiserfs_warning(fp, "\tDevice [0x%x]\n", get_jp_journal_dev(jp)); |
| reiserfs_warning(fp, "\tMagic [0x%x]\n", get_jp_journal_magic(jp)); |
| |
| reiserfs_warning(fp, |
| "\tSize %u blocks (including 1 for journal header) (first block %u)\n", |
| get_jp_journal_size(jp) + 1, |
| get_jp_journal_1st_block(jp)); |
| reiserfs_warning(fp, "\tMax transaction length %u blocks\n", |
| get_jp_journal_max_trans_len(jp)); |
| reiserfs_warning(fp, "\tMax batch size %u blocks\n", |
| get_jp_journal_max_batch(jp)); |
| reiserfs_warning(fp, "\tMax commit age %u\n", |
| get_jp_journal_max_commit_age(jp)); |
| /*reiserfs_warning (fp, "\tMax transaction age %u\n", get_jp_journal_max_trans_age (jp)); */ |
| } |
| |
| /* return 1 if this is not super block */ |
| int print_super_block(FILE * fp, reiserfs_filsys_t fs, const char *file_name, |
| struct buffer_head *bh, int short_print) |
| { |
| struct reiserfs_super_block *sb = |
| (struct reiserfs_super_block *)(bh->b_data); |
| dev_t rdev; |
| int format = 0; |
| __u16 state; |
| time_t last_check = get_sb_v2_lastcheck(sb); |
| char last_check_buf[26]; |
| |
| if (!does_look_like_super_block(sb)) |
| return 1; |
| |
| rdev = misc_device_rdev(file_name); |
| |
| reiserfs_warning(fp, "Reiserfs super block in block %lu on 0x%x of ", |
| bh->b_blocknr, rdev); |
| switch (get_reiserfs_format(sb)) { |
| case REISERFS_FORMAT_3_5: |
| reiserfs_warning(fp, "format 3.5 with "); |
| format = 1; |
| break; |
| case REISERFS_FORMAT_3_6: |
| reiserfs_warning(fp, "format 3.6 with "); |
| format = 2; |
| break; |
| default: |
| reiserfs_warning(fp, "unknown format with "); |
| break; |
| } |
| if (is_reiserfs_jr_magic_string(sb)) |
| reiserfs_warning(fp, "non-"); |
| reiserfs_warning(fp, "standard journal\n"); |
| if (short_print) { |
| reiserfs_warning(fp, "Blocks (total/free): %u/%u by %d bytes\n", |
| get_sb_block_count(sb), get_sb_free_blocks(sb), |
| get_sb_block_size(sb)); |
| } else { |
| reiserfs_warning(fp, "Count of blocks on the device: %u\n", |
| get_sb_block_count(sb)); |
| reiserfs_warning(fp, "Number of bitmaps: %u", |
| get_sb_bmap_nr(sb)); |
| if (get_sb_bmap_nr(sb) != reiserfs_fs_bmap_nr(fs)) |
| reiserfs_warning(fp, " (really uses %u)", |
| reiserfs_fs_bmap_nr(fs)); |
| reiserfs_warning(fp, "\nBlocksize: %d\n", |
| get_sb_block_size(sb)); |
| reiserfs_warning(fp, |
| "Free blocks (count of blocks - used [journal, " |
| "bitmaps, data, reserved] blocks): %u\n", |
| get_sb_free_blocks(sb)); |
| reiserfs_warning(fp, "Root block: %u\n", get_sb_root_block(sb)); |
| } |
| reiserfs_warning(fp, "Filesystem is %sclean\n", |
| (get_sb_umount_state(sb) == |
| FS_CLEANLY_UMOUNTED) ? "" : "NOT "); |
| |
| if (short_print) |
| return 0; |
| reiserfs_warning(fp, "Tree height: %d\n", get_sb_tree_height(sb)); |
| reiserfs_warning(fp, "Hash function used to sort names: %s\n", |
| code2name(get_sb_hash_code(sb))); |
| reiserfs_warning(fp, "Objectid map size %d, max %d\n", |
| get_sb_oid_cursize(sb), get_sb_oid_maxsize(sb)); |
| reiserfs_warning(fp, "Journal parameters:\n"); |
| print_journal_params(fp, sb_jp(sb)); |
| reiserfs_warning(fp, "Blocks reserved by journal: %u\n", |
| get_sb_reserved_for_journal(sb)); |
| state = get_sb_fs_state(sb); |
| reiserfs_warning(fp, "Fs state field: 0x%x:\n", state); |
| if ((state & FS_FATAL) == FS_FATAL) |
| reiserfs_warning(fp, "\tFATAL corruptions exist.\n"); |
| if ((state & FS_ERROR) == FS_ERROR) |
| reiserfs_warning(fp, "\t some corruptions exist.\n"); |
| if ((state & IO_ERROR) == IO_ERROR) |
| reiserfs_warning(fp, "\tI/O corruptions exist.\n"); |
| |
| reiserfs_warning(fp, "sb_version: %u\n", get_sb_version(sb)); |
| if (format == 2) { |
| reiserfs_warning(fp, "inode generation number: %u\n", |
| get_sb_v2_inode_generation(sb)); |
| reiserfs_warning(fp, "UUID: %U\n", sb->s_uuid); |
| reiserfs_warning(fp, "LABEL: %.16s\n", sb->s_label); |
| reiserfs_warning(fp, "Set flags in SB:\n"); |
| if ((get_sb_v2_flag(sb, reiserfs_attrs_cleared))) |
| reiserfs_warning(fp, "\tATTRIBUTES CLEAN\n"); |
| reiserfs_warning(fp, "Mount count: %u\n", |
| get_sb_v2_mnt_count(sb)); |
| reiserfs_warning(fp, "Maximum mount count: "); |
| if (get_sb_v2_max_mnt_count(sb) && |
| get_sb_v2_max_mnt_count(sb) != USHRT_MAX) |
| reiserfs_warning(fp, "%u\n", |
| get_sb_v2_max_mnt_count(sb)); |
| else if (get_sb_v2_max_mnt_count(sb) == USHRT_MAX) |
| reiserfs_warning(fp, "Administratively disabled.\n"); |
| else |
| reiserfs_warning(fp, |
| "Disabled. Run fsck.reiserfs(8) or use tunefs.reiserfs(8) to enable.\n"); |
| if (last_check) { |
| ctime_r(&last_check, last_check_buf); |
| reiserfs_warning(fp, "Last fsck run: %s", |
| last_check_buf); |
| } else |
| reiserfs_warning(fp, |
| "Last fsck run: Never with a version " |
| "that supports this feature.\n"); |
| reiserfs_warning(fp, "Check interval in days: "); |
| if (get_sb_v2_check_interval(sb) && |
| get_sb_v2_check_interval(sb) != UINT_MAX) |
| reiserfs_warning(fp, "%u\n", |
| get_sb_v2_check_interval(sb) / (24 * |
| 60 * |
| 60)); |
| else if (get_sb_v2_check_interval(sb) == UINT_MAX) |
| reiserfs_warning(fp, "Administratively disabled.\n"); |
| else |
| reiserfs_warning(fp, |
| "Disabled. Run fsck.reiserfs(8) or use tunefs.reiserfs(8) to enable.\n"); |
| } |
| |
| return 0; |
| } |
| |
| void print_filesystem_state(FILE * fp, reiserfs_filsys_t fs) |
| { |
| reiserfs_warning(fp, "\nFilesystem state: "); |
| if (reiserfs_is_fs_consistent(fs)) |
| reiserfs_warning(fp, "consistent\n\n"); |
| else |
| reiserfs_warning(fp, |
| "consistency is not checked after last mounting\n\n"); |
| } |
| |
| static int print_desc_block(FILE * fp, struct buffer_head *bh) |
| { |
| if (memcmp(get_jd_magic(bh), JOURNAL_DESC_MAGIC, 8)) |
| return 1; |
| |
| reiserfs_warning(fp, |
| "Desc block %lu (j_trans_id %ld, j_mount_id %ld, j_len %ld)\n", |
| bh->b_blocknr, get_desc_trans_id(bh), |
| get_desc_mount_id(bh), get_desc_trans_len(bh)); |
| |
| return 0; |
| } |
| |
| void print_block(FILE * fp, reiserfs_filsys_t fs, struct buffer_head *bh, ...) //int print_mode, int first, int last) |
| { |
| va_list args; |
| int mode, first, last; |
| const char *file_name; |
| |
| va_start(args, bh); |
| |
| if (!bh) { |
| reiserfs_warning(stderr, "print_block: buffer is NULL\n"); |
| return; |
| } |
| |
| mode = va_arg(args, int); |
| first = va_arg(args, int); |
| last = va_arg(args, int); |
| file_name = (fs) ? fs->fs_file_name : NULL; |
| if (print_desc_block(fp, bh)) |
| if (print_super_block(fp, fs, file_name, bh, 0)) |
| if (print_leaf(fp, fs, bh, mode, first, last)) |
| if (print_internal(fp, bh, first, last)) |
| reiserfs_warning(fp, |
| "Block %lu contains unformatted data\n", |
| bh->b_blocknr); |
| } |
| |
| void print_tb(int mode, int item_pos, int pos_in_item, struct tree_balance *tb, |
| const char *mes) |
| { |
| unsigned int h = 0; |
| struct buffer_head *tbSh, *tbFh; |
| |
| if (!tb) |
| return; |
| |
| printf("\n********************** PRINT_TB for %s *******************\n", |
| mes); |
| printf("MODE=%c, ITEM_POS=%d POS_IN_ITEM=%d\n", mode, item_pos, |
| pos_in_item); |
| printf |
| ("*********************************************************************\n"); |
| |
| printf |
| ("* h * S * L * R * F * FL * FR * CFL * CFR *\n"); |
| /* |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789 |
| 1 2 3 4 5 6 7 8 |
| printk ("*********************************************************************\n"); |
| */ |
| |
| for (h = 0; h < sizeof(tb->insert_size) / sizeof(tb->insert_size[0]); |
| h++) { |
| if (PATH_H_PATH_OFFSET(tb->tb_path, h) <= |
| tb->tb_path->path_length |
| && PATH_H_PATH_OFFSET(tb->tb_path, |
| h) > ILLEGAL_PATH_ELEMENT_OFFSET) { |
| tbSh = PATH_H_PBUFFER(tb->tb_path, h); |
| tbFh = PATH_H_PPARENT(tb->tb_path, h); |
| } else { |
| /* printk ("print_tb: h=%d, PATH_H_PATH_OFFSET=%d, path_length=%d\n", |
| h, PATH_H_PATH_OFFSET (tb->tb_path, h), tb->tb_path->path_length); */ |
| tbSh = NULL; |
| tbFh = NULL; |
| } |
| printf |
| ("* %u * %3lu(%2lu) * %3lu(%2lu) * %3lu(%2lu) * %5lu * %5lu * %5lu * %5lu * %5lu *\n", |
| h, tbSh ? tbSh->b_blocknr : ~0ul, |
| tbSh ? tbSh->b_count : ~0ul, |
| tb->L[h] ? tb->L[h]->b_blocknr : ~0ul, |
| tb->L[h] ? tb->L[h]->b_count : ~0ul, |
| tb->R[h] ? tb->R[h]->b_blocknr : ~0ul, |
| tb->R[h] ? tb->R[h]->b_count : ~0ul, |
| tbFh ? tbFh->b_blocknr : ~0ul, |
| tb->FL[h] ? tb->FL[h]->b_blocknr : ~0ul, |
| tb->FR[h] ? tb->FR[h]->b_blocknr : ~0ul, |
| tb->CFL[h] ? tb->CFL[h]->b_blocknr : ~0ul, |
| tb->CFR[h] ? tb->CFR[h]->b_blocknr : ~0ul); |
| } |
| |
| printf |
| ("*********************************************************************\n"); |
| |
| /* print balance parameters for leaf level */ |
| h = 0; |
| printf |
| ("* h * size * ln * lb * rn * rb * blkn * s0 * s1 * s1b * s2 * s2b * curb * lk * rk *\n"); |
| printf |
| ("* %d * %4d * %2d * %2d * %2d * %2d * %4d * %2d * %2d * %3d * %2d * %3d * %4d * %2d * %2d *\n", |
| h, tb->insert_size[h], tb->lnum[h], tb->lbytes, tb->rnum[h], |
| tb->rbytes, tb->blknum[h], tb->s0num, tb->s1num, tb->s1bytes, |
| tb->s2num, tb->s2bytes, tb->cur_blknum, tb->lkey[h], tb->rkey[h]); |
| |
| /* this prints balance parameters for non-leaf levels */ |
| do { |
| h++; |
| printf("* %d * %4d * %2d * * %2d * * %2d *\n", |
| h, tb->insert_size[h], tb->lnum[h], tb->rnum[h], |
| tb->blknum[h]); |
| } while (tb->insert_size[h]); |
| |
| printf |
| ("*********************************************************************\n"); |
| |
| /* print FEB list (list of buffers in form (bh (b_blocknr, b_count), that will be used for new nodes) */ |
| for (h = 0; h < sizeof(tb->FEB) / sizeof(tb->FEB[0]); h++) |
| printf("%s%p (%lu %d)", h == 0 ? "FEB list: " : ", ", |
| tb->FEB[h], tb->FEB[h] ? tb->FEB[h]->b_blocknr : 0, |
| tb->FEB[h] ? tb->FEB[h]->b_count : 0); |
| printf("\n"); |
| |
| printf |
| ("********************** END OF PRINT_TB *******************\n\n"); |
| } |
| |
| static void print_bmap_block(FILE * fp, int i, unsigned long block, |
| const char *map, int blocks, int silent, |
| int blocksize) |
| { |
| int j, k; |
| int bits = blocksize * 8; |
| int zeros = 0, ones = 0; |
| |
| reiserfs_warning(fp, "#%d: block %lu: ", i, block); |
| |
| blocks = blocksize * 8; |
| |
| if (misc_test_bit(0, map)) { |
| /* first block addressed by this bitmap block is used */ |
| ones++; |
| if (!silent) |
| reiserfs_warning(fp, "Busy (%d-", i * bits); |
| for (j = 1; j < blocks; j++) { |
| while (misc_test_bit(j, map)) { |
| ones++; |
| if (j == blocks - 1) { |
| if (!silent) |
| reiserfs_warning(fp, "%d)\n", |
| j + i * bits); |
| goto end; |
| } |
| j++; |
| } |
| if (!silent) |
| reiserfs_warning(fp, "%d) Free(%d-", |
| j - 1 + i * bits, |
| j + i * bits); |
| |
| while (!misc_test_bit(j, map)) { |
| zeros++; |
| if (j == blocks - 1) { |
| if (!silent) |
| reiserfs_warning(fp, "%d)\n", |
| j + i * bits); |
| goto end; |
| } |
| j++; |
| } |
| if (!silent) |
| reiserfs_warning(fp, "%d) Busy(%d-", |
| j - 1 + i * bits, |
| j + i * bits); |
| |
| j--; |
| end: |
| /* to make gcc 3.2 do not sware here */ ; |
| } |
| } else { |
| /* first block addressed by this bitmap is free */ |
| zeros++; |
| if (!silent) |
| reiserfs_warning(fp, "Free (%d-", i * bits); |
| for (j = 1; j < blocks; j++) { |
| k = 0; |
| while (!misc_test_bit(j, map)) { |
| k++; |
| if (j == blocks - 1) { |
| if (!silent) |
| reiserfs_warning(fp, "%d)\n", |
| j + i * bits); |
| zeros += k; |
| goto end2; |
| } |
| j++; |
| } |
| zeros += k; |
| if (!silent) |
| reiserfs_warning(fp, "%d) Busy(%d-", |
| j - 1 + i * bits, |
| j + i * bits); |
| |
| k = 0; |
| while (misc_test_bit(j, map)) { |
| ones++; |
| if (j == blocks - 1) { |
| if (!silent) |
| reiserfs_warning(fp, "%d)\n", |
| j + i * bits); |
| ones += k; |
| goto end2; |
| } |
| j++; |
| } |
| ones += k; |
| if (!silent) |
| reiserfs_warning(fp, "%d) Free(%d-", |
| j - 1 + i * bits, |
| j + i * bits); |
| |
| j--; |
| end2: |
| /* to make gcc 3.2 do not sware here */ ; |
| } |
| } |
| |
| reiserfs_warning(fp, "used %d, free %d\n", ones, zeros); |
| } |
| |
| /* read bitmap of disk and print details */ |
| void print_bmap(FILE * fp, reiserfs_filsys_t fs, int silent) |
| { |
| struct reiserfs_super_block *sb; |
| int bmap_nr; |
| int i; |
| int bits_per_block; |
| int blocks; |
| unsigned long block; |
| struct buffer_head *bh; |
| |
| sb = fs->fs_ondisk_sb; |
| bmap_nr = reiserfs_fs_bmap_nr(fs); |
| bits_per_block = fs->fs_blocksize * 8; |
| blocks = bits_per_block; |
| |
| reiserfs_warning(fp, "Bitmap blocks are:\n"); |
| block = fs->fs_super_bh->b_blocknr + 1; |
| for (i = 0; i < bmap_nr; i++) { |
| bh = bread(fs->fs_dev, block, fs->fs_blocksize); |
| if (!bh) { |
| reiserfs_warning(stderr, |
| "print_bmap: bread failed for %d: %lu\n", |
| i, block); |
| continue; |
| } |
| if (i == bmap_nr - 1) |
| if (get_sb_block_count(sb) % bits_per_block) |
| blocks = |
| get_sb_block_count(sb) % bits_per_block; |
| print_bmap_block(fp, i, block, bh->b_data, blocks, silent, |
| fs->fs_blocksize); |
| brelse(bh); |
| |
| if (spread_bitmaps(fs)) |
| block = |
| (block / (fs->fs_blocksize * 8) + |
| 1) * (fs->fs_blocksize * 8); |
| else |
| block++; |
| |
| } |
| } |
| |
| void print_objectid_map(FILE * fp, reiserfs_filsys_t fs) |
| { |
| int i; |
| struct reiserfs_super_block *sb; |
| __le32 *omap; |
| |
| sb = fs->fs_ondisk_sb; |
| if (fs->fs_format == REISERFS_FORMAT_3_6) |
| omap = (__le32 *) (sb + 1); |
| else if (fs->fs_format == REISERFS_FORMAT_3_5) |
| omap = (__le32 *) ((struct reiserfs_super_block_v1 *)sb + 1); |
| else { |
| reiserfs_warning(fp, |
| "print_objectid_map: proper signature is not found\n"); |
| return; |
| } |
| |
| reiserfs_warning(fp, "Map of objectids (super block size %d)\n", |
| (char *)omap - (char *)sb); |
| |
| for (i = 0; i < get_sb_oid_cursize(sb); i++) { |
| if (i % 2 == 0) { |
| reiserfs_warning(fp, "busy(%u-%u) ", |
| le32_to_cpu(omap[i]), |
| le32_to_cpu(omap[i + 1]) - 1); |
| } else { |
| reiserfs_warning(fp, "free(%u-%u) ", |
| le32_to_cpu(omap[i]), |
| ((i + 1) == |
| get_sb_oid_cursize(sb)) ? ~(__u32) 0 |
| : (le32_to_cpu(omap[i + 1]) - 1)); |
| } |
| } |
| |
| reiserfs_warning(fp, "\nObject id array has size %d (max %d):", |
| get_sb_oid_cursize(sb), get_sb_oid_maxsize(sb)); |
| |
| for (i = 0; i < get_sb_oid_cursize(sb); i++) |
| reiserfs_warning(fp, "%s%u ", i % 2 ? "" : "*", |
| le32_to_cpu(omap[i])); |
| reiserfs_warning(fp, "\n"); |
| |
| } |
| |
| void print_journal_header(reiserfs_filsys_t fs) |
| { |
| struct reiserfs_journal_header *j_head; |
| |
| j_head = (struct reiserfs_journal_header *)(fs->fs_jh_bh->b_data); |
| reiserfs_warning(stdout, "Journal header (block #%lu of %s):\n" |
| "\tj_last_flush_trans_id %ld\n" |
| "\tj_first_unflushed_offset %ld\n" |
| "\tj_mount_id %ld\n", |
| fs->fs_jh_bh->b_blocknr, fs->fs_j_file_name, |
| get_jh_last_flushed(j_head), |
| get_jh_replay_start_offset(j_head), |
| get_jh_mount_id(j_head)); |
| print_journal_params(stdout, &j_head->jh_journal); |
| } |
| |
| static void print_trans_element(reiserfs_filsys_t fs, |
| reiserfs_trans_t *trans, unsigned int index, |
| unsigned long in_journal, |
| unsigned long in_place) |
| { |
| if (index % 8 == 0) |
| reiserfs_warning(stdout, "#%d\t", index); |
| |
| reiserfs_warning(stdout, "%lu->%lu%s ", in_journal, in_place, |
| block_of_bitmap(fs, in_place) ? "B" : ""); |
| if ((index + 1) % 8 == 0 || index == trans->trans_len - 1) |
| reiserfs_warning(stdout, "\n"); |
| } |
| |
| void print_one_transaction(reiserfs_filsys_t fs, reiserfs_trans_t *trans) |
| { |
| reiserfs_warning(stdout, |
| "Mountid %u, transid %u, desc %lu, length %u, commit %lu\n", |
| trans->mount_id, trans->trans_id, trans->desc_blocknr, |
| trans->trans_len, trans->commit_blocknr); |
| for_each_block(fs, trans, print_trans_element); |
| } |
| |
| /* print all valid transactions and found dec blocks */ |
| void print_journal(reiserfs_filsys_t fs) |
| { |
| if (!reiserfs_journal_opened(fs)) { |
| reiserfs_warning(stderr, |
| "print_journal: journal is not opened\n"); |
| return; |
| } |
| print_journal_header(fs); |
| |
| for_each_transaction(fs, print_one_transaction); |
| } |