reiserfsprogs-3.6.9/0000777000077100007710000000000007705315454010211 5reiserfsprogs-3.6.9/lib/0000777000077100007710000000000007705315452010755 5reiserfsprogs-3.6.9/lib/io.c0000664000077100007710000006554107705261642011462 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "io.h" #include "misc.h" #include "config.h" void check_memory_msg (void) { fprintf(stderr, "\nThe problem has occurred looks like a hardware problem (perhaps memory).\n" "Send us the bug report only if the second run dies at the same place with\n" "the same block number.\n"); } void check_hd_msg (void) { fprintf(stderr, "\nThe problem has occurred looks like a hardware problem.\n" "If you have bad blocks, we advise you to get a new hard\n" "drive, because once you get one bad block that the disk\n" "drive internals cannot hide from your sight, the chances\n" "of getting more are generally said to become much higher\n" "(precise statistics are unknown to us), and this disk drive\n" "is probably not expensive enough for you to risk your time\n" "and data on it. If you don't want to follow that advice,\n" "then if you have just a few bad blocks, try writing to the\n" "bad blocks and see if the drive remaps the bad blocks (that\n" "means it takes a block it has in reserve and allocates it\n" "for use for requests of that block number). If it cannot\n" "remap the block, this could be quite bad, as it may mean\n" "that so many blocks have gone bad that none remain in \n" "reserve to allocate.\n"); } static int is_bad_block (unsigned long block) { #ifdef IO_FAILURE_EMULATION /* this array similates bad blocks on the device */ unsigned long bad_blocks [] = { 8208, 8209, 8210 /*, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19*/ }; int i; for (i = 0; i < sizeof (bad_blocks) / sizeof (bad_blocks[0]); i ++) if (bad_blocks [i] == block) return 1; #endif return 0; } /* All buffers are in double linked cycled list. If getblk found buffer with wanted block number in hash queue it moves buffer to the end of list. */ static int g_nr_buffers; static unsigned long buffers_memory; /* create buffers until we spend this fraction of system memory, this ** is a hard limit on the amount of buffer ram used */ #define BUFFER_MEMORY_FRACTION 10 /* number of bytes in local buffer cache before we start forcing syncs ** of dirty data and reusing unused buffers instead of allocating new ** ones. If a flush doesn't find reusable buffers, new ones are ** still allocated up to the BUFFER_MEMORY_FRACTION percentage ** */ #define BUFFER_SOFT_LIMIT (500 * 1024) static unsigned long buffer_soft_limit = BUFFER_SOFT_LIMIT; #define NR_HASH_QUEUES 4096 static struct buffer_head * g_a_hash_queues [NR_HASH_QUEUES]; static struct buffer_head * Buffer_list_head; static struct buffer_head * g_free_buffers = NULL ; static struct buffer_head * g_buffer_heads; static int buffer_hits = 0 ; static int buffer_misses = 0 ; static int buffer_reads = 0 ; static int buffer_writes = 0 ; static void _show_buffers(struct buffer_head **list, int dev, unsigned long size) { int all = 0; int dirty = 0; int in_use = 0; /* count != 0 */ int free = 0; struct buffer_head * next; next = *list; if (!next) return ; for (;;) { if (next->b_dev == dev && next->b_size == size) { all ++; if (next->b_count != 0) { in_use ++; } if (buffer_dirty (next)) { dirty ++; } if (buffer_clean (next) && next->b_count == 0) { free ++; } } next = next->b_next; if (next == *list) break; } printf("show_buffers (dev %d, size %lu): free %d, count != 0 %d, dirty %d, " "all %d\n", dev, size, free, in_use, dirty, all); } static void show_buffers (int dev, int size) { _show_buffers(&Buffer_list_head, dev, size) ; _show_buffers(&g_free_buffers, dev, size) ; } static void insert_into_hash_queue (struct buffer_head * bh) { int index = bh->b_blocknr % NR_HASH_QUEUES; if (bh->b_hash_prev || bh->b_hash_next) die ("insert_into_hash_queue: hash queue corrupted"); if (g_a_hash_queues[index]) { g_a_hash_queues[index]->b_hash_prev = bh; bh->b_hash_next = g_a_hash_queues[index]; } g_a_hash_queues[index] = bh; } static void remove_from_hash_queue (struct buffer_head * bh) { if (bh->b_hash_next == 0 && bh->b_hash_prev == 0 && bh != g_a_hash_queues[bh->b_blocknr % NR_HASH_QUEUES]) /* (b_dev == -1) ? */ return; if (bh == g_a_hash_queues[bh->b_blocknr % NR_HASH_QUEUES]) { if (bh->b_hash_prev != 0) die ("remove_from_hash_queue: hash queue corrupted"); g_a_hash_queues[bh->b_blocknr % NR_HASH_QUEUES] = bh->b_hash_next; } if (bh->b_hash_next) bh->b_hash_next->b_hash_prev = bh->b_hash_prev; if (bh->b_hash_prev) bh->b_hash_prev->b_hash_next = bh->b_hash_next; bh->b_hash_prev = bh->b_hash_next = 0; } static void put_buffer_list_end (struct buffer_head **list, struct buffer_head * bh) { struct buffer_head * last = 0; if (bh->b_prev || bh->b_next) die ("put_buffer_list_end: buffer list corrupted"); if (*list == 0) { bh->b_next = bh; bh->b_prev = bh; *list = bh; } else { last = (*list)->b_prev; bh->b_next = last->b_next; bh->b_prev = last; last->b_next->b_prev = bh; last->b_next = bh; } } static void remove_from_buffer_list (struct buffer_head **list, struct buffer_head * bh) { if (bh == bh->b_next) { *list = 0; } else { bh->b_prev->b_next = bh->b_next; bh->b_next->b_prev = bh->b_prev; if (bh == *list) *list = bh->b_next; } bh->b_next = bh->b_prev = 0; } static void put_buffer_list_head (struct buffer_head **list, struct buffer_head * bh) { put_buffer_list_end (list, bh); *list = bh; } /* #include static size_t estimate_memory_amount (void) { size_t len = 1; size_t max = 0; void * addr; while (len > 0) { addr = mmap (0, len, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) { if (errno != ENOMEM) die ("mmap failed: %s\n", strerror(errno)); break; } if (mlock (addr, len) != 0) { if (errno == EPERM) die ("No permission to run mlock"); break; } munlock (addr, len); munmap (addr, len); max = len; len *= 2; } // * If we've looped, we don't want to return 0, we want to return the // * last successful len before we looped. In the event that mmap/mlock // * failed for len = 1, max will still be 0, so we don't get an invalid // * result return max; } */ #define GROW_BUFFERS__NEW_BUFERS_PER_CALL 10 /* creates number of new buffers and insert them into head of buffer list */ static int grow_buffers (int size) { int i; struct buffer_head * bh, * tmp; /* get memory for array of buffer heads */ bh = (struct buffer_head *)getmem (GROW_BUFFERS__NEW_BUFERS_PER_CALL * sizeof (struct buffer_head) + sizeof (struct buffer_head *)); if (g_buffer_heads == 0) g_buffer_heads = bh; else { /* link new array to the end of array list */ tmp = g_buffer_heads; while (*(struct buffer_head **)(tmp + GROW_BUFFERS__NEW_BUFERS_PER_CALL) != 0) tmp = *(struct buffer_head **)(tmp + GROW_BUFFERS__NEW_BUFERS_PER_CALL); *(struct buffer_head **)(tmp + GROW_BUFFERS__NEW_BUFERS_PER_CALL) = bh; } for (i = 0; i < GROW_BUFFERS__NEW_BUFERS_PER_CALL; i ++) { tmp = bh + i; memset (tmp, 0, sizeof (struct buffer_head)); tmp->b_data = getmem (size); if (tmp->b_data == 0) die ("grow_buffers: no memory for new buffer data"); tmp->b_dev = -1; tmp->b_size = size; put_buffer_list_head (&g_free_buffers, tmp); } buffers_memory += GROW_BUFFERS__NEW_BUFERS_PER_CALL * size; g_nr_buffers += GROW_BUFFERS__NEW_BUFERS_PER_CALL; return GROW_BUFFERS__NEW_BUFERS_PER_CALL; } struct buffer_head *find_buffer(int dev, unsigned long block, unsigned long size) { struct buffer_head * next; next = g_a_hash_queues[block % NR_HASH_QUEUES]; for (;;) { struct buffer_head *tmp = next; if (!next) break; next = tmp->b_hash_next; if (tmp->b_blocknr != block || tmp->b_size != size || tmp->b_dev != dev) continue; next = tmp; break; } return next; } static struct buffer_head * get_free_buffer (struct buffer_head **list, unsigned long size) { struct buffer_head * next; next = *list; if (!next) return 0; for (;;) { if (!next) die ("get_free_buffer: buffer list is corrupted"); if (next->b_count == 0 && buffer_clean (next) && next->b_size == size) { remove_from_hash_queue (next); remove_from_buffer_list (list, next); return next; } next = next->b_next; if (next == *list) break; } return 0; } /* to_write == 0 when all blocks have to be flushed. Otherwise - write only buffers with b_count == 0 */ static int sync_buffers (struct buffer_head **list, int dev, int to_write) { struct buffer_head * next; int written = 0; restart: next = *list; if (!next) return 0; for (;;) { if (!next) die ("sync_buffers: buffer list is corrupted"); if (next->b_dev == dev && buffer_dirty (next) && buffer_uptodate (next)) { if ((to_write == 0 || next->b_count == 0) && !buffer_do_not_flush (next)) { bwrite (next); } } /* if this buffer is reusable, put it onto the end of the free list */ if (next->b_count == 0 && buffer_clean(next)) { remove_from_hash_queue (next); remove_from_buffer_list (list, next); put_buffer_list_end (&g_free_buffers, next); written++ ; if (written == to_write) return written; goto restart; } if (to_write && written >= to_write) return written; next = next->b_next; if (next == *list) break; } return written; } void flush_buffers (int dev) { if (dev == -1) die ("flush_buffers: device is not specified"); sync_buffers (&Buffer_list_head, dev, 0/*all*/); buffer_soft_limit = BUFFER_SOFT_LIMIT; } struct buffer_head * getblk (int dev, unsigned long block, int size) { struct buffer_head * bh; bh = find_buffer (dev, block, size); if (bh) { /* move the buffer to the end of list */ /*checkmem (bh->b_data, bh->b_size);*/ remove_from_buffer_list (&Buffer_list_head, bh); put_buffer_list_end (&Buffer_list_head, bh); bh->b_count ++; buffer_hits++ ; return bh; } buffer_misses++ ; bh = get_free_buffer (&g_free_buffers, size); if (bh == NULL) { if (buffers_memory >= buffer_soft_limit) { if (sync_buffers (&Buffer_list_head, dev, 32) == 0) { grow_buffers(size); buffer_soft_limit = buffers_memory + GROW_BUFFERS__NEW_BUFERS_PER_CALL * size; } } else { if (grow_buffers(size) == 0) sync_buffers (&Buffer_list_head, dev, 32); } bh = get_free_buffer (&g_free_buffers, size); if (bh == NULL) { show_buffers (dev, size); die ("getblk: no free buffers after grow_buffers and refill (%d)", g_nr_buffers); } } bh->b_count = 1; bh->b_dev = dev; bh->b_size = size; bh->b_blocknr = block; bh->b_end_io = NULL ; memset (bh->b_data, 0, size); misc_clear_bit(BH_Dirty, &bh->b_state); misc_clear_bit(BH_Uptodate, &bh->b_state); put_buffer_list_end (&Buffer_list_head, bh); insert_into_hash_queue (bh); /*checkmem (bh->b_data, bh->b_size);*/ return bh; } void brelse (struct buffer_head * bh) { if (bh == 0) return; if (bh->b_count == 0) die ("brelse: can not free a free buffer %lu", bh->b_blocknr); /*checkmem (bh->b_data, get_mem_size (bh->b_data));*/ bh->b_count --; } void bforget (struct buffer_head * bh) { if (bh) { bh->b_state = 0; brelse (bh); remove_from_hash_queue (bh); remove_from_buffer_list(&Buffer_list_head, bh); put_buffer_list_head(&Buffer_list_head, bh); } } /* Returns 0 on success; 1 - end of file; 0 - OK. */ static int f_read(struct buffer_head * bh) { unsigned long long offset; ssize_t bytes; buffer_reads++ ; offset = (unsigned long long)bh->b_size * bh->b_blocknr; if (lseek64 (bh->b_dev, offset, SEEK_SET) < 0) return -1; bytes = read (bh->b_dev, bh->b_data, bh->b_size); return bytes < 0 ? -1 : (bytes != (ssize_t)bh->b_size ? 1 : 0); } struct buffer_head * bread (int dev, unsigned long block, size_t size) { struct buffer_head * bh; int ret; if (is_bad_block (block)) return 0; bh = getblk (dev, block, size); /*checkmem (bh->b_data, get_mem_size(bh->b_data));*/ if (buffer_uptodate (bh)) return bh; ret = f_read(bh); if (ret > 0) die ("%s: End of file, cannot read the block (%lu).\n", __FUNCTION__, bh->b_blocknr); else if (ret < 0) { /* BAD BLOCK LIST SUPPORT * die ("%s: Cannot read a block # %lu. Specify list of badblocks\n",*/ if (errno == EIO) { check_hd_msg(); die ("%s: Cannot read the block (%lu): (%s).\n", __FUNCTION__, bh->b_blocknr, strerror(errno)); } else { fprintf (stderr, "%s: Cannot read the block (%lu): (%s).\n", __FUNCTION__, bh->b_blocknr, strerror(errno)); return NULL; } } mark_buffer_uptodate (bh, 0); return bh; } int valid_offset( int fd, loff_t offset) { char ch; loff_t res; /*res = reiserfs_llseek (fd, offset, 0);*/ res = lseek64 (fd, offset, SEEK_SET); if (res < 0) return 0; /* if (read (fd, &ch, 1) < 0) does not wirk on files */ if (read (fd, &ch, 1) < 1) return 0; return 1; } #define ROLLBACK_FILE_START_MAGIC "_RollBackFileForReiserfsFSCK" static struct block_handler * rollback_blocks_array; static __u32 rollback_blocks_number = 0; static FILE * s_rollback_file = 0; static FILE * log_file; static int do_rollback = 0; static char * rollback_data; static int rollback_blocksize; void init_rollback_file (char * rollback_file, int *blocksize, FILE * log) { char * string; struct stat64 buf; if (rollback_file == NULL) return; stat64(rollback_file, &buf); s_rollback_file = fopen (rollback_file, "w+"); if (s_rollback_file == NULL) { fprintf (stderr, "Cannot create file %s, work without a rollback file\n", rollback_file); return; } rollback_blocksize = *blocksize; string = ROLLBACK_FILE_START_MAGIC; fwrite (string, 28, 1, s_rollback_file); fwrite (&rollback_blocksize, sizeof (rollback_blocksize), 1, s_rollback_file); fwrite (&rollback_blocks_number, sizeof (rollback_blocks_number), 1, s_rollback_file); fflush(s_rollback_file); rollback_data = getmem(rollback_blocksize); // printf("\ncheckmem1"); // fflush (stdout); // checkmem (rollback_data, get_mem_size((char *)rollback_data)); // printf(" OK"); log_file = log; if (log_file) fprintf (log_file, "rollback: file (%s) initialize\n", rollback_file); do_rollback = 0; } #if 0 static void erase_rollback_file (char * rollback_file) { close_rollback_file (); unlink (rollback_file); } #endif int open_rollback_file (char * rollback_file, FILE * log) { char string [28]; struct stat64 buf; if (rollback_file == NULL) return -1; if (stat64(rollback_file, &buf)) { fprintf (stderr, "Cannot stat rollback file (%s)\n", rollback_file); return -1; } s_rollback_file = fopen (rollback_file, "r+"); if (s_rollback_file == NULL) { fprintf (stderr, "Cannot open file (%s)\n", rollback_file); return -1; } fread (string, 28, 1, s_rollback_file); if (!strcmp (string, ROLLBACK_FILE_START_MAGIC)) { fprintf (stderr, "Specified file (%s) does not look like a rollback file\n", rollback_file); fclose (s_rollback_file); s_rollback_file = 0; return -1; } fread (&rollback_blocksize, sizeof (rollback_blocksize), 1, s_rollback_file); if (rollback_blocksize <= 0) { fprintf(stderr, "rollback: wrong rollback blocksize, exit\n"); return -1; } log_file = log; if (log_file) fprintf (log_file, "rollback: file (%s) opened\n", rollback_file); do_rollback = 1; return 0; } void close_rollback_file () { if (s_rollback_file == 0) return; if (!do_rollback) { if (fseek (s_rollback_file, 28 + sizeof(int), SEEK_SET) == (loff_t)-1) return; fwrite (&rollback_blocks_number, sizeof (rollback_blocksize), 1, s_rollback_file); if (log_file != 0) fprintf (log_file, "rollback: %d blocks backed up\n", rollback_blocks_number); } fclose (s_rollback_file); freemem (rollback_data); freemem (rollback_blocks_array); // fprintf (stdout, "rollback: (%u) blocks saved, \n", rollback_blocks_number); /* for (i = 0; i < rollback_blocks_number; i++) fprintf(stdout, "device (%Lu), block number (%u)\n", rollback_blocks_array [i].device, rollback_blocks_array [i].blocknr); fprintf(stdout, "\n"); */ } void do_fsck_rollback (int fd_device, int fd_journal_device, FILE * progress) { loff_t offset; struct stat64 buf; int descriptor; ssize_t retval; int count_failed = 0; int count_rollbacked = 0; dev_t b_dev; dev_t n_dev = 0; dev_t n_journal_dev = 0; unsigned long total, done = 0; if (fd_device == 0) { fprintf(stderr, "rollback: unspecified device, exit\n"); return; } if (fd_journal_device) { if (!fstat64 (fd_journal_device, &buf)) { n_journal_dev = buf.st_rdev; } else { fprintf(stderr, "rollback: specified journal device cannot be stated\n"); } } if (!fstat64 (fd_device, &buf)) { n_dev = buf.st_rdev; } else { fprintf(stderr, "rollback: specified device cannot be stated, exit\n"); return; } rollback_data = getmem (rollback_blocksize); // printf("\ncheckmem2"); // fflush (stdout); // checkmem (rollback_data, get_mem_size((char *)rollback_data)); // printf(" OK"); fread (&rollback_blocks_number, sizeof (rollback_blocks_number), 1, s_rollback_file); total = rollback_blocks_number; while (1) { print_how_far (progress, &done, rollback_blocks_number, 1, 0/*not quiet*/); descriptor = 0; if ((retval = fread (&b_dev, sizeof (b_dev), 1, s_rollback_file)) <= 0) { if (retval) fprintf (stderr, "rollback: fread: %s\n", strerror (errno)); break; } if ((retval = fread (&offset, sizeof (offset), 1, s_rollback_file)) <= 0) { if (retval) fprintf (stderr, "rollback: fread: %s\n", strerror (errno)); break; } if ((retval = fread (rollback_data, rollback_blocksize, 1, s_rollback_file)) <= 0) { if (retval) fprintf (stderr, "rollback: fread: %s\n", strerror (errno)); break; } if (n_dev == b_dev) descriptor = fd_device; if ((n_journal_dev) && (n_journal_dev == b_dev)) descriptor = fd_journal_device; if (descriptor == 0) { fprintf(stderr, "rollback: block from unknown device, skip block\n"); count_failed ++; continue; } if (lseek64 (descriptor, offset, SEEK_SET) == (loff_t)-1) { fprintf(stderr, "device cannot be lseeked, skip block\n"); count_failed ++; continue; } if (write (descriptor, rollback_data, rollback_blocksize) == -1) { fprintf (stderr, "rollback: write %d bytes returned error " "(block=%lld, dev=%lld): %s\n", rollback_blocksize, offset/rollback_blocksize, b_dev, strerror (errno)); count_failed ++; } else { count_rollbacked ++; /*if you want to know what gets rollbacked, uncomment it*/ /* if (log_file != 0 && log_file != stdout) fprintf (log_file, "rollback: block %Lu of device %Lu was restored\n", (loff_t)offset/rollback_blocksize, b_dev); */ // fprintf (stdout, "rollback: block (%Ld) written\n", (loff_t)offset/rollback_blocksize); } } printf ("\n"); if (log_file != 0) fprintf (log_file, "rollback: (%u) blocks restored\n", count_rollbacked); } /* static void rollback__mark_block_saved (struct block_handler * rb_e) { if (rollback_blocks_array == NULL) rollback_blocks_array = getmem (ROLLBACK__INCREASE_BLOCK_NUMBER * sizeof (*rb_e)); if (rollback_blocks_number == get_mem_size ((void *)rollback_blocks_array) / sizeof (*rb_e)) rollback_blocks_array = expandmem (rollback_blocks_array, get_mem_size((void *)rollback_blocks_array), ROLLBACK__INCREASE_BLOCK_NUMBER * sizeof (*rb_e)); // checkmem ((char *)rollback_blocks_array, get_mem_size((char *)rollback_blocks_array)); rollback_blocks_array[rollback_blocks_number] = *rb_e; rollback_blocks_number ++; qsort (rollback_blocks_array, rollback_blocks_number, sizeof (*rb_e), rollback_compare); // printf("\ncheckmem3"); // fflush (stdout); // checkmem ((char *)rollback_blocks_array, get_mem_size((char *)rollback_blocks_array)); // printf(" OK"); } */ /* for now - just make sure that bad blocks did not get here */ int bwrite (struct buffer_head * bh) { unsigned long long offset; long long bytes, size; if (is_bad_block (bh->b_blocknr)) { fprintf (stderr, "bwrite: bad block is going to be written: %lu\n", bh->b_blocknr); exit(8); } if (!buffer_dirty (bh) || !buffer_uptodate (bh)) return 0; buffer_writes++ ; if (bh->b_start_io) /* this is used by undo feature of reiserfsck */ bh->b_start_io (bh->b_blocknr); size = bh->b_size; offset = (loff_t)size * (loff_t)bh->b_blocknr; if (lseek64 (bh->b_dev, offset, SEEK_SET) == (loff_t)-1){ fprintf (stderr, "bwrite: lseek to position %llu (block=%lu, dev=%d): %s\n", offset, bh->b_blocknr, bh->b_dev, strerror(errno)); exit(8); /* File system errors left uncorrected */ } if (s_rollback_file != NULL && bh->b_size == (unsigned long)rollback_blocksize) { struct stat64 buf; __u32 position; struct block_handler block_h; /*log previous content into the log*/ if (!fstat64 (bh->b_dev, &buf)) { block_h.blocknr = bh->b_blocknr; block_h.device = buf.st_rdev; if (reiserfs_bin_search(&block_h, rollback_blocks_array, rollback_blocks_number, sizeof (block_h), &position, blockdev_list_compare) != POSITION_FOUND) { /*read initial data from the disk*/ if (read(bh->b_dev, rollback_data, bh->b_size) == (long long)bh->b_size) { fwrite(&buf.st_rdev, sizeof (buf.st_rdev), 1, s_rollback_file); fwrite(&offset, sizeof (offset), 1, s_rollback_file); fwrite(rollback_data, rollback_blocksize, 1, s_rollback_file); fflush(s_rollback_file); blocklist__insert_in_position(&block_h, (void *)(&rollback_blocks_array), &rollback_blocks_number, sizeof(block_h), &position); /*if you want to know what gets saved, uncomment it*/ /* if (log_file != 0 && log_file != stdout) { fprintf (log_file, "rollback: block %lu of device %Lu was " "backed up\n", bh->b_blocknr, buf.st_rdev); } */ } else { fprintf (stderr, "bwrite: read (block=%lu, dev=%d): %s\n", bh->b_blocknr, bh->b_dev, strerror (errno)); exit(8); } if (lseek64 (bh->b_dev, offset, SEEK_SET) == (loff_t)-1) { fprintf (stderr, "bwrite: lseek to position %llu (block=%lu, " "dev=%d): %s\n", offset, bh->b_blocknr, bh->b_dev, strerror(errno)); exit(8); } } } else { fprintf (stderr, "bwrite: fstat of (%d) returned -1: %s\n", bh->b_dev, strerror(errno)); } } else if (s_rollback_file != NULL) { fprintf (stderr, "rollback: block (%lu) has the size different from " "the fs uses, block skipped\n", bh->b_blocknr); } bytes = write(bh->b_dev, bh->b_data, size); if (bytes != size) { fprintf (stderr, "bwrite: write %lld bytes returned %lld (block=%ld, " "dev=%d): %s\n", size, bytes, bh->b_blocknr, bh->b_dev, strerror(errno)); exit(8); } mark_buffer_clean (bh); if (bh->b_end_io) { bh->b_end_io(bh, 1) ; } return 0; } static int _check_and_free_buffer_list(struct buffer_head *list) { struct buffer_head *next = list ; int count = 0 ; if (!list) return 0 ; for(;;) { if (next->b_count != 0) fprintf (stderr, "check_and_free_buffer_mem: not free buffer " "(%d, %ld, %ld, %d)\n", next->b_dev, next->b_blocknr, next->b_size, next->b_count); if (buffer_dirty (next) && buffer_uptodate (next)) fprintf (stderr, "check_and_free_buffer_mem: dirty buffer " "(%d %lu) found\n", next->b_dev, next->b_blocknr); freemem (next->b_data); count++; next = next->b_next; if (next == list) break; } return count; } static void check_and_free_buffer_mem (void) { int count = 0; struct buffer_head * next ; // printf("check and free buffer mem, hits %d misses %d reads %d writes %d\n", // buffer_hits, buffer_misses, buffer_reads, buffer_writes) ; /*sync_buffers (0, 0);*/ count = _check_and_free_buffer_list(Buffer_list_head); count += _check_and_free_buffer_list(g_free_buffers); if (count != g_nr_buffers) die ("check_and_free_buffer_mem: found %d buffers, must be %d", count, g_nr_buffers); /* free buffer heads */ while ((next = g_buffer_heads)) { g_buffer_heads = *(struct buffer_head **)(next + GROW_BUFFERS__NEW_BUFERS_PER_CALL); freemem (next); } return; } /* */ void free_buffers (void) { check_and_free_buffer_mem (); } static void _invalidate_buffer_list(struct buffer_head *list, int dev) { struct buffer_head * next; if (!list) return; next = list; for (;;) { if (next->b_dev == dev) { if (buffer_dirty (next) || next->b_count) fprintf (stderr, "invalidate_buffers: dirty buffer or used buffer (%d %lu) found\n", next->b_count, next->b_blocknr); next->b_state = 0; remove_from_hash_queue (next); } next = next->b_next; if (next == list) break; } } /* forget all buffers of the given device */ void invalidate_buffers (int dev) { _invalidate_buffer_list(Buffer_list_head, dev) ; _invalidate_buffer_list(g_free_buffers, dev) ; } int user_confirmed (FILE * fp, char * q, char * yes) { char * answer = 0; size_t n = 0; fprintf (fp, "%s", q); if (getline (&answer, &n, stdin) != (ssize_t)strlen (yes) || strcmp (yes, answer)) return 0; return 1; } reiserfsprogs-3.6.9/lib/Makefile.am0000664000077100007710000000011507665645672012743 noinst_LIBRARIES = libmisc.a libmisc_a_SOURCES = io.c misc.c ##reiserfs.c reiserfsprogs-3.6.9/lib/Makefile.in0000644000077100007710000002475307705315225012747 # Makefile.in generated by automake 1.7.2 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__quote = @am__quote@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ noinst_LIBRARIES = libmisc.a libmisc_a_SOURCES = io.c misc.c subdir = lib mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) libmisc_a_AR = $(AR) cru libmisc_a_LIBADD = am_libmisc_a_OBJECTS = io.$(OBJEXT) misc.$(OBJEXT) libmisc_a_OBJECTS = $(am_libmisc_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/io.Po ./$(DEPDIR)/misc.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libmisc_a_SOURCES) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(libmisc_a_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu lib/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) AR = ar clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libmisc.a: $(libmisc_a_OBJECTS) $(libmisc_a_DEPENDENCIES) -rm -f libmisc.a $(libmisc_a_AR) libmisc.a $(libmisc_a_OBJECTS) $(libmisc_a_LIBADD) $(RANLIB) libmisc.a mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@ distclean-depend: -rm -rf ./$(DEPDIR) .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ distclean-depend distclean-generic distclean-tags distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: reiserfsprogs-3.6.9/lib/misc.c0000664000077100007710000005160207705261642011777 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ /* for stat64() */ #define _FILE_OFFSET_BITS 64 /* for getline() proto and _LARGEFILE64_SOURCE */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64) # define BLKGETSIZE64 _IOR(0x12, 114, sizeof(__u64)) #endif #include "swab.h" #include "io.h" #include "misc.h" /* Debian modifications by Ed Boraas */ #include /* End Debian mods */ void die (char * fmt, ...) { static char buf[1024]; va_list args; va_start (args, fmt); vsprintf (buf, fmt, args); va_end (args); fprintf (stderr, "\n%s\n", buf); abort (); } #define MEM_BEGIN "_mem_begin_" #define MEM_END "mem_end" #define MEM_FREED "__free_" #define CONTROL_SIZE (strlen (MEM_BEGIN) + 1 + sizeof (int) + strlen (MEM_END) + 1) unsigned int get_mem_size(char *p) { char *begin; begin = p - strlen (MEM_BEGIN) - 1 - sizeof(int); return *(int *)(begin + strlen (MEM_BEGIN) + 1); } void checkmem (char * p, int size) { char * begin; char * end; begin = p - strlen (MEM_BEGIN) - 1 - sizeof (int); if (strcmp (begin, MEM_BEGIN)) die ("checkmem: memory corrupted - invalid head sign"); if (*(int *)(begin + strlen (MEM_BEGIN) + 1) != size) die ("checkmem: memory corrupted - invalid size"); end = begin + size + CONTROL_SIZE - strlen (MEM_END) - 1; if (strcmp (end, MEM_END)) die ("checkmem: memory corrupted - invalid end sign"); } void *getmem (int size) { char * mem; if ((mem = mem_alloc(size)) == NULL) die ("getmem: no more memory (%d)", size); memset (mem, 0, size); // checkmem (mem, size); return mem; } void *mem_alloc(int size) { char * p; char * mem; p = (char *)malloc (CONTROL_SIZE + size); if (!p) die ("getmem: no more memory (%d)", size); /* Write the MEM_BEGIN magic in the beginning of allocated memory. */ strcpy (p, MEM_BEGIN); p += strlen (MEM_BEGIN) + 1; /* Write the size after the magic. */ *(int *)p = size; p += sizeof (int); mem = p; p += size; strcpy (p, MEM_END); return mem; } void * expandmem (void * vp, int size, int by) { int allocated; char * mem, * p = vp; int expand_by = by; if (p) { checkmem (p, size); allocated = CONTROL_SIZE + size; p -= (strlen (MEM_BEGIN) + 1 + sizeof (int)); } else { allocated = 0; /* add control bytes to the new allocated area */ expand_by += CONTROL_SIZE; } p = realloc (p, allocated + expand_by); if (!p) die ("expandmem: no more memory (%d)", size); if (!vp) { strcpy (p, MEM_BEGIN); } mem = p + strlen (MEM_BEGIN) + 1 + sizeof (int); *(int *)(p + strlen (MEM_BEGIN) + 1) = size + by; /* fill new allocated area by 0s */ if(by > 0) memset (mem + size, 0, by); strcpy (mem + size + by, MEM_END); // checkmem (mem, size + by); return mem; } void freemem (void * vp) { char * p = vp; int size; if (!p) return; size = get_mem_size (vp); checkmem (p, size); p -= (strlen (MEM_BEGIN) + 1 + sizeof (int)); strcpy (p, MEM_FREED); strcpy (p + size + CONTROL_SIZE - strlen (MEM_END) - 1, MEM_FREED); free (p); } typedef int (*func_t) (char *); static int is_readonly_dir (char * dir) { /* int fd; char template [1024]; snprintf (template, 1024, "%s/testXXXXXX", dir); fd = mkstemp (template); if (fd >= 0) { close (fd); return 0; } */ if (utime (dir, 0) != -1) /* this is not ro mounted fs */ return 0; return (errno == EROFS) ? 1 : 0; } #ifdef __i386__ #include #include #define __NR_bad_stat64 195 _syscall2(long, bad_stat64, char *, filename, struct stat64 *, statbuf); #else #define bad_stat64 stat64 #endif /* yes, I know how ugly it is */ #define return_stat_field(field) \ struct stat st;\ struct stat64 st64;\ \ if (bad_stat64 (file_name, &st64) == 0) {\ return st64.st_##field;\ } else if (stat (file_name, &st) == 0)\ return st.st_##field;\ \ perror ("stat failed");\ exit (8);\ mode_t get_st_mode (char * file_name) { return_stat_field (mode); } /* may I look at this undocumented (at least in the info of libc 2.3.1-58) field? */ dev_t get_st_rdev (char * file_name) { return_stat_field (rdev); } off64_t get_st_size (char * file_name) { return_stat_field (size); } blkcnt64_t get_st_blocks (char * file_name) { return_stat_field (blocks); } static int _is_mounted (char * device_name, func_t f) { int retval; FILE *fp; struct mntent *mnt; struct statfs stfs; struct stat root_st; mode_t mode; if (stat ("/", &root_st) == -1) die ("is_mounted: could not stat \"/\": %s\n", strerror(errno)); mode = get_st_mode (device_name); if (S_ISREG (mode)) /* regular file can not be mounted */ return 0; if (!S_ISBLK (mode)) die ("is_mounted: %s is neither regular file nor block device", device_name); if (root_st.st_dev == get_st_rdev (device_name)) { /* device is mounted as root. Check whether it is mounted read-only */ return (f ? f ("/") : 1); } /* if proc filesystem is mounted */ if (statfs ("/proc", &stfs) == -1 || stfs.f_type != 0x9fa0/*procfs magic*/ || (fp = setmntent ("/proc/mounts", "r")) == NULL) { /* proc filesystem is not mounted, or /proc/mounts does not exist */ if (f) return (user_confirmed (stderr, " (could not figure out) Is filesystem mounted read-only? (Yes)", "Yes\n")); else return (user_confirmed (stderr, " (could not figure out) Is filesystem mounted? (Yes)", "Yes\n")); } retval = 0; while ((mnt = getmntent (fp)) != NULL) if (strcmp (device_name, mnt->mnt_fsname) == 0) { retval = (f ? f (mnt->mnt_dir) : 1/*mounted*/); break; } endmntent (fp); return retval; } int is_mounted_read_only (char * device_name) { return _is_mounted (device_name, is_readonly_dir); } int is_mounted (char * device_name) { return _is_mounted (device_name, 0); } char buf1 [100]; char buf2 [100]; void print_how_fast (unsigned long passed, unsigned long total, int cursor_pos, int reset_time) { static time_t t0 = 0, t1 = 0, t2 = 0; int speed; int indent; if (reset_time) time (&t0); time (&t1); if (t1 != t0) { speed = passed / (t1 - t0); if (total - passed) { if (t1 - t2 < 1) return; t2 = t1; } } else speed = 0; /* what has to be written */ if (total) sprintf (buf1, "left %lu, %d /sec", total - passed, speed); else { /*(*passed) ++;*/ sprintf (buf1, "done %lu, %d /sec", passed, speed); } /* make indent */ indent = 79 - cursor_pos - strlen (buf1); memset (buf2, ' ', indent); buf2[indent] = 0; fprintf (stderr, "%s%s", buf2, buf1); memset (buf2, '\b', indent + strlen (buf1)); buf2 [indent + strlen (buf1)] = 0; fprintf (stderr, "%s", buf2); fflush (stderr); } static char * strs[] = {"0%",".",".",".",".","20%",".",".",".",".","40%",".",".",".",".","60%",".",".",".",".","80%",".",".",".",".","100%"}; static char progress_to_be[1024]; static char current_progress[1024]; static void str_to_be (char * buf, int prosents) { int i; prosents -= prosents % 4; buf[0] = 0; for (i = 0; i <= prosents / 4; i ++) strcat (buf, strs[i]); } void print_how_far (FILE * fp, unsigned long * passed, unsigned long total, unsigned int inc, int quiet) { int percent; if (*passed == 0) current_progress[0] = 0; (*passed) += inc; if (*passed > total) { /* fprintf (fp, "\nprint_how_far: total %lu has been reached already. cur=%lu\n", total, *passed);*/ return; } percent = ((*passed) * 100) / total; str_to_be (progress_to_be, percent); if (strlen (current_progress) != strlen (progress_to_be)) { fprintf (fp, "%s", progress_to_be + strlen (current_progress)); } strcat (current_progress, progress_to_be + strlen (current_progress)); if (!quiet) { print_how_fast(*passed /* - inc*/, total, strlen (progress_to_be), (*passed == inc) ? 1 : 0); } fflush (fp); } /* calculates number of blocks in a file. Returns 0 for "sparse" regular files and files other than regular files and block devices */ unsigned long count_blocks (char * filename, int blocksize) { loff_t high, low; int fd; unsigned long sz; __u64 size; if (!S_ISBLK (get_st_mode (filename)) && !S_ISREG (get_st_mode (filename))) return 0; fd = open (filename, O_RDONLY); if (fd == -1) die ("count_blocks: open failed (%s)", strerror (errno)); #ifdef BLKGETSIZE64 { if (ioctl (fd, BLKGETSIZE64, &size) >= 0) { size = (size / 4096) * 4096 / blocksize; sz = size; if ((__u64)sz != size) die ("count_blocks: block device too large"); return sz; } } #endif #ifdef BLKGETSIZE { if (ioctl (fd, BLKGETSIZE, &sz) >= 0) { size = sz; return (size * 512 / 4096) * 4096 / blocksize; } } #endif low = 0; for( high = 1; valid_offset (fd, high); high *= 2 ) low = high; while (low < high - 1) { const loff_t mid = ( low + high ) / 2; if (valid_offset (fd, mid)) low = mid; else high = mid; } valid_offset (fd, 0); close (fd); return (low + 1) * 4096 / 4096 / blocksize ; } /* there are masks for certain bits */ __u16 mask16 (int from, int count) { __u16 mask; mask = (0xffff >> from); mask <<= from; mask <<= (16 - from - count); mask >>= (16 - from - count); return mask; } __u32 mask32 (int from, int count) { __u32 mask; mask = (0xffffffff >> from); mask <<= from; mask <<= (32 - from - count); mask >>= (32 - from - count); return mask; } __u64 mask64 (int from, int count) { __u64 mask; mask = (0xffffffffffffffffLL >> from); mask <<= from; mask <<= (64 - from - count); mask >>= (64 - from - count); return mask; } __u32 get_random (void) { srandom (time (0)); return random (); } /* this implements binary search in the array 'base' among 'num' elements each of those is 'width' bytes long. 'comp_func' is used to compare keys */ int reiserfs_bin_search (void * key, void * base, __u32 num, int width, __u32 * ppos, comparison_fn_t comp_func) { __u32 rbound, lbound, j; int ret; if (num == 0 || base == NULL) { /* objectid map may be 0 elements long */ *ppos = 0; return POSITION_NOT_FOUND; } lbound = 0; rbound = num - 1; for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) { ret = comp_func ((void *)((char *)base + j * width), key ) ; if (ret < 0) { /* second is greater */ lbound = j + 1; continue; } else if (ret > 0) { /* first is greater */ if (j == 0) break; rbound = j - 1; continue; } else { /* equal */ *ppos = j; return POSITION_FOUND; } } *ppos = lbound; return POSITION_NOT_FOUND; } #define BLOCKLIST__ELEMENT_NUMBER 10 /*element is block number and device*/ int blockdev_list_compare (const void * block1, const void * block2) { if (*(__u32 *)block1 < *(__u32 *)block2) return -1; if (*(__u32 *)block1 > *(__u32 *)block2) return 1; if (*((__u32 *)block1 + 1) < *((__u32 *)block2 + 1)) return -1; if (*((__u32 *)block1 + 1) > *((__u32 *)block2 + 1)) return 1; return 0; } /* return -1 if smth found, otherwise return position which new item should be inserted into */ /* int blocklist__is_block_saved (struct block_handler ** base, __u32 * count, __u32 blocknr, dev_t device, __u32 * position) { struct block_handler block_h; *position = 0; if (*base == NULL) return 0; block_h.blocknr = blocknr; block_h.device = device; if (reiserfs_bin_search (&block_h, *base, *count, sizeof (block_h), position, blocklist_compare) == POSITION_FOUND) return 1; return 0; } */ void blocklist__insert_in_position (void *elem, void **base, __u32 *count, int elem_size, __u32 *position) { if (elem_size == 0) return; if (*base == NULL) *base = getmem (BLOCKLIST__ELEMENT_NUMBER * elem_size); if (*count == get_mem_size((void *)*base) / elem_size) *base = expandmem (*base, get_mem_size((void *)*base), BLOCKLIST__ELEMENT_NUMBER * elem_size); if (*position < *count) { memmove (*base + (*position + 1), *base + (*position), (*count - *position) * elem_size); } memcpy (*base + (char) *position * elem_size, elem, elem_size); *count+=1; } static int get_random_bytes (void *out, int size) { int fd; if ((fd = open("/dev/urandom", O_RDONLY)) == -1) return 1; if (read(fd, out, size) <= 0) { close (fd); return 1; } close (fd); return 0; } int generate_random_uuid (unsigned char * uuid) { if (get_random_bytes(uuid, 16)) { return -1; } /* Set the UUID variant to DCE */ uuid[8] = (uuid[8] & 0x3F) | 0x80; /* Set UUID version to 4 --- truely random generation */ uuid[6] = (uuid[6] & 0x0F) | 0x40; return 0; } int uuid_is_correct (unsigned char * uuid) { int i; for (i = 0; i < 16; i++) if (uuid[i]) break; if (i == 16) return 0; if (!misc_test_bit(7, &uuid[8]) || misc_test_bit(6, &uuid[8])) return 0; if (misc_test_bit(7, &uuid[6]) || !misc_test_bit(6, &uuid[6]) || misc_test_bit(5, &uuid[6]) || misc_test_bit(4, &uuid[6])) return 0; return 1; } static int parse_uuid (const unsigned char * in, unsigned char * uuid) { int i, j = 0; unsigned char frame[3]; if (strlen(in) != 36) return -1; for (i = 0; i < 36; i++) { if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) { if (in[i] != '-') return 0; } else if (!isxdigit(in[i])) { return -1; } } frame[2] = 0; for (i = 0; i < 36; i ++) { if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) continue; frame[0] = in[i++]; frame[1] = in[i]; uuid[j++] = strtoul(frame, NULL, 16); } return 0; } int set_uuid (const unsigned char * text, unsigned char * UUID) { if (parse_uuid (text, UUID) || !uuid_is_correct(UUID)) return -1; return 0; } /* 0 - dma is not supported, scsi or regular file */ /* 1 - xt drive */ /* 2 - ide drive */ static void get_dma_support(dma_info_t *dma_info){ if (S_ISREG(dma_info->stat.st_mode)) dma_info->stat.st_rdev = dma_info->stat.st_dev; if (IDE_DISK_MAJOR(MAJOR(dma_info->stat.st_rdev))) { dma_info->support_type = 2; return; } #ifdef XT_DISK_MAJOR if (MAJOR(dma_info->stat.st_rdev) == XT_DISK_MAJOR) { dma_info->support_type = 1; return; } #endif dma_info->support_type = 0; } /* * Return values: * 0 - ok; * 1 - preparation cannot be done * -1 - preparation failed */ int prepare_dma_check(dma_info_t *dma_info) { DIR *dir; struct dirent *dirent; struct stat64 stat; dev_t rdev; int rem; char buf[256]; #ifndef HDIO_GET_DMA return -1; #endif if (fstat64(dma_info->fd, &dma_info->stat)) die("stat64 on device failed\n"); get_dma_support(dma_info); /* dma should be supported */ if (dma_info->support_type == 0) return 1; if (dma_info->support_type == 2) { rdev = dma_info->stat.st_rdev; if ((rem = (MINOR(rdev) % 64)) != 0) { rdev -= rem; if(!(dir = opendir("/dev/"))) { dma_info->support_type = 1; return 0; } while ((dirent = readdir(dir)) != NULL) { if (strncmp(dirent->d_name, ".", 1) == 0 || strncmp(dirent->d_name, "..", 2) == 0) continue; memset(buf, 0, 256); strncat(buf, "/dev/", 5); strncat(buf, dirent->d_name, strlen(dirent->d_name)); if (stat64(buf, &stat)) break; if (S_ISBLK(stat.st_mode) && stat.st_rdev == rdev) { dma_info->stat = stat; dma_info->fd = open(buf, O_RDONLY | O_LARGEFILE); closedir(dir); return 0; } } closedir(dir); dma_info->support_type = 1; return 1; } } return 0; } static int is_dma_on (int fd) { #ifdef HDIO_GET_DMA static long parm; if (ioctl(fd, HDIO_GET_DMA, &parm)) return -1; else return parm; #endif return 0; } static __u64 dma_speed(int fd, int support_type) { static struct hd_driveid id; __u64 speed = 0; if (support_type != 2) return 0; #ifdef HDIO_OBSOLETE_IDENTITY if (!ioctl(fd, HDIO_GET_IDENTITY, &id) || !ioctl(fd, HDIO_OBSOLETE_IDENTITY)) { #else if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) { #endif speed |= (__u64)id.dma_1word & ~(__u64)0xff; speed |= ((__u64)id.dma_mword & ~(__u64)0xff) << 16; speed |= ((__u64)id.dma_ultra & ~(__u64)0xff) << 32; } else if (errno == -ENOMSG) return -1; else return -1; return speed; } int get_dma_info(dma_info_t *dma_info) { if ((dma_info->dma = is_dma_on(dma_info->fd)) == -1) return -1; if ((dma_info->speed = dma_speed(dma_info->fd, dma_info->support_type)) == (__u64)-1) return -1; return 0; } void clean_after_dma_check(int fd, dma_info_t *dma_info) { signal(SIGALRM, SIG_IGN); if (dma_info->fd && fd != dma_info->fd) close(dma_info->fd); } /* Only le bitops operations are used. */ inline int misc_set_bit (unsigned long long nr, void * addr) { __u8 * p, mask; int retval; p = (__u8 *)addr; p += nr >> 3; mask = 1 << (nr & 0x7); /*cli();*/ retval = (mask & *p) != 0; *p |= mask; /*sti();*/ return retval; } inline int misc_clear_bit (unsigned long long nr, void * addr) { __u8 * p, mask; int retval; p = (__u8 *)addr; p += nr >> 3; mask = 1 << (nr & 0x7); /*cli();*/ retval = (mask & *p) != 0; *p &= ~mask; /*sti();*/ return retval; } inline int misc_test_bit(unsigned long long nr, const void * addr) { __u8 * p, mask; p = (__u8 *)addr; p += nr >> 3; mask = 1 << (nr & 0x7); return ((mask & *p) != 0); } inline unsigned long long misc_find_first_zero_bit (const void *vaddr, unsigned long long size) { const __u8 *p = vaddr, *addr = vaddr; unsigned long long res; if (!size) return 0; size = (size >> 3) + ((size & 0x7) > 0); while (*p++ == 255) { if (--size == 0) return (unsigned long long)(p - addr) << 3; } --p; for (res = 0; res < 8; res++) if (!misc_test_bit (res, p)) break; return res + (p - addr) * 8; } inline unsigned long long misc_find_next_zero_bit (const void *vaddr, unsigned long long size, unsigned long long offset) { const __u8 *addr = vaddr; const __u8 *p = addr + (offset >> 3); int bit = offset & 7; unsigned long long res; if (offset >= size) return size; if (bit) { /* Look for zero in first char */ for (res = bit; res < 8; res++) if (!misc_test_bit (res, p)) return res + (p - addr) * 8; p++; } /* No zero yet, search remaining full bytes for a zero */ res = misc_find_first_zero_bit (p, size - 8 * (p - addr)); return res + (p - addr) * 8; } inline unsigned long long misc_find_first_set_bit (const void *vaddr, unsigned long long size) { const __u8 *p = vaddr, *addr = vaddr; unsigned long long res; if (!size) return 0; size = (size >> 3) + ((size & 0x7) > 0); while (*p++ == 0) { if (--size == 0) return (unsigned long long)(p - addr) << 3; } --p; for (res = 0; res < 8; res++) if (misc_test_bit (res, p)) break; return res + (p - addr) * 8; } inline unsigned long long misc_find_next_set_bit(const void *vaddr, unsigned long long size, unsigned long long offset) { const __u8 *addr = vaddr; const __u8 *p = addr + (offset >> 3); int bit = offset & 7; unsigned long long res; if (offset >= size) return size; if (bit) { /* Look for zero in first char */ for (res = bit; res < 8; res++) if (misc_test_bit (res, p)) return res + (p - addr) * 8; p++; } /* No set bit yet, search remaining full bytes for a 1 */ res = misc_find_first_set_bit (p, size - 8 * (p - addr)); return res + (p - addr) * 8; } #include "credits.h" /* Reads the "CREDITS" file and prints one paragraph from it. */ void misc_print_credit(FILE *out) { char *line; fprintf(out, "\nA pair of credits:\n"); line = credits[(random() % CREDITS_COUNT)]; fprintf(out, "%s", line); line = credits[(random() % CREDITS_COUNT)]; fprintf(out, "%s", line); } reiserfsprogs-3.6.9/NEWS0000664000077100007710000000000007665645672010631 reiserfsprogs-3.6.9/fsck/0000777000077100007710000000000007705315453011136 5reiserfsprogs-3.6.9/fsck/ustree.c0000664000077100007710000001760007705261642012533 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" /* key1 and key2 are pointer to deh_offset of the struct reiserfs_de_head */ int comp_dir_entries (void * key1, void * key2) { __u32 off1, off2; off1 = le32_to_cpu (*(__u32 *)key1); off2 = le32_to_cpu (*(__u32 *)key2); if (off1 < off2) return -1; if (off1 > off2) return 1; return 0; } struct tree_balance * cur_tb = 0; void reiserfsck_paste_into_item (struct path * path, const char * body, int size) { struct tree_balance tb; init_tb_struct (&tb, fs, path, size); if (fix_nodes (/*tb.transaction_handle,*/ M_PASTE, &tb, 0/*ih*/) != CARRY_ON) //fix_nodes(options, tree_balance, ih_to_option, body_to_option) die ("reiserfsck_paste_into_item: fix_nodes failed"); do_balance (/*tb.transaction_handle,*/ &tb, 0, body, M_PASTE, 0/*zero num*/); } void reiserfsck_insert_item (struct path * path, struct item_head * ih, const char * body) { struct tree_balance tb; init_tb_struct (&tb, fs, path, IH_SIZE + get_ih_item_len(ih)); if (fix_nodes (/*tb.transaction_handle,*/ M_INSERT, &tb, ih/*, body*/) != CARRY_ON) die ("reiserfsck_insert_item: fix_nodes failed"); do_balance (/*tb.transaction_handle,*/ &tb, ih, body, M_INSERT, 0/*zero num*/); } static void free_unformatted_nodes (struct item_head * ih, struct buffer_head * bh) { __u32 * punfm = (__u32 *)B_I_PITEM (bh, ih); unsigned int i; for (i = 0; i < I_UNFM_NUM (ih); i ++, punfm ++) if (*punfm != 0) { struct buffer_head * to_be_forgotten; to_be_forgotten = find_buffer (fs->fs_dev, le32_to_cpu (*punfm), fs->fs_blocksize); if (to_be_forgotten) { //atomic_inc(&to_be_forgotten->b_count); to_be_forgotten->b_count ++; bforget (to_be_forgotten); } reiserfs_free_block (fs, le32_to_cpu (*punfm)); } } void reiserfsck_delete_item (struct path * path, int temporary) { struct tree_balance tb; struct item_head * ih = PATH_PITEM_HEAD (path); if (is_indirect_ih (ih) && !temporary) free_unformatted_nodes (ih, PATH_PLAST_BUFFER (path)); init_tb_struct (&tb, fs, path, -(IH_SIZE + get_ih_item_len(ih))); if (fix_nodes (/*tb.transaction_handle,*/ M_DELETE, &tb, 0/*ih*/) != CARRY_ON) die ("reiserfsck_delete_item: fix_nodes failed"); do_balance (/*tb.transaction_handle,*/ &tb, 0, 0, M_DELETE, 0/*zero num*/); } void reiserfsck_cut_from_item (struct path * path, int cut_size) { struct tree_balance tb; struct item_head * ih; if (cut_size >= 0) die ("reiserfsck_cut_from_item: cut size == %d", cut_size); if (is_indirect_ih (ih = PATH_PITEM_HEAD (path))) { __u32 unfm_ptr = B_I_POS_UNFM_POINTER (PATH_PLAST_BUFFER (path), ih, I_UNFM_NUM (ih) - 1); if (unfm_ptr != 0) { struct buffer_head * to_be_forgotten; to_be_forgotten = find_buffer (fs->fs_dev, le32_to_cpu (unfm_ptr), fs->fs_blocksize); if (to_be_forgotten) { //atomic_inc(&to_be_forgotten->b_count); to_be_forgotten->b_count ++; bforget (to_be_forgotten); } reiserfs_free_block (fs, le32_to_cpu (unfm_ptr)); } } init_tb_struct (&tb, fs, path, cut_size); if (fix_nodes (/*tb.transaction_handle,*/ M_CUT, &tb, 0) != CARRY_ON) die ("reiserfsck_cut_from_item: fix_nodes failed"); do_balance (/*tb.transaction_handle,*/ &tb, 0, 0, M_CUT, 0/*zero num*/); } /* uget_rkey is utils clone of stree.c/get_rkey */ /* struct key * uget_rkey (struct path * path) { int pos, offset = path->path_length; struct buffer_head * bh; if (offset < FIRST_PATH_ELEMENT_OFFSET) die ("uget_rkey: illegal offset in the path (%d)", offset); while (offset-- > FIRST_PATH_ELEMENT_OFFSET) { if (! buffer_uptodate (PATH_OFFSET_PBUFFER (path, offset))) die ("uget_rkey: parent is not uptodate"); // Parent at the path is not in the tree now. if (! B_IS_IN_TREE (bh = PATH_OFFSET_PBUFFER (path, offset))) die ("uget_rkey: buffer on the path is not in tree"); // Check whether position in the parrent is correct. if ((pos = PATH_OFFSET_POSITION (path, offset)) > B_NR_ITEMS (bh)) die ("uget_rkey: invalid position (%d) in the path", pos); // Check whether parent at the path really points to the child. if (get_dc_child_blocknr (B_N_CHILD (bh, pos)) != PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr) die ("uget_rkey: invalid block number (%d). Must be %ld", get_dc_child_blocknr (B_N_CHILD (bh, pos)), PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr); // Return delimiting key if position in the parent is not the last one. if (pos != B_NR_ITEMS (bh)) return B_N_PDELIM_KEY(bh, pos); } // there is no right delimiting key return 0; } */ static unsigned long first_child (struct buffer_head * bh) { return get_dc_child_blocknr (B_N_CHILD (bh, 0)); } #if 0 static unsigned long last_child (struct buffer_head * bh) { return child_block_number (bh, node_item_number (bh)); } #endif static unsigned long get_child (int pos, struct buffer_head * parent) { if (pos == -1) return -1; if (pos > B_NR_ITEMS (parent)) die ("get_child: no child found, should not happen: %d of %d", pos, B_NR_ITEMS (parent)); return get_dc_child_blocknr (B_N_CHILD (parent, pos)); } static void print (int cur, int total) { if (fsck_quiet (fs)) return; printf ("/%3d (of %3d)", cur, total);fflush (stdout); } /* erase /XXX(of XXX) */ static void erase (void) { if (fsck_quiet (fs)) return; printf ("\b\b\b\b\b\b\b\b\b\b\b\b\b"); printf (" "); printf ("\b\b\b\b\b\b\b\b\b\b\b\b\b"); fflush (stdout); } void pass_through_tree (reiserfs_filsys_t * fs, do_after_read_t action1, do_on_full_path_t action2, int depth) { struct buffer_head * path[MAX_HEIGHT] = {0,}; int total[MAX_HEIGHT] = {0,}; int cur[MAX_HEIGHT] = {0,}; int h = 0; unsigned long block = get_sb_root_block (fs->fs_ondisk_sb); int problem; if (block >= get_sb_block_count (fs->fs_ondisk_sb) || not_data_block (fs, block)) { die ("\nBad root block %lu. (--rebuild-tree did not complete)\n", block); } while ( 1 ) { problem = 0; if (path[h]) die ("pass_through_tree: empty slot expected"); if (h) print (cur[h - 1], total[h - 1]); if (fs->fs_badblocks_bm && reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, block)) { fsck_log ("%s: block %lu specified in badblock list found in tree, whole subtree skipped\n", __FUNCTION__, block); fsck_data (fs)->check.bad_nodes++; one_more_corruption (fs, FATAL); if (h == 0) { brelse (path[h]); path[h] = 0; break; } problem = 1; } else { path[h] = bread (fs->fs_dev, block, fs->fs_blocksize); if (path[h] == 0) /* FIXME: handle case when read failed */ die ("pass_through_tree: unable to read %lu block on device 0x%x\n", block, fs->fs_dev); if (action1) if ((problem = action1 (fs, path, h))) { fsck_log (" the problem in the internal node occured (%lu), whole subtree is skipped\n", path[h]->b_blocknr); fsck_data (fs)->check.bad_nodes++; if (h == 0) { brelse (path[h]); path[h] = 0; break; } } } /* Time to stop. */ if (h == depth) problem ++; if (problem || is_leaf_node (path[h])) { if (!problem && action2) action2 (fs, path, h); brelse (path[h]); if (h) erase (); while (h && (cur[h-1] == total[h-1] || problem)) { problem = 0; path[h] = 0; h --; brelse (path[h]); if (h) erase (); } if (h == 0) { path[h] = 0; break; } block = get_child (cur[h - 1], path[h-1]); cur[h - 1] ++; path[h] = 0; continue; } total[h] = B_NR_ITEMS (path[h]) + 1; cur[h] = 1; block = first_child (path[h]); h ++; } } reiserfsprogs-3.6.9/fsck/lost+found.c0000664000077100007710000002542307705261642013316 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" void erase_name (int len); void print_name (char * name, int len); void modify_item (struct item_head * ih, void * item); /* fixme: search_by_key is not needed after any add_entry */ static __u64 _look_for_lost (reiserfs_filsys_t * fs, int link_lost_dirs) { struct key key, prev_key, * rdkey; INITIALIZE_PATH (path); int item_pos; struct buffer_head * bh; struct item_head * ih; unsigned long leaves; int is_it_dir; static int lost_files = 0; /* looking for lost dirs we calculate amount of lost files, so that when we will look for lost files we will be able to stop when there are no lost files anymore */ int retval; __u64 size; key = root_dir_key; if (!link_lost_dirs && !lost_files) { /* we have to look for lost files but we know already that there are no any */ return 0; } fsck_progress ("Looking for lost %s:\n", link_lost_dirs ? "directories" : "files"); leaves = 0; /* total size of added entries */ size = 0; while (1) { retval = reiserfs_search_by_key_4 (fs, &key, &path); /* fixme: we assume path ends up with a leaf */ bh = get_bh (&path); item_pos = get_item_pos (&path); if (retval != ITEM_FOUND) { if (item_pos == get_blkh_nr_items (B_BLK_HEAD (bh))) { rdkey = uget_rkey (&path); if (!rdkey) { pathrelse (&path); break; } key = *rdkey; pathrelse (&path); continue; } /* we are on the item in the buffer */ } /* print ~ how many leaves were scanned and how fast it was */ if (!fsck_quiet (fs)) print_how_fast (leaves++, 0, 50, 0); for (ih = get_ih (&path); item_pos < get_blkh_nr_items (B_BLK_HEAD (bh)); item_pos ++, ih ++, PATH_LAST_POSITION(&path)++) { if (is_item_reachable (ih)) continue; /* found item which can not be reached */ if (!is_direntry_ih (ih) && !is_stat_data_ih (ih)) { continue; } if (is_direntry_ih (ih)) { /* if this directory has no stat data - try to recover it */ struct key sd; struct path tmp; sd = ih->ih_key; set_type_and_offset (KEY_FORMAT_1, &sd, SD_OFFSET, TYPE_STAT_DATA); if (reiserfs_search_by_key_4 (fs, &sd, &tmp) == ITEM_FOUND) { /* should not happen - because if there were a stat data - we would have done with the whole directory */ pathrelse (&tmp); continue; } lost_found_pass_stat (fs)->dir_recovered ++; create_dir_sd (fs, &tmp, &sd, modify_item); id_map_mark(proper_id_map (fs), get_key_objectid (&sd)); key = sd; pathrelse (&path); goto cont; } /* stat data marked "not having name" found */ if (is_stat_data_ih (get_ih(&path))) fix_obviously_wrong_sd_mode (&path); is_it_dir = ((not_a_directory (B_I_PITEM (bh,ih))) ? 0 : 1); if (is_it_dir) { struct key tmp_key; INITIALIZE_PATH (tmp_path); struct item_head * tmp_ih; /* there is no need to link empty lost directories into /lost+found */ tmp_key = ih->ih_key; set_type_and_offset (KEY_FORMAT_1, &tmp_key, 0xffffffff, TYPE_DIRENTRY); reiserfs_search_by_key_4 (fs, &tmp_key, &tmp_path); tmp_ih = get_ih (&tmp_path); tmp_ih --; if (not_of_one_file (&tmp_key, tmp_ih)) reiserfs_panic ("not directory found"); if (!is_direntry_ih (tmp_ih) || (get_deh_offset (B_I_DEH (get_bh (&tmp_path), tmp_ih) + get_ih_entry_count (tmp_ih) - 1) == DOT_DOT_OFFSET)) { /* last directory item is either stat data or empty directory item - do not link this dir into lost+found */ lost_found_pass_stat (fs)->empty_lost_dirs ++; pathrelse (&tmp_path); continue; } pathrelse (&tmp_path); } if (link_lost_dirs && !is_it_dir) { /* we are looking for directories and it is not a dir */ lost_files ++; continue; } lost_found_pass_stat (fs)->lost_found ++; { struct key obj_key = {0, 0, {{0, 0},}}; char * lost_name; struct item_head tmp_ih; /* key to continue */ key = ih->ih_key; set_key_objectid (&key, get_key_objectid (&key) + 1); tmp_ih = *ih; if (id_map_test(semantic_id_map (fs), get_key_objectid (&ih->ih_key))) { /* objectid is used, relocate an object */ lost_found_pass_stat (fs)->oid_sharing ++; if (is_it_dir) { relocate_dir (&tmp_ih, 1); lost_found_pass_stat (fs)->oid_sharing_dirs_relocated ++; } else { rewrite_file (&tmp_ih, 1, 1); lost_found_pass_stat (fs)->oid_sharing_files_relocated ++; } linked_already(&tmp_ih.ih_key); } else { if (!is_it_dir) id_map_mark(semantic_id_map (fs), get_key_objectid (&ih->ih_key)); } asprintf (&lost_name, "%u_%u", get_key_dirid (&tmp_ih.ih_key), get_key_objectid (&tmp_ih.ih_key)); /* entry in lost+found directory will point to this key */ set_key_dirid (&obj_key, get_key_dirid (&tmp_ih.ih_key)); set_key_objectid (&obj_key, get_key_objectid (&tmp_ih.ih_key)); pathrelse (&path); /* 0 does not mean anyting - item with "." and ".." already exists and reached, so only name will be added */ size += reiserfs_add_entry (fs, &lost_found_dir_key, lost_name, name_length (lost_name, lost_found_dir_format), &obj_key, 0/*fsck_need*/); if (is_it_dir) { /* fixme: we hope that if we will try to pull all the directory right now - then there will be less lost_found things */ print_name (lost_name, strlen (lost_name)); /*fsck_progress ("\tChecking lost dir \"%s\":", lost_name);*/ rebuild_semantic_pass (&obj_key, &lost_found_dir_key, /*dot_dot*/0, /*reloc_ih*/0); erase_name (strlen (lost_name)); /*fsck_progress ("finished\n");*/ lost_found_pass_stat (fs)->lost_found_dirs ++; } else { if (reiserfs_search_by_key_4 (fs, &obj_key, &path) != ITEM_FOUND) reiserfs_panic ("look_for_lost: lost file stat data %K not found", &obj_key); /* check_regular_file does not mark stat data reachable */ mark_item_reachable (get_ih (&path), get_bh (&path)); rebuild_check_regular_file (&path, get_item (&path), 0/*reloc_ih*/); pathrelse (&path); lost_found_pass_stat (fs)->lost_found_files ++; lost_files --; } free (lost_name); goto cont; } } /* for */ prev_key = key; PATH_LAST_POSITION(&path) = item_pos - 1; rdkey = reiserfs_next_key (&path); if (rdkey) key = *rdkey; else break; if (comp_keys (&prev_key, &key) != -1) reiserfs_panic ("pass_3a: key must grow 2: prev=%k next=%k", &prev_key, &key); pathrelse (&path); cont: if (!link_lost_dirs && !lost_files) { break; } } pathrelse (&path); #if 0 /* check names added we just have added to/lost+found. Those names are marked DEH_Lost_found flag */ fsck_progress ("Checking lost+found directory.."); fflush (stdout); check_semantic_tree (&lost_found_dir_key, &root_dir_key, 0, 1/* lost+found*/); fsck_progress ("finished\n"); #endif return size; } static void save_lost_found_result (reiserfs_filsys_t * fs) { FILE * file; int retval; /* save bitmaps with which we will be able start reiserfs from pass 1 */ file = open_file ("temp_fsck_file.deleteme", "w+"); if (!file) return; reiserfs_begin_stage_info_save (file, LOST_FOUND_DONE); reiserfs_end_stage_info_save (file); close_file (file); retval = rename ("temp_fsck_file.deleteme", state_dump_file (fs)); if (retval != 0) fsck_progress ("pass 0: Could not rename the temporary file temp_fsck_file.deleteme to %s", state_dump_file (fs)); } /* we have nothing to load from a state file, but we have to fetch on-disk bitmap, copy it to allocable bitmap, and fetch objectid map */ void load_lost_found_result (reiserfs_filsys_t * fs) { fsck_new_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_copy (fsck_new_bitmap (fs), fs->fs_bitmap2); fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_copy (fsck_allocable_bitmap (fs), fs->fs_bitmap2); fs->block_allocator = reiserfsck_reiserfs_new_blocknrs; fs->block_deallocator = reiserfsck_reiserfs_free_block; /* we need objectid map on semantic pass to be able to relocate files */ proper_id_map (fs) = id_map_init(); /* Not implemented yet. fetch_objectid_map (proper_id_map (fs), fs); */ } void after_lost_found (reiserfs_filsys_t * fs) { /* update super block: objectid map, fsck state */ set_sb_fs_state (fs->fs_ondisk_sb, LOST_FOUND_DONE); mark_buffer_dirty (fs->fs_super_bh); /* write all dirty blocks */ fsck_progress ("Flushing.."); id_map_flush(proper_id_map (fs), fs); fs->fs_dirt = 1; reiserfs_flush_to_ondisk_bitmap (fsck_new_bitmap(fs), fs); reiserfs_flush (fs); fsck_progress ("finished\n"); stage_report (0x3a, fs); if (!fsck_run_one_step (fs)) { if (fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1)) /* reiserfsck continues */ return; } save_lost_found_result (fs); id_map_free(proper_id_map (fs)); proper_id_map (fs) = 0; fs->fs_dirt = 1; reiserfs_close (fs); exit(EXIT_OK); } void pass_3a_look_for_lost (reiserfs_filsys_t * fs) { INITIALIZE_PATH (path); struct item_head * ih; void * sd; __u64 size, sd_size; __u32 blocks; __u16 mode; __u32 objectid; unsigned int gen_counter; fsck_progress ("Pass 3a (looking for lost dir/files):\n"); /* when warnings go not to stderr - separate them in the log */ if (fsck_log_file (fs) != stderr) fsck_log ("####### Pass 3a (lost+found pass) #########\n"); /* look for lost dirs first */ size = _look_for_lost (fs, 1); /* link files which are still lost */ size += _look_for_lost (fs, 0); /* update /lost+found sd_size and sd_blocks (nlink is correct already) */ objectid = reiserfs_find_entry (fs, &root_dir_key, "lost+found", &gen_counter, &lost_found_dir_key); if (!objectid) { reiserfs_panic ("look_for_lost: The entry 'lost+found' could not be found in the root directory."); } if (reiserfs_search_by_key_4 (fs, &lost_found_dir_key, &path) != ITEM_FOUND) reiserfs_panic ("look_for_lost: The StatData of the 'lost+found' directory %K could not be found", &lost_found_dir_key); ih = get_ih (&path); sd = get_item (&path); get_sd_size (ih, sd, &sd_size); size += sd_size; blocks = dir_size2st_blocks (size); set_sd_size (ih, sd, &size); set_sd_blocks (ih, sd, &blocks); /* make lost+found to be drwx------ */ mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR; set_sd_mode (ih, sd, &mode); mark_buffer_dirty (get_bh (&path)); pathrelse (&path); after_lost_found (fs); } reiserfsprogs-3.6.9/fsck/check_tree.c0000664000077100007710000007541607705261642013331 /* * Copyright 1999-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" struct check_relocated { __u32 old_dir_id; __u32 old_objectid; /*mode_t mode;*/ struct check_relocated * next; }; static struct check_relocated * relocated_list; void to_be_relocated (struct key * key) { struct check_relocated * cur, * prev, * new_relocated; cur = relocated_list; prev = 0; while (cur && comp_short_keys(key, (struct key *)cur) != 1) { if (comp_short_keys (key, (struct key *)cur) == 0) return; prev = cur; cur = cur->next; } new_relocated = getmem (sizeof (struct check_relocated)); copy_short_key ((struct key *)new_relocated, key); if (prev) { new_relocated->next = prev->next; prev->next = new_relocated; } else { new_relocated->next = relocated_list; relocated_list = new_relocated; } } int should_be_relocated (struct key * key) { struct check_relocated *cur, *prev; int ret = 0; if (!key) return 0; cur = relocated_list; prev = NULL; while (cur && comp_short_keys(key, (struct key *)cur) != 1) { if (comp_short_keys (key, (struct key *)cur) == 0) { ret = 1; break; } prev = cur; cur = cur->next; } if (ret) { /* cur is found */ if (prev) /* not the first */ prev->next = cur->next; else /* first */ relocated_list = cur->next; freemem (cur); } return ret; } void clear_relocated_list() { struct check_relocated *next; while (relocated_list) { next = relocated_list->next; freemem (relocated_list); relocated_list = next; } } // // // // check_fs_tree stops and recommends to run fsck --rebuild-tree when: // 1. read fails // 2. node of wrong level found in the tree // 3. something in the tree points to wrong block number // out of filesystem boundary is pointed by tree // to block marked as free in bitmap // the same block is pointed from more than one place // not data blocks (journal area, super block, bitmaps) // 4. bad formatted node found // 5. delimiting keys are incorrect // /* mark every block we see in the tree in control bitmap, so, when to make sure, that no blocks are pointed to from more than one place we use additional bitmap (control_bitmap). If we see pointer to a block we set corresponding bit to 1. If it is set already - run fsck with --rebuild-tree */ static reiserfs_bitmap_t * control_bitmap; static reiserfs_bitmap_t * source_bitmap; static int tree_scanning_failed = 0; /* 1 if block is not marked as used in the bitmap */ static int is_block_free (reiserfs_filsys_t * fs, unsigned long block) { return !reiserfs_bitmap_test_bit (source_bitmap, block); } /*static int hits = 0;*/ /* we have seen this block in the tree, mark corresponding bit in the control bitmap */ static void we_met_it (unsigned long block) { reiserfs_bitmap_set_bit (control_bitmap, block); /*hits ++;*/ } /* have we seen this block somewhere in the tree before? */ static int did_we_meet_it (unsigned long block) { return reiserfs_bitmap_test_bit (control_bitmap, block); } static void init_control_bitmap (reiserfs_filsys_t * fs) { unsigned int i; unsigned long block; unsigned long reserved; control_bitmap = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); if (!control_bitmap) die ("init_control_bitmap: Failed to allocate a control bitmap."); /*printf ("Initially number of zeros in control bitmap %d\n", reiserfs_bitmap_zeros (control_bitmap));*/ /* skipped and super block */ for (i = 0; i <= fs->fs_super_bh->b_blocknr; i ++) we_met_it (i); /*printf ("SKIPPED: %d blocks marked used (%d)\n", hits, reiserfs_bitmap_zeros (control_bitmap)); hits = 0;*/ /* bitmaps */ block = fs->fs_super_bh->b_blocknr + 1; for (i = 0; i < get_sb_bmap_nr (fs->fs_ondisk_sb); i ++) { we_met_it (block); if (spread_bitmaps (fs)) block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8); else block ++; } /*printf ("BITMAPS: %d blocks marked used (%d)\n", hits, reiserfs_bitmap_zeros (control_bitmap)); hits = 0;*/ /* mark as used area of the main device either containing a journal or reserved to hold it */ reserved = get_size_of_journal_or_reserved_area (fs->fs_ondisk_sb); /* where does journal area (or reserved journal area) start from */ if (!is_new_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) && !is_old_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) die ("init_control_bitmap: Wrong super block location. You must run --rebuild-sb."); block = get_journal_start_must (fs); for (i = block; i < reserved + block; i ++) we_met_it (i); if (fs->fs_badblocks_bm) for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { if (reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i)) we_met_it (i); } } /* if we managed to complete tree scanning and if control bitmap and/or proper amount of free blocks mismatch with bitmap on disk and super block's s_free_blocks - we can fix that */ static void handle_bitmaps (reiserfs_filsys_t * fs) { int problem = 0; if (tree_scanning_failed) { fsck_progress ("Could not scan the internal tree. --rebuild-tree is required\n"); return; } fsck_progress ("Comparing bitmaps.."); /* check free block counter */ if (get_sb_free_blocks (fs->fs_ondisk_sb) != reiserfs_bitmap_zeros (control_bitmap)) { /* fsck_log ("vpf-10630: The count of free blocks in the on-disk bitmap (%lu) mismatches " "with the correct one (%lu).\n", get_sb_free_blocks (fs->fs_ondisk_sb), reiserfs_bitmap_zeros (control_bitmap)); */ problem++; } if (reiserfs_bitmap_compare (source_bitmap, control_bitmap)) problem++; if (problem) { if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { fsck_log ("vpf-10630: The on-disk and the correct bitmaps differs. " "Will be fixed later.\n"); // fsck_progress ("Trying to fix bitmap ..\n"); /* mark blocks as used in source bitmap if they are used in control bitmap */ reiserfs_bitmap_disjunction (source_bitmap, control_bitmap); /* change used blocks count accordinly source bitmap, copy bitmap changes to on_disk bitmap */ set_sb_free_blocks (fs->fs_ondisk_sb, reiserfs_bitmap_zeros (source_bitmap)); reiserfs_bitmap_copy (fs->fs_bitmap2, source_bitmap); mark_buffer_dirty (fs->fs_super_bh); /* // check again if ((diff = reiserfs_bitmap_compare (source_bitmap, control_bitmap)) != 0) { // do not mark them as fatal or fixable because one can live with leaked space. // So this is not a fatal corruption, and fix-fixable cannot fix it fsck_progress (" bitmaps were not recovered. \n" "\tYou can either run rebuild-tree or live with %d leaked blocks\n", diff); } else { fsck_progress ("finished\n"); } */ } else if (problem) { fsck_log ("vpf-10640: The on-disk and the correct bitmaps differs.\n"); while (problem) { /* fixable corruptions because we can try to recover them without rebuilding the tree */ one_more_corruption (fs, FIXABLE); problem --; } } } else fsck_progress ("finished\n"); return; } static int auto_handle_bitmaps (reiserfs_filsys_t *fs) { unsigned long i; if (source_bitmap->bm_byte_size != control_bitmap->bm_byte_size) return -1; for (i = 0; i < source_bitmap->bm_byte_size; i ++) { if (control_bitmap->bm_map[i] & ~source_bitmap->bm_map[i]) { return 1; } } return 0; } /* is this block legal to be pointed to by some place of the tree? */ static int bad_block_number (reiserfs_filsys_t * fs, unsigned long block) { if (block >= get_sb_block_count (fs->fs_ondisk_sb) || not_data_block (fs, block)) { /* block has value which can not be used as a pointer in a tree */ return 1; /* if (is_unfm_pointer) { // unformatted node pointer will be zeroed one_more_corruption (fs, fixable); return 1; } // internal nodes can not have wrong pointer one_more_corruption (fs, fatal); return 1; */ } if (is_block_free (fs, block)) { /* block is marked free - bitmap problems will be handled later */ //one_more_corruption (fs, fixable); } return 0; } static int got_already (reiserfs_filsys_t * fs, unsigned long block) { if (did_we_meet_it (block)) { /* block is in tree at least twice */ return 1; } we_met_it (block); return 0; } /* 1 if it does not look like reasonable stat data */ static int bad_stat_data (reiserfs_filsys_t * fs, struct buffer_head * bh, struct item_head * ih) { unsigned long objectid; // __u32 links; objectid = get_key_objectid (&ih->ih_key); if (!is_objectid_used (fs, objectid)) { /* FIXME: this could be cured right here */ fsck_log ("bad_stat_data: The objectid (%lu) is marked free, but used by an object %k\n", objectid, &ih->ih_key); /* if it is FIX_FIXABLE we flush objectid map at the end no way to call one_less_corruption later */ if (fsck_mode (fs) != FSCK_FIX_FIXABLE) one_more_corruption (fs, FIXABLE); } if (id_map_mark(proper_id_map (fs), objectid)) { fsck_log ("bad_stat_data: The objectid (%lu) is shared by at least two files\n", objectid); if (fsck_mode (fs) == FSCK_FIX_FIXABLE) to_be_relocated (&ih->ih_key); // one_more_corruption (fs, FIXABLE); } return 0; /* Check this on semantic_check pass. sd = (struct stat_data *)B_I_PITEM(bh,ih); get_sd_nlink (ih, sd, &links); if (S_ISDIR(sd->sd_mode)) { if (links < 2) { fsck_log ("%s: block %lu: The directory StatData %k has bad nlink number (%u)\n", __FUNCTION__, bh->b_blocknr, &ih->ih_key, links); one_more_corruption (fs, fatal); } } else { if (links == 0) { fsck_log ("%s: block %lu: The StatData %k has bad nlink number (%u)\n", __FUNCTION__, bh->b_blocknr, &ih->ih_key); one_more_corruption (fs, fatal); } } */ } /* it looks like we can check item length only */ static int bad_direct_item (reiserfs_filsys_t * fs, struct buffer_head * bh, struct item_head * ih) { return 0; } inline void handle_one_pointer (reiserfs_filsys_t * fs, struct buffer_head * bh, __u32 * ptr) { if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { fsck_log (" - zeroed"); *ptr = 0; mark_buffer_dirty (bh); } else { one_more_corruption (fs, FIXABLE); } } /* static int bad_badblocks_item (reiserfs_filsys_t * fs, struct buffer_head * bh, struct item_head * ih) { int i; __u32 * ind = (__u32 *)B_I_PITEM (bh, ih); if (get_ih_item_len (ih) % 4) { fsck_log ("%s: block %lu: item (%H) has bad length\n", __FUNCTION__, bh->b_blocknr, ih); one_more_corruption (fs, fatal); return 1; } for (i = 0; i < I_UNFM_NUM (ih); i ++) { // __u32 unfm_ptr; // unfm_ptr = le32_to_cpu (ind [i]); if (!le32_to_cpu (ind [i])) { fsck_log ("%s: block %lu: badblocks item (%H) has zero pointer."); fsck_log ("Not an error, but could be deleted with --fix-fixable\n", __FUNCTION__, bh->b_blocknr, ih); continue; } // check list of badblocks pointers if (le32_to_cpu (ind [i]) >= get_sb_block_count (fs->fs_ondisk_sb)) { fsck_log ("%s: badblock pointer (block %lu) points out of disk spase (%lu)", __FUNCTION__, bh->b_blocknr, le32_to_cpu (ind [i])); handle_one_pointer (fs, bh, &ind[i]); fsck_log ("\n"); } if (did_we_meet_it (le32_to_cpu (ind [i]))) { // it can be // 1. not_data_block // delete pointer // 2. ind [i] or internal/leaf // advice to run fix-fixable if there is no fatal errors // with list of badblocks, say that it could fix it. if (not_data_block (fs, le32_to_cpu (ind [i]))) { fsck_log ("%s: badblock pointer (block %lu) points on fs metadata (%lu)", __FUNCTION__, bh->b_blocknr, le32_to_cpu (ind [i])); handle_one_pointer (fs, bh, &ind[i]); fsck_log ("\n"); } else { one_more_corruption (fs, badblocks); fsck_log ("%s: badblock item points to a block" " which in the tree already. Use --badblock-file option" " to fix the problem\n", __FUNCTION__); } } else { we_met_it (le32_to_cpu (ind [i])); } } return 0; } */ /* for each unformatted node pointer: make sure it points to data area and that it is not in the tree yet */ static int bad_indirect_item (reiserfs_filsys_t * fs, struct buffer_head * bh, struct item_head * ih) { __u32 * ind = (__u32 *)B_I_PITEM (bh, ih); unsigned int i; if (get_ih_item_len (ih) % 4) { fsck_log ("%s: block %lu: The item (%H) has the bad length (%u)\n", __FUNCTION__, bh->b_blocknr, ih, get_ih_item_len (ih)); one_more_corruption (fs, FATAL); return 1; } for (i = 0; i < I_UNFM_NUM (ih); i ++) { // __u32 unfm_ptr; fsck_check_stat (fs)->unfm_pointers ++; // unfm_ptr = le32_to_cpu (ind [i]); if (!le32_to_cpu (ind [i])) { fsck_check_stat (fs)->zero_unfm_pointers ++; continue; } /* check unformatted node pointer and mark it used in the control bitmap */ if (bad_block_number (fs, le32_to_cpu (ind [i]))) { fsck_log ("%s: block %lu: The item %k has the bad pointer (%d) to the block (%lu)", __FUNCTION__, bh->b_blocknr, &ih->ih_key, i, le32_to_cpu (ind [i])); handle_one_pointer (fs, bh, &ind[i]); fsck_log ("\n"); continue; } if (got_already (fs, le32_to_cpu (ind [i]))) { fsck_log ("%s: block %lu: The item (%H) has the bad pointer (%d) to the block (%lu), " "which is in tree already", __FUNCTION__, bh->b_blocknr, ih, i, le32_to_cpu (ind [i])); handle_one_pointer (fs, bh, &ind [i]); fsck_log ("\n"); continue; } } #if 0 /* delete this check for 3.6 */ if (get_ih_free_space (ih) > fs->fs_blocksize - 1) { if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { /*FIXME: fix it if needed*/ } else { fsck_log ("bad_indirect_item: %H has wrong ih_free_space\n", ih); one_more_corruption (fs, fixable); } } #endif return 0; } /* FIXME: this was is_bad_directory from pass0.c */ static int bad_directory_item (reiserfs_filsys_t * fs, struct buffer_head * bh, struct item_head * ih) { char * name; int namelen; unsigned int count, i; struct reiserfs_de_head * deh = B_I_DEH (bh, ih); int min_entry_size = 1;/* We have no way to understand whether the filesystem was created in 3.6 format or converted to it. So, we assume that minimal name length is 1 */ __u16 state; count = get_ih_entry_count (ih); if (count == 0) { one_more_corruption (fs, FATAL); return 1; } /* make sure item looks like a directory */ if (get_ih_item_len (ih) / (DEH_SIZE + min_entry_size) < count) { /* entry count can not be that big */ fsck_log ("%s: block %lu: The directory item %k has the exsessively big entry count (%u)\n", __FUNCTION__, bh->b_blocknr, &ih->ih_key, count); one_more_corruption (fs, FATAL); return 1; } if (get_deh_location (&deh[count - 1]) != DEH_SIZE * count) { /* last entry should start right after array of dir entry headers */ fsck_log ("%s: block %lu: The directory item %k has the corrupted entry structure\n", __FUNCTION__, bh->b_blocknr, &ih->ih_key); one_more_corruption (fs, FATAL); return 1; } /* check name hashing */ for (i = 0; i < count; i ++, deh ++) { namelen = name_in_entry_length (ih, deh, i); name = name_in_entry (deh, i); if (!is_properly_hashed (fs, name, namelen, get_deh_offset (deh))) { fsck_log ("%s: block %lu: The directory item %k has a not properly hashed entry (%d)\n", __FUNCTION__, bh->b_blocknr, &ih->ih_key, i); one_more_corruption (fs, FATAL); return 1; } } deh = B_I_DEH (bh, ih); state = (1 << DEH_Visible2); /* ok, items looks like a directory */ for (i = 0; i < count; i ++, deh ++) { if (get_deh_state (deh) != state) { fsck_log ("bad_directory_item: block %lu: The directory item %k has the entry (%d) " "\"%.*s\" with a not legal state (%o), (%o) expected", bh->b_blocknr, &ih->ih_key, i, name_in_entry_length (ih, deh, i), name_in_entry (deh, i), get_deh_state (deh), state); if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { set_deh_state (deh, 1 << DEH_Visible2); mark_buffer_dirty (bh); fsck_log (" - corrected\n"); } else one_more_corruption (fs, FIXABLE); fsck_log ("\n"); } } return 0; } static int bad_item (reiserfs_filsys_t * fs, struct buffer_head * bh, int num) { struct item_head * ih; int format; ih = B_N_PITEM_HEAD (bh, num); if ((get_ih_flags(ih)) != 0) { if (fsck_mode(fs) != FSCK_FIX_FIXABLE) { one_more_corruption (fs, FIXABLE); fsck_log ("%s: vpf-10570: block %lu: The item header (%d) has not cleaned flags.\n", __FUNCTION__, bh->b_blocknr, num); } else { fsck_log ("%s: vpf-10580: block %lu: Flags in the item header (%d) were cleaned\n", __FUNCTION__, bh->b_blocknr, num); clean_ih_flags(ih); mark_buffer_dirty(bh); } } if (is_stat_data_ih(ih) && get_ih_item_len(ih) == SD_SIZE) format = KEY_FORMAT_2; else if (is_stat_data_ih(ih) && get_ih_item_len(ih) == SD_V1_SIZE) format = KEY_FORMAT_1; else format = key_format(&ih->ih_key); if (format != get_ih_key_format(ih)) { if (fsck_mode(fs) != FSCK_FIX_FIXABLE) { one_more_corruption (fs, FIXABLE); fsck_log ("%s: vpf-10710: block %lu: The format (%d) specified in the item header (%d) " "differs from the key format (%d).\n", __FUNCTION__, bh->b_blocknr, get_ih_key_format(ih), num, format); } else { fsck_log ("%s: vpf-10720: block %lu: The format (%d) specified in the item header (%d) " "was fixed to the key format (%d).\n", __FUNCTION__, bh->b_blocknr, get_ih_key_format(ih), num, format); set_ih_key_format(ih, format); mark_buffer_dirty(bh); } } if (get_key_dirid (&ih->ih_key) == (__u32)-1) { if (get_key_objectid (&ih->ih_key) != (__u32)-1) { /* safe link can be -1 object_id 0x1 INDIRECT (truncate) or -1 object_id blocksize+1 DIRECT (unlink) */ if (is_direct_ih(ih)) if (get_offset(&ih->ih_key) == fs->fs_blocksize + 1) if (get_ih_item_len (ih) == 4) { /*fsck_log("vpf-00010: safe link found %k\n", &ih->ih_key);*/ fsck_check_stat(fs)->safe ++; return 0; } if (is_indirect_ih(ih)) if(get_offset(&ih->ih_key) == 0x1) if (get_ih_item_len (ih) == 4) { /*fsck_log("vpf-00020: safe link found %k\n", &ih->ih_key);*/ fsck_check_stat(fs)->safe ++; return 0; } /* it does not look like safe link */ /* dir_id == -1 can be used only by safe links */ one_more_corruption (fs, FATAL); fsck_log ("%s: vpf-10290: block %lu, item %d: The item has a wrong key %k\n", __FUNCTION__, num, bh->b_blocknr, &ih->ih_key); return 1; } else { /* BAD BLOCK LIST SUPPORT if (is_indirect_ih (ih)) { // it looks like badblocks item if (fs->fs_badblocks_bm) return 0; else return bad_badblocks_item (fs, bh, ih); } else {*/ one_more_corruption (fs, FATAL); fsck_log ("%s: vpf-10300: block %lu, item %d: The item has a wrong key %k\n", __FUNCTION__, num, bh->b_blocknr, &ih->ih_key); return 1; } } else if (get_key_objectid (&ih->ih_key) == (__u32)-1) { one_more_corruption (fs, FATAL); fsck_log ("%s: vpf-10310: block %lu, item %d: The item has a wrong key %k\n", __FUNCTION__, num, bh->b_blocknr, &ih->ih_key); return 1; } if (is_stat_data_ih (ih)) return bad_stat_data (fs, bh, ih); if (is_direct_ih (ih)) return bad_direct_item (fs, bh, ih); if (is_indirect_ih(ih)) return bad_indirect_item (fs, bh, ih); return bad_directory_item (fs, bh, ih); } /* 1 if i-th and (i-1)-th items can not be neighbors in a leaf */ int bad_pair (reiserfs_filsys_t * fs, struct buffer_head * bh, int pos) { struct item_head * ih; ih = B_N_PITEM_HEAD (bh, pos); if (comp_keys (&((ih - 1)->ih_key), &ih->ih_key) != -1) { if (fsck_mode (fs) != FSCK_REBUILD) one_more_corruption (fs, FATAL); return 1; } if (is_stat_data_ih (ih)) /* left item must be of another object */ if (comp_short_keys (&((ih - 1)->ih_key), &ih->ih_key) != -1) { if (fsck_mode (fs) != FSCK_REBUILD) one_more_corruption (fs, FATAL); return 1; } if (get_key_dirid (&ih->ih_key) == (__u32)-1) { if (get_key_objectid (&ih->ih_key) == (__u32)-1) { /* BAD BLOCK LIST SUPPORT if (is_indirect_ih (ih) && comp_short_keys (&((ih - 1)->ih_key), &ih->ih_key) != 0) return 0; // badblocks item */ /* it does not look like badblocks item */ } else { /* safe link ? */ if (comp_short_keys (&((ih - 1)->ih_key), &ih->ih_key) == 0) { if (is_indirect_ih (ih - 1) && is_direct_ih(ih)) return 0; /* safe link */ /* they do not look like safe links */ } else { if (is_indirect_ih (ih) || is_direct_ih(ih)) return 0; /* safe link */ /* it does not look like safe link */ } } } if (is_direct_ih(ih)) { /* left item must be indirect or stat data item of the same file */ if (not_of_one_file (&((ih - 1)->ih_key), &ih->ih_key)) { if (fsck_mode (fs) != FSCK_REBUILD) one_more_corruption (fs, FATAL); return 1; } if (!((is_stat_data_ih (ih - 1) && get_offset (&ih->ih_key) == 1) || (is_indirect_ih (ih - 1) && get_offset (&(ih - 1)->ih_key) + get_bytes_number (ih-1, bh->b_size) == get_offset (&ih->ih_key)))) { if (fsck_mode (fs) != FSCK_REBUILD) one_more_corruption (fs, FATAL); return 1; } } if (is_indirect_ih (ih) || is_direntry_ih (ih)) { /* left item must be stat data of the same object */ if (not_of_one_file (&((ih - 1)->ih_key), &ih->ih_key) || !is_stat_data_ih (ih - 1)) { if (fsck_mode (fs) != FSCK_REBUILD) one_more_corruption (fs, FATAL); return 1; } } return 0; } /* 1 if block head or any of items is bad */ static int bad_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh) { int i; if (leaf_structure_check(fs, bh)) return 1; for (i = 0; i < B_NR_ITEMS (bh); i ++) { if (bad_item (fs, bh, i)) { fsck_log ("bad_leaf: block %lu, item %d: The corrupted item found (%H)\n", bh->b_blocknr, i, B_N_PITEM_HEAD (bh, i)); } if (i && bad_pair (fs, bh, i)) { fsck_log ("bad_leaf: block %lu, items %d and %d: The wrong order of items: %k, %k\n", bh->b_blocknr, i-1, i, &B_N_PITEM_HEAD (bh, i-1)->ih_key, &B_N_PITEM_HEAD (bh, i)->ih_key); } } return 0; } /* 1 if bh does not look like internal node */ static int bad_internal (reiserfs_filsys_t * fs, struct buffer_head * bh) { int i; for (i = 0; i <= B_NR_ITEMS (bh); i ++) { if (i != B_NR_ITEMS (bh) && i != B_NR_ITEMS (bh) - 1) /* make sure that keys are in increasing order */ if (comp_keys (B_N_PDELIM_KEY (bh, i), B_N_PDELIM_KEY (bh, i + 1)) != -1) { fsck_log ("%s: vpf-10320: block %lu, items %d and %d: The wrong order " "of items: %k, %k\n", __FUNCTION__, bh->b_blocknr, i, i+1, B_N_PDELIM_KEY (bh, i), B_N_PDELIM_KEY (bh, i + 1)); one_more_corruption (fs, FATAL); return 1; } /* make sure that the child is correct */ if (bad_block_number (fs, get_dc_child_blocknr (B_N_CHILD (bh,i)))) { fsck_log ("%s: vpf-10330: block %lu, item %d: The internal item points to the " "not legal block (%lu)\n", __FUNCTION__, bh->b_blocknr, i, get_dc_child_blocknr (B_N_CHILD (bh,i))); one_more_corruption (fs, FATAL); return 1; } } return 0; } /* h == 0 for root level. block head's level == 1 for leaf level */ static inline int h_to_level (reiserfs_filsys_t * fs, int h) { return get_sb_tree_height (fs->fs_ondisk_sb) - h - 1; } /* bh must be formatted node. blk_level must be tree_height - h + 1 */ static int bad_node (reiserfs_filsys_t * fs, struct buffer_head ** path, int h) { struct buffer_head ** pbh = &path[h]; if (B_LEVEL (*pbh) != h_to_level (fs, h)) { fsck_log ("block %lu: The level of the node (%d) is not correct, (%d) expected\n", (*pbh)->b_blocknr, B_LEVEL (*pbh), h_to_level (fs, h)); one_more_corruption (fs, FATAL); return 1; } if (bad_block_number (fs, (*pbh)->b_blocknr)) { one_more_corruption (fs, FATAL); fsck_log ("%s: vpf-10340: The node in the wrong block number (%lu) found in the tree\n", __FUNCTION__, (*pbh)->b_blocknr); return 1; } if (got_already (fs, (*pbh)->b_blocknr)) { fsck_log ("%s: vpf-10350: The block (%lu) is used more than once in the tree.\n", __FUNCTION__, (*pbh)->b_blocknr); one_more_corruption (fs, FATAL); return 1; } if (is_leaf_node (*pbh)) { fsck_check_stat (fs)->leaves ++; return bad_leaf (fs, *pbh); } fsck_check_stat (fs)->internals ++; return bad_internal (fs, *pbh); } /* internal node bh must point to block */ static int get_pos (struct buffer_head * bh, unsigned long block) { int i; for (i = 0; i <= B_NR_ITEMS (bh); i ++) { if (get_dc_child_blocknr (B_N_CHILD (bh, i)) == block) return i; } die ("An internal pointer to the block (%lu) cannot be found in the node (%lu)", block, bh->b_blocknr); return 0; } /* path[h] - leaf node */ static struct key * lkey (struct buffer_head ** path, int h) { int pos; while (h > 0) { pos = get_pos (path[h - 1], path[h]->b_blocknr); if (pos) return B_N_PDELIM_KEY(path[h - 1], pos - 1); h --; } return 0; } /* path[h] - leaf node */ static struct key * rkey (struct buffer_head ** path, int h) { int pos; while (h > 0) { pos = get_pos (path[h - 1], path[h]->b_blocknr); if (pos != B_NR_ITEMS (path[h - 1])) return B_N_PDELIM_KEY (path[h - 1], pos); h --; } return 0; } /* are all delimiting keys correct */ static int bad_path (reiserfs_filsys_t * fs, struct buffer_head ** path, int h1) { int h = 0; struct key * dk; int pos = 0; while (path[h]) h ++; h--; // path[h] is leaf if (h != h1) die ("bad_path: The leaf is expected as the last element in the path"); if (h) pos = get_pos (path[h - 1], path[h]->b_blocknr); dk = lkey (path, h); if (dk && comp_keys (dk, B_N_PKEY (path[h], 0))) { /* left delimiting key must be equal to the key of 0-th item in the node */ fsck_log ("bad_path: The left delimiting key %k of the node (%lu) must " "be equal to the first element's key %k within the node.\n", dk, path[h]->b_blocknr, B_N_PKEY (path[h], 0)); one_more_corruption (fs, FATAL); return 1; } dk = rkey (path, h); if (dk && comp_keys (dk, B_N_PKEY (path[h], get_blkh_nr_items (B_BLK_HEAD (path[h])) - 1)) != 1) { /* right delimiting key must be greater than the key of the last item in the node */ fsck_log ("bad_path: The right delimiting key %k of the node (%lu) must " "be greater than the last (%d) element's key %k within the node.\n", dk, path[h]->b_blocknr, get_blkh_nr_items (B_BLK_HEAD (path[h])) - 1, B_N_PKEY (path[h], get_blkh_nr_items (B_BLK_HEAD (path[h])) - 1)); one_more_corruption (fs, FATAL); return 1; } if (h && (get_dc_child_size (B_N_CHILD(path[h-1],pos)) + get_blkh_free_space ((struct block_head *)path[h]->b_data) + BLKH_SIZE != path[h]->b_size)) { /* wrong dc_size */ fsck_log ("bad_path: block %lu, pointer %d: The used space (%d) of the " "child block (%lu)", path[h-1]->b_blocknr, pos, get_dc_child_size(B_N_CHILD(path[h-1],pos)), path[h]->b_blocknr); fsck_log (" is not equal to the (blocksize (4096) - free space (%d) - " "header size (%u))", get_blkh_free_space((struct block_head *)path[h]->b_data), BLKH_SIZE); if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { set_dc_child_size (B_N_CHILD(path[h-1],pos), path[h]->b_size - get_blkh_free_space ((struct block_head *)path[h]->b_data) - BLKH_SIZE); fsck_log (" - corrected to (%lu)\n", get_dc_child_size (B_N_CHILD(path[h-1],pos))); mark_buffer_dirty (path[h-1]); } else { one_more_corruption (fs, FIXABLE); fsck_log ("\n"); return 1; } } return 0; } static void before_check_fs_tree (reiserfs_filsys_t * fs) { init_control_bitmap (fs); source_bitmap = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_copy (source_bitmap, fs->fs_bitmap2); proper_id_map (fs) = id_map_init(); } static void after_check_fs_tree (reiserfs_filsys_t * fs) { if (fsck_mode(fs) == FSCK_FIX_FIXABLE) { reiserfs_flush_to_ondisk_bitmap (fs->fs_bitmap2, fs); reiserfs_flush (fs); fs->fs_dirt = 1; reiserfs_bitmap_delta (source_bitmap, control_bitmap); fsck_deallocate_bitmap(fs) = source_bitmap; } else reiserfs_delete_bitmap (source_bitmap); reiserfs_delete_bitmap (control_bitmap); flush_buffers (fs->fs_dev); } /* pass internal tree of filesystem */ void check_fs_tree (reiserfs_filsys_t * fs) { before_check_fs_tree (fs); fsck_progress ("Checking internal tree.."); pass_through_tree (fs, bad_node, bad_path, fsck_mode(fs) == FSCK_AUTO ? 2 : -1); /* internal tree is correct (including all objects have correct sequences of items) */ fsck_progress ("finished\n"); /* compare created bitmap with the original */ if (fsck_mode(fs) == FSCK_AUTO) { if (auto_handle_bitmaps(fs)) { fprintf(stderr, "The on-disk bitmap looks corrupted."); one_more_corruption(fs, FIXABLE); } id_map_free(proper_id_map(fs)); } else handle_bitmaps (fs); after_check_fs_tree (fs); } static int clean_attributes_handler (reiserfs_filsys_t * fs, struct buffer_head ** path, int h) { struct buffer_head * bh = path[h]; int i; if (B_LEVEL (bh) != h_to_level (fs, h)) { reiserfs_panic ("The node (%lu) with wrong level (%d) found in the tree, (%d) expected\n", bh->b_blocknr, B_LEVEL (bh), h_to_level (fs, h)); } if (!is_leaf_node (bh)) return 0; for (i = 0; i < B_NR_ITEMS (bh); i ++) { if (is_stat_data_ih (B_N_PITEM_HEAD (bh, i)) && get_ih_item_len (B_N_PITEM_HEAD (bh, i)) == SD_SIZE) { set_sd_v2_sd_attrs((struct stat_data *)B_N_PITEM(bh, i), 0); mark_buffer_dirty (bh); } } return 0; } void do_clean_attributes (reiserfs_filsys_t * fs) { pass_through_tree (fs, clean_attributes_handler, NULL, -1); set_sb_v2_flag (fs->fs_ondisk_sb, reiserfs_attrs_cleared); mark_buffer_dirty (fs->fs_super_bh); } reiserfsprogs-3.6.9/fsck/ubitmap.c0000664000077100007710000001010107665645672012670 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" /* g_disk_bitmap initially contains copy of disk bitmaps (cautious version of it); g_new_bitmap initially has marked only super block, bitmap blocks and bits after the end of bitmap in pass 1 we go through g_disk_bitmap. If block does not look like formatted node, we skip it. If block contains internal node, put 0 in g_disk_bitmap if block is not used in new tree yet. If block contains leaf and is used already (by an indirect item handled already to this time) save all items. They will be inserted into tree after pass 1. If block looking like leaf is not used in the new tree, try to insert in into tree. If it is not possible, mark block in g_uninsertable_leaf_bitmap. Blocks marked in this bitmap will be inserted into tree in pass 2. They can not be This means, that in pass 1 when we have found block containing the internal nodes we mark it in g_disk_bitmap as free (reiserfs_free_internal_block). When block gets into new tree it is marked in g_new_bitmap (mark_block_used) When collecting resources for do_balance, we mark new blocks with mark_block_used. After do_balance we unmark unused new blocks in g_new_bitmap (bitmap.c:/reiserfs_free_block) Allocating of new blocks: look for 0 bit in g_disk_bitmap (find_zero_bit_in_bitmap), make sure, that g_new_bitmap contains 0 at the corresponding bit (is_block_used). */ /* is blocks used (marked by 1 in new bitmap) in the tree which is being built (as leaf, internal, bitmap, or unformatted node) */ int is_block_used (unsigned long block) { return reiserfs_bitmap_test_bit (fsck_new_bitmap (fs), block); } void mark_block_used (unsigned long block, int check_hardware) { if (!block) return; if (is_block_used (block)) { if (check_hardware) check_memory_msg(); die ("mark_block_used: (%lu) used already", block); } reiserfs_bitmap_set_bit (fsck_new_bitmap (fs), block); } void mark_block_free (unsigned long block) { if (!is_block_used (block)) die ("mark_block_free: (%lu) is free already", block); reiserfs_bitmap_clear_bit (fsck_new_bitmap (fs), block); } int is_block_uninsertable (unsigned long block) { return !reiserfs_bitmap_test_bit (fsck_uninsertables (fs), block); } /* uninsertable block is marked by bit clearing */ void mark_block_uninsertable (unsigned long block) { if (is_block_uninsertable (block)) die ("mark_block_uninsertable: (%lu) is uninsertable already", block); reiserfs_bitmap_clear_bit (fsck_uninsertables (fs), block); /* we do not need thsi actually */ pass_1_stat (fs)->uninsertable_leaves ++; } /* FIXME: should be able to work around no disk space */ int reiserfsck_reiserfs_new_blocknrs (reiserfs_filsys_t * fs, unsigned long * free_blocknrs, unsigned long start, int amount_needed) { int i; if (!are_there_allocable_blocks (amount_needed)) die ("out of disk space"); for (i = 0; i < amount_needed; i ++) { free_blocknrs[i] = alloc_block (); if (!free_blocknrs[i]) die ("reiserfs_new_blocknrs: 0 is allocated"); mark_block_used (free_blocknrs[i], 0); } return CARRY_ON; } // FIXME: do you check readability of a block? If f_read fails - you // free block in bitmap or if you mark bad blocks used to avoid their // allocation in future you should have bad block counter in a super // block. Another minor issue: users of _get_new_buffer expect buffer // to be filled with 0s struct buffer_head * reiserfsck_get_new_buffer (unsigned long start) { unsigned long blocknr = 0; struct buffer_head * bh = NULL; reiserfs_new_blocknrs (fs, &blocknr, start, 1); bh = getblk (fs->fs_dev, blocknr, fs->fs_blocksize); return bh; } /* free block in new bitmap */ int reiserfsck_reiserfs_free_block (reiserfs_filsys_t * fs, unsigned long block) { mark_block_free (block); /* put it back to pool of blocks for allocation */ make_allocable (block); return 0; } reiserfsprogs-3.6.9/fsck/reiserfsck.80000664000077100007710000001575207705261642013317 .\" -*- nroff -*- .\" Copyright 1996-2003 Hans Reiser. .\" .TH REISERFSCK 8 "April 2003" "Reiserfsprogs-3.6.9" .SH NAME reiserfsck \- check a Linux Reiserfs file system .SH SYNOPSIS .B reiserfsck [ \fB-afprVy\fR ] [ \fB--rebuild-sb\fR | \fB--check\fR | \fB--fix-fixable\fR | \fB--rebuild-tree\fR | \fB--clean-attributes\fR ] .\" [ \fB-i\fR | \fB--interactive\fR ] [ \fB-j\fR | \fB--journal\fR \fIdevice\fR ] [ \fB-z\fR | \fB--adjust-size\fR ] [ \fB-n\fR | \fB--nolog\fR ] [ \fB-l\fR | \fB--logfile \fIfile\fR ] [ \fB-q\fR | \fB--quiet\fR ] [ \fB-y\fR | \fB--yes\fR ] .\" [ \fB-b\fR | \fB--scan-marked-in-bitmap \fIbitmap-filename\fR ] .\" [ \fB-h\fR | \fB--hash \fIhash-name\fR ] .\" [ \fB-g\fR | \fB--background\fR ] [ \fB-S\fR | \fB--scan-whole-partition\fR ] [ \fB--no-journal-available\fR ] .I device .SH DESCRIPTION \fBReiserfsck\fR searches for a Reiserfs filesystem on a device, replays any necessary transactions, and either checks or repairs the file system. .TP .I device is the special file corresponding to the device or partition (e.g /dev/hdXX for IDE disk partition or /dev/sdXX for SCSI disk partition). .SH OPTIONS .TP .B --rebuild-sb This option recovers the superblock on a Reiserfs partition. Normally you only need this option if mount reports "read_super_block: can't find a reiserfs file system" and you are sure that a Reiserfs file system is there. .TP .B --check This default action checks file system consistency and reports but does not repair any corruption that it finds. This option may be used on a read-only file system mount. .TP .B --fix-fixable This option recovers certain kinds of corruption that do not require rebuilding the entire file system tree (\fB--rebuild-tree\fR). Normally you only need this option if the \fB--check\fR option reports "corruption that can be fixed with \fB--fix-fixable\fR". This includes: zeroing invalid data-block pointers, correcting st_size and st_blocks for directories, and deleting invalid directory entries. .TP .B --rebuild-tree This option rebuilds the entire file system tree using leaf nodes found on the device. Normally you only need this option if the \fB--check\fR option reports "corruption that can be fixed only during \fB--rebuild-tree\fR". You are strongly encouraged to make a backup copy of the whole partition before attempting the \fB--rebuild-tree\fR option. .TP .B --clean-attributes This option cleans reserved fields of Stat-Data items. .TP .B \fB--journal \fIdevice \fR, \fB-j \fIdevice \fR This option supplies the device name of the current file system journal. This option is required when the journal resides on a separate device from the main data device (although it can be avoided with the expert option \fB--no-journal-available\fR). .TP .\" .B --interactive, -i .\" This makes \fBreiserfsck\fR to stop after each pass completed. .\" .TP .B --adjust-size, -z This option causes \fBreiserfsck\fR to correct file sizes that are larger than the offset of the last discovered byte. This implies that holes at the end of a file will be removed. File sizes that are smaller than the offset of the last discovered byte are corrected by --fix-fixable. .TP \fB--logfile \fIfile\fR, \fB-l \fI file\fR This option causes \fBreiserfsck\fR to report any corruption it finds to the specified log file rather than stderr. .TP .B --nolog, -n This option prevents \fBreiserfsck\fR from reporting any kinds of corruption. .TP .B --quiet, -q This option prevents \fBreiserfsck\fR from reporting its rate of progress. .TP .B --yes, -y This option inhibits \fBreiserfsck\fR from asking you for confirmation after telling you what it is going to do, assuming yes. For safety, it does not work with the --rebuild-tree option. .TP \fB-a\fR, \fB-p\fR These options are usually passed by fsck -A during the automatic checking of those partitions listed in /etc/fstab. These options cause \fBreiserfsck\fR to print some information about the specified file system, check if error flags in the superblock are set and do some light-weight checks. If these checks reveal a corruption or the flag indicating a (possibly fixable) corruption is found set in the superblock, then \fBreiserfsck\fR switches to the fix-fixable mode. If the flag indicating a fatal corruption is found set in the superblock, then \fBreiserfsck\fR finishes with an error. .TP .B -V This option prints the reiserfsprogs version and exit. .TP \fB-r\fR, \fB-f\fR These options are ignored. .SH EXPERT OPTIONS DO NOT USE THESE OPTIONS UNLESS YOU KNOW WHAT YOU ARE DOING. WE ARE NOT RESPONSIBLE IF YOU LOSE DATA AS A RESULT OF THESE OPTIONS. .TP .B \fB\--no-journal-available\fR This option allows \fBreiserfsck\fR to proceed when the journal device is not available. This option has no effect when the journal is located on the main data device. NOTE: after this operation you must use \fBreiserfstune\fR to specify a new journal device. .TP .B --scan-whole-partition, -S This option causes \fB--rebuild-tree\fR to scan the whole partition, not only used space on the partition. .SH EXAMPLE OF USING 1. You think something may be wrong with a reiserfs partition on /dev/hda1 or you would just like to perform a periodic disk check. 2. Run \fBreiserfsck --check --logfile check.log /dev/hda1\fR. If \fBreiserfsck --check\fR exits with status 0 it means no errors were discovered. 3. If \fBreiserfsck --check\fR exits with status 1 (and reports about fixable corruptions) it means that you should run \fBreiserfsck --fix-fixable --logfile fixable.log /dev/hda1\fR. 4. If \fBreiserfsck --check\fR exits with status 2 (and reports about fatal corruptions) it means that you need to run \fBreiserfsck --rebuild-tree\fR. If \fBreiserfsck --check\fR fails in some way you should also run \fBreiserfsck --rebuild-tree\fR, but we also encourage you to submit this as a bug report. 5. Before running \fBreiserfsck --rebuild-tree\fR, please make a backup of the whole partition before proceeding. Then run \fBreiserfsck --rebuild-tree --logfile rebuild.log /dev/hda1\fR. 6. If the \fB--rebuild-tree\fR step fails or does not recover what you expected, please submit this as a bug report. Try to provide as much information as possible and we will try to help solve the problem. .SH EXIT CODES \fBreiserfsck\fR uses the following exit codes: .br \ \fI0\fR \-\ No errors. .br \ \fI1\fR \-\ File system errors corrected. .br \ \fI4\fR \-\ File system fatal errors left uncorrected, .br \ \fBreiserfsck --rebuild-tree\fR needs to be launched. .br \ \fI6\fR \-\ File system fixable errors left uncorrected, .br \ \fBreiserfsck --fix-fixable\fR needs to be launched. .br \ \fI8\fR \-\ Operational error. .br \ \fI16\fR \-\ Usage or syntax error. .br .SH AUTHOR This version of \fBreiserfsck\fR has been written by Vitaly Fertman . .SH BUGS There are likely to be some bugs. Please report bugs to the ReiserFS mail-list . .SH TODO Faster recovering, signal handling, i/o error handling, etc. .SH SEE ALSO .BR mkreiserfs (8), .BR reiserfstune (8) .BR resize_reiserfs (8), .BR debugreiserfs (8), reiserfsprogs-3.6.9/fsck/super.c0000664000077100007710000007535307676637011012377 /* * Copyright 2001-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" #include #include #define fsck_conditional_log(sb_found, fmt, list...) { \ if (sb_found) \ fsck_log(fmt, ## list); \ } int what_fs_version () { size_t n = 0; char * answer = 0; int version; printf("\nwhat the version of ReiserFS do you use[1-4]\n" "\t(1) 3.6.x\n" "\t(2) >=3.5.9 (introduced in the middle of 1999) (if you use linux 2.2, choose this one)\n" "\t(3) < 3.5.9 converted to new format (don't choose if unsure)\n" "\t(4) < 3.5.9 (this is very old format, don't choose if unsure)\n" "\t(X) exit\n"); getline (&answer, &n, stdin); version = atoi (answer); if (version < 1 || version > 4) die ("rebuild_sb: wrong version"); return version; } /* #define super_error(exit_code, text) { \ fsck_log(text); \ return exit_code; \ } int check_sb (reiserfs_filsys_t * fs) { int magic = 0, version = 0; if (!is_blocksize_correct (fs->fs_blocksize)) super_error(-1, "Wrong blocksize found in the super block\n"); if (is_reiserfs_3_6_magic_string (sb)) magic = 2; else if (is_reiserfs_3_5_magic_string (sb)) magic = 1; else if (is_reiserfs_jr_magic_string (sb)) magic = 3; else super_error(-1, "Invalid magic found in the super block.\n"); if (magic == 1 || magic == 2) { if (fsck_data (fs)->journal_dev_name) fsck_log("Reiserfs with standard journal found, but there was specified a " "journal dev\n"); standard_journal = 1; } else { if (!fsck_data (fs)->journal_dev_name) super_error(-1, "Reiserfs with non standard journal found, but there was not " "specified any journal dev\n"); standard_journal = 0; } if (get_sb_version (sb) != REISERFS_FORMAT_3_6 && get_sb_version (sb) != REISERFS_FORMAT_3_5) super_error(-1, "Invalid format found in the super block.\n"); if (is_new_sb_location(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) { if (magic == 3) version = get_sb_version (sb) == REISERFS_FORMAT_3_6 ? 1 : 2; else version = magic == 2 ? 1 : 2; } else if (is_old_sb_location(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) { if (magic == 3) version = get_sb_version (sb) == REISERFS_FORMAT_3_6 ? 3 : 4; else version = magic == 2 ? 3 : 4; } else die("Super block in the wong block(%d).\n", fs->fs_super_bh->b_blocknr); if (version == 0) die ("FS format must be figured out here.\n"); if (get_sb_block_count (sb) > count_blocks (filename, fs->fs_blocksize)) super_error(-1, "Invalid block count found in the super block.\n"); if (get_sb_block_size (sb) != fs->fs_blocksize) super_error(-1, "Invalid block size found in the super block (%lu).\n", get_sb_block_size (sb)); //Non needed from here p_oid_maxsize = (fs->fs_blocksize - reiserfs_super_block_size (sb)) / sizeof(__u32) / 2 * 2; if (get_sb_oid_maxsize (sb) != p_oid_maxsize) super_error(-1, "Invalid objectid map max size found in the super block (%lu).\n", get_sb_oid_maxsize (sb)); if (get_sb_oid_cursize (sb) == 1 || get_sb_oid_cursize (sb) > get_sb_oid_maxsize (sb)) super_error(-1, "Invalid objectid map found in the super block (%lu).\n", get_sb_oid_cursize (sb)); if (get_sb_root_block (sb) > block_count && get_sb_root_block (sb) != ~0) fsck_log("Invalid root block found in the super block (%lu).\n", get_sb_root_block (sb)); if (get_sb_free_blocks (sb) > block_count) fsck_log ("Invalid free block count found in the super block (%lu).\n", get_sb_free_blocks (sb)); if (get_sb_tree_height (sb) && ((get_sb_tree_height (sb) < DISK_LEAF_NODE_LEVEL + 1) || (get_sb_tree_height (sb) > MAX_HEIGHT) && (get_sb_tree_height (sb) != ~0))) super_error(-1, "Invalid tree height found in the super block (%lu).\n", get_sb_tree_height (sb)); if (get_sb_hash_code (sb) && code2name (get_sb_hash_code (sb)) == 0) super_error(-1, "Invalid hash found in the super block (%lu).\n", get_sb_hash_code (sb)); if (version == 1 || version == 3) { if (!uuid_is_correct(sb->s_uuid)) fsck_log ("Invalid uuid found, you should generate a new one.\n"); if (sb->s_flags & 0xfffffffe) fsck_log ("rebuild-sb: super block flags found (%u), zeroed\n", sb->s_flags); } //Not needed till here. p_bmap_nr = (block_count + (fs->fs_blocksize * 8 - 1)) / (fs->fs_blocksize * 8); if (get_sb_bmap_nr (sb) != p_bmap_nr) super_error(-1, "Invalid bitmap number found in the super block (%lu).\n", get_sb_bmap_nr (sb)); if (!fsck_skip_journal (fs) && standard_journal == 1) { if (get_jp_journal_dev (sb_jp(sb)) != 0) super_error(-1, "Invalid journal device found (%lu).\n", get_jp_journal_dev (sb_jp(sb))); if (get_jp_journal_1st_block (sb_jp(sb)) != get_journal_start_must (fs)) super_error(-1, "Invalid journal first block found (%lu).\n", get_jp_journal_1st_block (sb_jp(sb))); if (get_jp_journal_size (sb_jp(sb)) != journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) super_error(-1, "Invalid journal size found (%lu).\n", get_jp_journal_size (sb_jp(sb)) + 1); if (get_jp_journal_max_batch (sb_jp(sb)) != advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb)))) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal max batch size occured (%lu), fixed (%d)\n", get_jp_journal_max_batch (sb_jp(sb)), advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb)))); set_jp_journal_max_batch (sb_jp(sb), advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb)))); } if (get_jp_journal_max_commit_age (sb_jp(sb)) != advise_journal_max_commit_age()) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal max commit age occured (%lu), fixed (%d)\n", get_jp_journal_max_commit_age (sb_jp(sb)), advise_journal_max_commit_age()); set_jp_journal_max_commit_age (sb_jp(sb), advise_journal_max_commit_age()); } if (get_jp_journal_max_trans_age (sb_jp(sb)) != advise_journal_max_trans_age()) { fsck_log ("rebuild-sb: wrong journal max commit age occured (%lu), fixed (0)\n", get_jp_journal_max_trans_age (sb_jp(sb)), advise_journal_max_trans_age()); set_jp_journal_max_trans_age (sb_jp(sb), advise_journal_max_trans_age()); } } */ void rebuild_sb (reiserfs_filsys_t * fs, char * filename, struct fsck_data * data) { int version = 0; struct reiserfs_super_block * ondisk_sb = 0; struct reiserfs_super_block * sb = 0; struct reiserfs_journal_header *j_head; int magic_was_found = 0; unsigned long block_count = 0; __u16 p_oid_maxsize; __u16 p_bmap_nr; __u32 p_jp_journal_1st_block = 0; __u32 p_jp_dev_size = 0; int standard_journal = -1; char * journal_dev_name = 0; char * tmp; int sb_size; char * answer = 0; size_t n = 0; struct stat64 stat_buf; int retval, exit_code = EXIT_OK; if (!no_reiserfs_found (fs)) { sb = getmem (sizeof (*sb)); if (!is_opened_rw (fs)) { close (fs->fs_dev); fs->fs_dev = open (fs->fs_file_name, O_RDWR | O_LARGEFILE); } if (!is_blocksize_correct (fs->fs_blocksize)) { printf("\nCannot find a proper blocksize, enter block size [4096]: \n"); getline (&answer, &n, stdin); if (strcmp(answer, "\n")) { retval = (int) strtol (answer, &tmp, 0); if ((*tmp && strcmp(tmp, "\n")) || retval < 0) reiserfs_exit (EXIT_USER, "rebuild_sb: wrong block size specified\n"); if (!is_blocksize_correct (retval)) reiserfs_exit (EXIT_USER, "rebuild_sb: wrong block size specified, " "only power of 2 from 512-8192 interval are supported.\n"); } else retval = 4096; fs->fs_blocksize = retval; } block_count = count_blocks (filename, fs->fs_blocksize); /* save ondisk_sb somewhere and work in temp area */ ondisk_sb = fs->fs_ondisk_sb; memcpy (sb, fs->fs_ondisk_sb, sizeof (*sb)); fs->fs_ondisk_sb = sb; if (is_reiserfs_3_6_magic_string (sb)) { /* 3_6 magic */ if (fsck_data (fs)->journal_dev_name) /* journal dev must not be specified with standard journal */ reiserfs_exit (EXIT_USER, "ReiserFS with default journal " "is found, but there was specified a journal device."); if (fs->fs_super_bh->b_blocknr == REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 1; else if (fs->fs_super_bh->b_blocknr == REISERFS_OLD_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 3; magic_was_found = 2; } else if (is_reiserfs_3_5_magic_string (sb)) { if (fsck_data (fs)->journal_dev_name) /* journal dev must not be specified with standard journal */ reiserfs_exit (EXIT_USER, "ReiserFS with default journal " "is found, but there was specified a journal device."); /* 3_5 magic */ if (fs->fs_super_bh->b_blocknr == REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 2; else if (fs->fs_super_bh->b_blocknr == REISERFS_OLD_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 4; magic_was_found = 1; } else if (is_reiserfs_jr_magic_string (sb)) { if (!fsck_data (fs)->journal_dev_name && !fsck_skip_journal(fs)) /* journal dev must be specified with non standard journal */ reiserfs_exit (EXIT_USER, "ReiserFS with non default journal " "is found, but there was not specified any journal device."); if (get_sb_version (sb) == REISERFS_FORMAT_3_6) { /*non-standard magic + sb_format == 3_6*/ if (fs->fs_super_bh->b_blocknr == REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 1; else if (fs->fs_super_bh->b_blocknr == REISERFS_OLD_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 3; magic_was_found = 3; } else if (get_sb_version (sb) == REISERFS_FORMAT_3_5) { /* non-standard magic + sb_format == 3_5 */ if (fs->fs_super_bh->b_blocknr == REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 2; else if (fs->fs_super_bh->b_blocknr == REISERFS_OLD_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 4; magic_was_found = 3; } else { /* non-standard magic + bad sb_format */ version = 0; magic_was_found = 3; } } else reiserfs_exit (EXIT_USER, "We opened device but there is no magic " "and there is no correct superblock format found."); if (magic_was_found == 1 || magic_was_found == 2) standard_journal = 1; else standard_journal = 0; if (version == 0) version = what_fs_version (); if (get_sb_block_count (sb) != block_count) { do { printf("\nDid you use resizer(y/n)[n]: "); getline (&answer, &n, stdin); } while(strcmp ("y\n", answer) && strcmp ("n\n", answer) && strcmp ("\n", answer)); if (!strcmp ("y\n", answer)) { printf("\nEnter partition size [%lu]: ", block_count); getline (&answer, &n, stdin); if (strcmp ("\n", answer)) block_count = atoi (answer); set_sb_block_count (sb, block_count); } else { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong block count " "occured (%lu), fixed (%lu)\n", get_sb_block_count(sb), block_count); set_sb_block_count (sb, block_count); } } if (get_sb_block_size (sb) != fs->fs_blocksize) { fsck_log("rebuild-sb: wrong block size occured (%lu), fixed (%lu)\n", get_sb_block_size (sb), fs->fs_blocksize); set_sb_block_size (sb, fs->fs_blocksize); } } /* if no reiserfs_found or bad data found in that SB, what was checked in previous * clause */ if (no_reiserfs_found (fs)) { int fd; fd = open (filename, O_RDWR | O_LARGEFILE); if (fd == -1) { reiserfs_exit (EXIT_OPER, "rebuils_sb: cannot open device %s", filename); } version = what_fs_version (); if (version == 3 || version == 4) { retval = 4096; } else { printf("\nEnter block size [4096]: \n"); getline (&answer, &n, stdin); if (strcmp(answer, "\n")) { retval = (int) strtol (answer, &tmp, 0); if ((*tmp && strcmp(tmp, "\n")) || retval < 0) reiserfs_exit (EXIT_USER, "rebuild_sb: wrong block size specified\n"); if (!is_blocksize_correct (retval)) reiserfs_exit (EXIT_USER, "rebuild_sb: wrong block size specified, " "only divisible by 1024 are supported currently\n"); } else retval = 4096; } block_count = count_blocks (filename, retval); switch(version){ case 1: fs = reiserfs_create (filename, REISERFS_FORMAT_3_6, block_count, retval, 1, 1); break; case 2: fs = reiserfs_create (filename, REISERFS_FORMAT_3_5, block_count, retval, 1, 1); break; case 3: fs = reiserfs_create (filename, REISERFS_FORMAT_3_6, block_count, retval, 1, 0); break; case 4: fs = reiserfs_create (filename, REISERFS_FORMAT_3_5, block_count, retval, 1, 0); break; } if (fs == NULL) return; sb = fs->fs_ondisk_sb; fs->fs_vp = data; if (!fsck_skip_journal (fs)) { if (!fsck_data (fs)->journal_dev_name) { do { printf("\nNo journal device was specified. (If journal is not " "available, re-run with --no-journal-available option specified).\n" "Is journal default? (y/n)[y]: "); getline (&answer, &n, stdin); } while(strcmp ("y\n", answer) && strcmp ("n\n", answer) && strcmp ("\n", answer)); if (!strcmp ("n\n", answer)) { printf("\nSpecify journal device with -j option.\n"); exit(EXIT_USER); } standard_journal = 1; } else { standard_journal = 0; memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_JR_SUPER_MAGIC_STRING, strlen (REISERFS_JR_SUPER_MAGIC_STRING)); } } do { printf("\nDid you use resizer(y/n)[n]: "); getline (&answer, &n, stdin); } while (strcmp ("y\n", answer) && strcmp ("n\n", answer) && strcmp ("\n", answer)); if (!strcmp ("y\n", answer)) { printf("\nEnter partition size [%lu]: ", block_count); getline (&answer, &n, stdin); if (strcmp ("\n", answer)) block_count = atoi (answer); set_sb_block_count (sb, block_count); } set_sb_fs_state (sb, FS_ERROR); } if (version == 1 || version == 3) { if (get_reiserfs_format (sb) != REISERFS_FORMAT_3_6) { fsck_log("rebuild-sb: wrong reiserfs version occured (%lu), fixed (%lu)\n", get_reiserfs_format (sb), REISERFS_FORMAT_3_6); set_sb_version (sb, REISERFS_FORMAT_3_6); } } else if (version == 2 || version == 4) { if (get_reiserfs_format (sb) != REISERFS_FORMAT_3_5) { fsck_log("rebuild-sb: wrong reiserfs version occured (%lu), fixed (%lu)\n", get_reiserfs_format (sb), REISERFS_FORMAT_3_5); set_sb_version (sb, REISERFS_FORMAT_3_5); } } p_oid_maxsize = (fs->fs_blocksize - reiserfs_super_block_size (sb)) / sizeof(__u32) / 2 * 2; if (get_sb_oid_maxsize (sb) != p_oid_maxsize) { fsck_log("rebuild-sb: wrong objectid map max size occured (%lu), fixed (%lu)\n", get_sb_oid_maxsize (sb), p_oid_maxsize); set_sb_oid_maxsize (sb, p_oid_maxsize); } p_bmap_nr = (block_count + (fs->fs_blocksize * 8 - 1)) / (fs->fs_blocksize * 8); if (get_sb_bmap_nr (sb) != p_bmap_nr) { fsck_log("rebuild-sb: wrong bitmap number occured (%lu), fixed (%lu)\n", get_sb_bmap_nr (sb), p_bmap_nr); set_sb_bmap_nr (sb, (block_count + (fs->fs_blocksize * 8 - 1)) / (fs->fs_blocksize * 8)); } if (get_sb_root_block (sb) > block_count) { fsck_log("rebuild-sb: wrong root block occured (%lu), zeroed\n", get_sb_root_block (sb)); set_sb_root_block (sb, 0); } if (get_sb_free_blocks (sb) > block_count) { fsck_log ("rebuild-sb: wrong free block count occured (%lu), zeroed\n", get_sb_free_blocks (sb)); set_sb_free_blocks (sb, 0); } if (get_sb_umount_state (sb) != FS_CLEANLY_UMOUNTED && get_sb_umount_state (sb) != FS_NOT_CLEANLY_UMOUNTED) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong umount state (%u), " "fixed to (FS_NOT_CLEANLY_UMOUNTED)\n", get_sb_umount_state (sb)); set_sb_umount_state (sb, FS_NOT_CLEANLY_UMOUNTED); } if (get_sb_oid_cursize (sb) == 1 || get_sb_oid_cursize (sb) > get_sb_oid_maxsize (sb)) { fsck_log("rebuild-sb: wrong objectid map occured (%lu), zeroed\n", get_sb_oid_cursize (sb)); set_sb_oid_cursize (sb, 0); } if ( get_sb_tree_height (sb) && ((get_sb_tree_height (sb) < DISK_LEAF_NODE_LEVEL + 1) || (get_sb_tree_height (sb) > MAX_HEIGHT)) ) { fsck_log("rebuild-sb: wrong tree height occured (%u), zeroed\n", get_sb_tree_height (sb)); set_sb_tree_height (sb, 0); } if (get_sb_hash_code (sb) && code2name (get_sb_hash_code (sb)) == 0) { fsck_log("rebuild-sb: wrong hash occured (%lu), zeroed\n", get_sb_hash_code (sb)); set_sb_hash_code (sb, 0); } if (version == 1 || version == 3) { if (!uuid_is_correct(sb->s_uuid)) { if (generate_random_uuid (sb->s_uuid)) { fsck_log ("rebuild-sb: no uuid found, failed to genetate UUID\n"); } else { fsck_log ("rebuild-sb: no uuid found, a new uuid generated (%U)\n", sb->s_uuid); } } if (sb->s_flags != 0 && sb->s_flags != 1) { fsck_log ("rebuild-sb: super block flags found (%u), zeroed\n", sb->s_flags); sb->s_flags = 0; } } /* if we have a standard journal reserved = 0 dev - same size = journal_default_size(fs->fs_super_bh->b_blocknr, fs) offset = journal_default_size(fs) if we have a non standard journal if we found magic string try to find a jhead and comare dev, size, offset there if params are not equal move to "if we did not find a magic string" clause if we did not find a magic string ask user about his journal try to find a jhead and comare dev, size, offset there if params are not equal exit with error */ p_jp_journal_1st_block = get_journal_start_must (fs); if (standard_journal == 1) { if (get_jp_journal_dev (sb_jp(sb)) != 0) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal device " "occured (%lu), fixed (0)\n", get_jp_journal_dev (sb_jp(sb))); set_jp_journal_dev (sb_jp(sb), 0); } if (get_sb_reserved_for_journal (sb) != 0) { fsck_log ("rebuild-sb: wrong size reserved for default journal occured " "(%lu), fixed (0)\n", get_sb_reserved_for_journal (sb)); set_sb_reserved_for_journal (sb, 0); } if (get_jp_journal_1st_block (sb_jp(sb)) != p_jp_journal_1st_block) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal first " "block occured (%lu), fixed (%lu)\n", get_jp_journal_1st_block (sb_jp(sb)), p_jp_journal_1st_block); set_jp_journal_1st_block (sb_jp(sb) , p_jp_journal_1st_block); } if (get_jp_journal_size (sb_jp(sb)) != journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal size " "occured (%lu), fixed (%lu)\n", get_jp_journal_size (sb_jp(sb)) + 1, journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1); set_jp_journal_size (sb_jp(sb), journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize)); } if ((retval = reiserfs_open_journal(fs, filename, O_RDWR | O_LARGEFILE))) { fsck_log("\nrebuild-sb: Failed to open the journal device (%s).", filename); exit(retval == 1 ? EXIT_USER : EXIT_OPER); } } else if (!fsck_skip_journal(fs)) { /* Check that specified non-standard journal device exists. */ journal_dev_name = fsck_data (fs)->journal_dev_name; retval = stat64(journal_dev_name, &stat_buf); if (retval == -1) reiserfs_exit (EXIT_USER, "rebuild_sb: error while detecting the " "specified journal device (%s): %s\n", journal_dev_name, strerror(errno)); retval = 0; if (magic_was_found) { /* Super block was found. Try to open the journal on the base of its * journal parameters. */ retval = reiserfs_open_journal(fs, journal_dev_name, O_RDWR | O_LARGEFILE); if (retval == 0) { j_head = (struct reiserfs_journal_header *)(fs->fs_jh_bh->b_data); retval = memcmp(&j_head->jh_journal, sb_jp(sb), sizeof(struct journal_params)); if (retval) { /* journal parameters from the SB and from the J_Header does not * match. Close the jouranl, ask the user about correct journal * parameters. */ reiserfs_close_journal(fs); } } if (!reiserfs_journal_opened(fs)) { fsck_log ("Journal cannot be opened, assuming specified journal device " "is correct\n"); } } if (!reiserfs_journal_opened(fs)) { __u64 default_value; /* journal was not found or SB and J_Header parameters does not match. */ if (magic_was_found == 0) default_value = (!strcmp(fs->fs_file_name, journal_dev_name)) ? p_jp_journal_1st_block : 0; else default_value = get_jp_journal_1st_block (sb_jp(sb)); printf("\nEnter journal offset on %s in blocks [%Lu]: \n", journal_dev_name, (unsigned long long)default_value); getline (&answer, &n, stdin); if (strcmp(answer, "\n")) { retval = (int) strtol (answer, &tmp, 0); if ((*tmp && strcmp(tmp, "\n")) || retval < 0) reiserfs_exit(EXIT_USER, "rebuild_sb: wrong offset specified\n"); set_jp_journal_1st_block (sb_jp(sb), retval); } else set_jp_journal_1st_block (sb_jp(sb), default_value); p_jp_dev_size = count_blocks (journal_dev_name, fs->fs_blocksize); /* some checks for journal offset */ if (strcmp(fs->fs_file_name, journal_dev_name) != 0) { if (p_jp_dev_size < get_jp_journal_1st_block (sb_jp(sb)) + 1) reiserfs_exit(EXIT_USER, "rebuild_sb: offset is much than device size\n"); } /* default size if magic was not found is device size - journal_1st_block; default size if magic was found is found value + 1 block for journal header */ if (magic_was_found == 0) default_value = (!strcmp(fs->fs_file_name, journal_dev_name)) ? journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1 : p_jp_dev_size - get_jp_journal_1st_block (sb_jp(sb)); else default_value = get_jp_journal_size (sb_jp(sb)) + 1; printf("\nEnter journal size (including 1 block for journal header) on " "%s in blocks [%Lu]: \n", journal_dev_name, (unsigned long long)default_value); getline (&answer, &n, stdin); if (strcmp(answer, "\n")) { retval = (int) strtol (answer, &tmp, 0); if ((*tmp && strcmp(tmp, "\n")) || retval < 0) reiserfs_exit(EXIT_USER, "rebuild_sb: wrong offset specified\n"); set_jp_journal_size (sb_jp(sb), retval - 1); } else { set_jp_journal_size (sb_jp(sb), default_value - 1); } /* some checks for journal size */ if (get_jp_journal_size (sb_jp(sb)) + get_jp_journal_1st_block (sb_jp(sb)) + 1 > p_jp_dev_size) reiserfs_exit(EXIT_USER, "rebuild_sb: journal offset + journal size is " "greater than device size\n"); /* some checks for journal size */ if (get_jp_journal_size (sb_jp(sb)) < JOURNAL_MIN_SIZE) reiserfs_exit(EXIT_USER, "rebuild_sb: journal size cannot be less than " "%lu blocks.\n", JOURNAL_MIN_SIZE + 1); if ((retval = reiserfs_open_journal(fs, journal_dev_name, O_RDWR | O_LARGEFILE))) { fsck_log("\nrebuild-sb: Failed to open a journal device (%s).", journal_dev_name); exit(retval == 1 ? EXIT_USER : EXIT_OPER); } /* SB was found, but journal params were broken and have been recovered. * Futher work goes as SB would not be found. */ magic_was_found = 0; } if (strcmp (fs->fs_file_name, journal_dev_name)) set_jp_journal_dev (sb_jp(sb), stat_buf.st_rdev); else set_jp_journal_dev (sb_jp(sb), 0); } else { fsck_log ("\nJournal was specified as not available. reiserfstune is " "needed.\n\n"); set_jp_journal_magic (sb_jp(sb), NEED_TUNE); } if (reiserfs_journal_opened(fs)) { /* Journal was openned. Check/fix journal parameters and copy it the journal * header. */ if (get_jp_journal_max_trans_len (sb_jp(sb)) != advise_journal_max_trans_len( get_jp_journal_max_trans_len (sb_jp(sb)), get_jp_journal_size (sb_jp(sb)), fs->fs_blocksize, 0)) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal max " "transaction length occured (%lu), fixed (%d)\n", get_jp_journal_max_trans_len (sb_jp(sb)), advise_journal_max_trans_len ( get_jp_journal_max_trans_len (sb_jp(sb)), get_jp_journal_size (sb_jp(sb)), fs->fs_blocksize, 0)); set_jp_journal_max_trans_len (sb_jp(sb), advise_journal_max_trans_len ( get_jp_journal_max_trans_len (sb_jp(sb)), get_jp_journal_size (sb_jp(sb)), fs->fs_blocksize, 0)); } if (get_jp_journal_max_batch (sb_jp(sb)) != advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb)))) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal max " "batch size occured (%lu), fixed (%d)\n", get_jp_journal_max_batch (sb_jp(sb)), advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb)))); set_jp_journal_max_batch (sb_jp(sb), advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb)))); } if (get_jp_journal_max_commit_age (sb_jp(sb)) != advise_journal_max_commit_age()) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal " "max commit age occured (%lu), fixed (%d)\n", get_jp_journal_max_commit_age (sb_jp(sb)), advise_journal_max_commit_age()); set_jp_journal_max_commit_age (sb_jp(sb), advise_journal_max_commit_age()); } if (get_jp_journal_max_trans_age (sb_jp(sb)) != advise_journal_max_trans_age()) { fsck_log ("rebuild-sb: wrong journal max commit age occured (%u), " "fixed (%u)\n", get_jp_journal_max_trans_age (sb_jp(sb)), advise_journal_max_trans_age()); set_jp_journal_max_trans_age (sb_jp(sb), advise_journal_max_trans_age()); } j_head = (struct reiserfs_journal_header *)(fs->fs_jh_bh->b_data); if (standard_journal == 0) { if (get_jp_journal_magic (sb_jp(sb)) == 0 || get_jp_journal_magic (sb_jp(sb)) == NEED_TUNE) { int magic; magic = random(); fsck_log ("rebuild-sb: genarate the new journal magic (%d)\n", magic); set_jp_journal_magic (sb_jp(sb), magic); set_jp_journal_magic (&j_head->jh_journal, magic); } } else { set_jp_journal_magic (sb_jp(sb), 0); } retval = memcmp(&j_head->jh_journal, sb_jp(sb), sizeof(struct journal_params)); if (retval) { if (standard_journal == 1) { fsck_log("\nrebuild-sb: You either have a corrupted journal or have just " "changed\nthe start of the partition with some partition table editor. " "If you are\nsure that the start of the partition is ok, rebuild the " "journal header.\n"); } else if (!magic_was_found) { fsck_log("\nrebuild-sb: journal header is not found. You either have " "a corrupted,\nbad configured(device/offset/size), not available " "journal or have just changed\nthe start of the journal partition " "with some partition table editor. In the \ncase of corrupted " "journal you need to use --no-journal-available. If you are\n" "sure that the start of the partition is ok and journal is " "available, rebuild\nthe journal header.\n"); } if (standard_journal || !magic_was_found) { if (!user_confirmed (stdout, "Do you want to rebuild the journal header? " "(y/n)[n]: ", "y\n")) { exit(EXIT_USER); } else exit_code = EXIT_FIXED; } memcpy(&j_head->jh_journal, sb_jp(sb), sizeof(struct journal_params)); mark_buffer_dirty(fs->fs_jh_bh); bwrite (fs->fs_jh_bh); } } /* whether journal header contains params with the same dev, offset, size will be checked in open_journal */ if (version == 1 || version == 3) sb_size = SB_SIZE; else sb_size = SB_SIZE_V1; if (ondisk_sb == NULL || memcmp(ondisk_sb, sb, sb_size - ((sb_size == SB_SIZE) ? sizeof(fs->fs_ondisk_sb->s_unused) : 0))) { /* smth was changed in SB or a new one has been built */ set_sb_fs_state (sb, get_sb_fs_state (sb) | FS_ERROR); if (ondisk_sb) { /* if super_block was found, we keep sb in ondisk_sb */ fs->fs_ondisk_sb = ondisk_sb; memcpy (ondisk_sb, sb, sb_size); freemem(sb); } fflush(stdout); print_block (stderr, fs, fs->fs_super_bh); if (user_confirmed (stderr, "Is this ok ? (y/n)[n]: ", "y\n")) { mark_buffer_uptodate (fs->fs_super_bh, 1); mark_buffer_dirty (fs->fs_super_bh); bwrite (fs->fs_super_bh); fsck_progress ("The fs may still be unconsistent. Run reiserfsck --check.\n\n"); exit_code = EXIT_FIXED; } else { mark_buffer_clean (fs->fs_super_bh); fsck_progress ("Super block was not written\n"); } } else { print_block (stderr, fs, fs->fs_super_bh); mark_buffer_clean (fs->fs_super_bh); fsck_progress ("\nSuper block seems to be correct\n\n"); } exit(exit_code); } /* if (version == 0) { brelse (fs->fs_super_bh); freemem (fs); close (fs->fs_dev); fs = NULL; } */ reiserfsprogs-3.6.9/fsck/fsck.h0000664000077100007710000004255107705261642012162 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "io.h" #include "misc.h" #include "reiserfs_lib.h" /* main.c */ extern reiserfs_filsys_t * fs; int main (int argc, char * argv []); /* Exit codes. */ #define EXIT_OK 0 #define EXIT_FIXED 1 #define EXIT_FATAL 4 #define EXIT_FIXABLE 6 #define EXIT_OPER 8 /* Some operation returns error. */ #define EXIT_USER 16 /* * modes */ #define DO_NOTHING 0 #define FSCK_CHECK 1 #define FSCK_FIX_FIXABLE 2 #define FSCK_SB 3 #define FSCK_REBUILD 4 #define FSCK_ROLLBACK_CHANGES 5 #define FSCK_CLEAN_ATTRIBUTES 7 #define FSCK_AUTO 8 /* -a || -p specified */ /* temporary */ #define DO_TEST 9 /* * options */ #define OPT_INTERACTIVE 1 << 0 #define OPT_ADJUST_FILE_SIZE 1 << 1 /* not default yet */ #define OPT_QUIET 1 << 2 /* no "speed" info */ #define OPT_SILENT 1 << 3 /* no complains about found corruptions */ #define OPT_BACKGROUND 1 << 4 #define OPT_SKIP_JOURNAL 1 << 5 #define OPT_HASH_DEFINED 1 << 6 #define OPT_SAVE_PASSES_DUMP 1 << 7 #define OPT_SAVE_ROLLBACK 1 << 8 #define OPT_YES 1 << 9 #define BADBLOCKS_FILE 1 << 10 /* pass0.c */ void pass_0 (reiserfs_filsys_t *); void load_pass_0_result (FILE *, reiserfs_filsys_t *); int leaf_structure_check(reiserfs_filsys_t * fs, struct buffer_head * bh); int is_used_leaf (unsigned long block); int is_good_unformatted (unsigned long block); void mark_good_unformatted (unsigned long block); int is_bad_unformatted (unsigned long block); int are_there_allocable_blocks (unsigned int amout_needed); unsigned long alloc_block (void); void make_allocable (unsigned long block); void register_uninsertable (unsigned long block); void register_saved_item (void); int still_bad_unfm_ptr_1 (unsigned long block); int still_bad_unfm_ptr_2 (unsigned long block); void make_alloc_bitmap (reiserfs_filsys_t *); void delete_aux_bitmaps (); void set_aux_bitmaps(reiserfs_bitmap_t * leaves, reiserfs_bitmap_t * good, reiserfs_bitmap_t * bad); #define __is_marked(name,block) reiserfs_bitmap_test_bit (name##_bitmap, block) #define __mark(name,block) reiserfs_bitmap_set_bit (name##_bitmap, block) #define __unmark(name,block) reiserfs_bitmap_clear_bit (name##_bitmap, block) /* unformatted in tree */ extern reiserfs_bitmap_t * bad_unfm_in_tree_once_bitmap; #define is_bad_unfm_in_tree_once(block) __is_marked (bad_unfm_in_tree_once, block) #define mark_bad_unfm_in_tree_once(block) __mark (bad_unfm_in_tree_once, block) /* pass1.c */ void pass_1 (reiserfs_filsys_t *); void load_pass_1_result (FILE *, reiserfs_filsys_t *); struct buffer_head * make_buffer (int dev, unsigned long blocknr, int size, char * data); void build_the_tree (void); extern int g_unaccessed_items; int is_item_reachable (struct item_head * ih); void mark_item_reachable (struct item_head * ih, struct buffer_head * bh); void mark_item_unreachable (struct item_head * ih); struct si * remove_saved_item (struct si * si); int tree_is_empty (void); void make_single_leaf_tree (struct buffer_head * bh); /* pass2.c */ void pass_2 (reiserfs_filsys_t *); void load_pass_2_result (reiserfs_filsys_t *); void insert_item_separately (struct item_head * ih, char * item, int was_in_tree); void save_item (struct si ** head, struct item_head * ih, char * item, __u32 blocknr); struct si * save_and_delete_file_item (struct si * si, struct path * path); void take_bad_blocks_put_into_tree (void); void rewrite_object (struct item_head * ih, int do_remap); void pass_2_take_bad_blocks_put_into_tree (void); /*int is_remapped (struct item_head * ih);*/ void link_relocated_files (void); int should_relocate (struct item_head * ih); void relocate_dir (struct item_head * ih, int change_ih); extern __u32 objectid_for_relocation (struct key * key); extern void linked_already(struct key *new_key); /* file.c */ struct si { struct item_head si_ih; char * si_dnm_data; struct si * si_next; __u32 si_blocknr; // changed by XB; struct si * last_known; }; void put_saved_items_into_tree (struct si *); int reiserfsck_file_write (struct item_head * ih, char * item, int was_in_tree); int are_file_items_correct (struct item_head * sd_ih, void * sd, __u64 * size, __u32 * blocks, int mark_passed_items, int * symlink); int delete_N_items_after_key(struct key * start_key, struct si ** save_here, int skip_dir_items, int n_to_delete); void rewrite_file (struct item_head * ih, int should_relocate, int should_change_ih); /* semantic.c */ /* return values for check_regular_file and check_semantic_tree */ #define OK 0 #define STAT_DATA_NOT_FOUND -1 #define DIRECTORY_HAS_NO_ITEMS -2 #define RELOCATED -3 #define LOOP_FOUND -4 void load_semantic_result (FILE *, reiserfs_filsys_t *); void pass_3_semantic (reiserfs_filsys_t *); void semantic_check (void); int check_semantic_tree (struct key * key, struct key * parent, int is_dot_dot, int lost_found, struct item_head * new_ih); void zero_nlink (struct item_head * ih, void * sd); int not_a_directory (void * sd); int not_a_regfile (void * sd); int fix_obviously_wrong_sd_mode (struct path * path); int is_dot_dot (char * name, int namelen); int is_dot (char * name, int namelen); /*void create_dir_sd (reiserfs_filsys_t * fs, struct path * path, struct key * key);*/ int rebuild_check_regular_file (struct path * path, void * sd, struct item_head * new_ih); int rebuild_semantic_pass (struct key * key, struct key * parent, int is_dot_dot, struct item_head * new_ih); /* lost+found.c */ void pass_3a_look_for_lost (reiserfs_filsys_t *); void load_lost_found_result (reiserfs_filsys_t *); /* pass4.c */ //void get_next_key (struct path * path, int i, struct key * key); void pass_4_check_unaccessed_items (void); /* check.c */ int is_leaf_bad (struct buffer_head * bh); int is_bad_item (struct buffer_head * bh, struct item_head *, char *); /*int check_file_system (void);*/ void reiserfsck_check_pass1 (void); /*char * bad_name (char * name, int namelen);*/ /* to test result of direcotry item recovering on pass 0 */ int is_bad_directory (struct item_head * ih, char * item, int dev, int blocksize); //extern int bad_block_number (struct super_block * s, blocknr_t block); /* check_tree.c */ void check_fs_tree (reiserfs_filsys_t *); void do_clean_attributes (reiserfs_filsys_t * fs); int bad_pair (reiserfs_filsys_t *, struct buffer_head * bh, int i); int bad_leaf_2 (reiserfs_filsys_t *, struct buffer_head * bh); extern int should_be_relocated (struct key * key); extern void to_be_relocated (struct key * key); extern void clear_relocated_list(void); /* ustree.c */ void reiserfsck_paste_into_item (struct path * path, const char * body, int size); void reiserfsck_insert_item (struct path * path, struct item_head * ih, const char * body); void reiserfsck_delete_item (struct path * path, int temporary); void reiserfsck_cut_from_item (struct path * path, int cut_size); /*typedef int (comp3_function_t)(void * key1, void * key2, int version);*/ /*typedef int (comp_function_t)(struct key * key1, struct key * key2);*/ /*int ubin_search_id(__u32 * id, __u32 * base, __u32 number, __u32 * pos);*/ /*int usearch_by_key (struct super_block * s, struct key * key, struct path * path);*/ /*int usearch_by_key_3 (struct super_block * s, struct key * key, struct path * path, int * repeat, int stop_level, comp3_function_t comp_func, int version); int usearch_by_entry_key (struct super_block * s, struct key * key, struct path * path);*/ typedef int do_after_read_t (reiserfs_filsys_t *, struct buffer_head **, int h); typedef int do_on_full_path_t (reiserfs_filsys_t *, struct buffer_head **, int); void pass_through_tree (reiserfs_filsys_t *, do_after_read_t, do_on_full_path_t, int depth); //int comp_keys_3 (void * key1, void * key2); //int comp_dir_entries (void * key1, void * key2); /* bitmap.c */ int reiserfsck_reiserfs_new_blocknrs (reiserfs_filsys_t * fs, unsigned long * pblocknrs, unsigned long start_from, int amount_needed); int reiserfsck_reiserfs_free_block (reiserfs_filsys_t * fs, unsigned long block); struct buffer_head * reiserfsck_get_new_buffer (unsigned long start); int is_block_used (unsigned long block); void mark_block_used (unsigned long block, int check_hardware); void mark_block_uninsertable (unsigned long block); int is_block_uninsertable (unsigned long block); /* objectid.c */ int comp_ids(const void *p1, const void *p2); int is_objectid_used (reiserfs_filsys_t *, __u32 objectid); typedef struct id_map { void **index; __u32 count, last_used; } id_map_t; id_map_t *id_map_init(); void id_map_free(id_map_t *); int id_map_test(id_map_t *map, __u32 id); int id_map_mark(id_map_t *map, __u32 id); __u32 id_map_alloc(id_map_t *map); void id_map_flush(struct id_map * map, reiserfs_filsys_t * fs); /* FIXME: Needs to be implemented void fetch_objectid_map (struct id_map * map, reiserfs_filsys_t * fs); void reiserfs_objectid_map_save (FILE * fp, struct id_map * id_map); struct id_map * reiserfs_objectid_map_load (FILE * fp); */ void mark_formatted_pointed_by_indirect (__u32); int is_formatted_pointed_by_indirect (__u32); #define MAP_NOT_PACKED 0 #define MAP_PACKED 1 struct pass0_stat { unsigned long dealt_with; /* number of blocks read during pass 0 */ unsigned long leaves; /* blocks looking like reiserfs leaves found */ unsigned long leaves_corrected; unsigned long all_contents_removed; unsigned long too_old_leaves; /* these are leaves which contains direntries with different hash from the one specified with -h */ unsigned long wrong_pointers; /* pointers in indirect items pointing to wrong area */ unsigned long pointed; /* pointers blocks of device pointed by all indirect items */ }; struct pass1_stat { unsigned long leaves; /* leaves found in pass0 to build tree off */ unsigned long inserted_leaves; /* number of leaves inserted by pointers */ unsigned long pointed_leaves; /* pointers in indirect items which pointed to leaves (zeroed) */ unsigned long uninsertable_leaves; unsigned long non_unique_pointers; /* pointers to already pointed unformatted nodes */ unsigned long correct_pointers; unsigned long saved_items; /* items saved on pass1: should be 0 */ unsigned long allocable_blocks; /* allocable blocks before pass 1 starts */ }; struct pass2_stat { unsigned long leaves; /* leaves inserted item by item */ unsigned long safe_non_unique_pointers; /* these are just the same pointers */ unsigned long relocated; unsigned long shared_objectids; unsigned long rewritten; }; struct semantic_stat { unsigned long oid_sharing_files_relocated; unsigned long regular_files; unsigned long directories; unsigned long symlinks; unsigned long broken_files; unsigned long others; unsigned long fixed_sizes; unsigned long oid_sharing; unsigned long oid_sharing_dirs_relocated; unsigned long deleted_entries; }; struct lost_found_stat { unsigned long dir_recovered; unsigned long empty_lost_dirs; unsigned long lost_found; unsigned long lost_found_files; unsigned long lost_found_dirs; unsigned long oid_sharing; unsigned long oid_sharing_dirs_relocated; unsigned long oid_sharing_files_relocated; }; struct pass_4_stat { unsigned long deleted_items; }; struct rebuild_info { union { struct pass0_stat pass0; struct pass1_stat pass1; struct pass2_stat pass2; struct { struct semantic_stat semantic; struct lost_found_stat lost_found; } tree; struct pass_4_stat pass4; } pass_u; /* bitmaps */ reiserfs_bitmap_t * source_bitmap; reiserfs_bitmap_t * new_bitmap; reiserfs_bitmap_t * allocable_bitmap; reiserfs_bitmap_t * uninsertables; char * bitmap_file_name; /*char * new_bitmap_file_name;*/ char * passes_dump_file_name; /* after pass 0, 1 or 2 reiserfsck can store data with which it will be able to start from the point it stopped last time at */ unsigned short mode; unsigned long options; /* rollback file */ char * rollback_file; /* hash hits stat */ int hash_amount; unsigned long * hash_hits; char * defined_hash; #define USED_BLOCKS 1 #define EXTERN_BITMAP 2 #define ALL_BLOCKS 3 int scan_area; int use_journal_area; int test; }; struct check_info { unsigned long bad_nodes; unsigned long fatal_corruptions; unsigned long fixable_corruptions; // unsigned long badblocks_corruptions; unsigned long leaves; unsigned long internals; unsigned long dirs; unsigned long files; unsigned long safe; unsigned long unfm_pointers; unsigned long zero_unfm_pointers; reiserfs_bitmap_t * deallocate_bitmap; }; struct fsck_data { unsigned short mode; /* check, rebuild, etc*/ unsigned long options; struct rebuild_info rebuild; struct check_info check; char * journal_dev_name; /* log file name and handle */ char * log_file_name; FILE * log; /* this is a file where reiserfsck will explain what it is doing. This is usually stderr. But when -g is specified - reiserfsck runs in the background and append progress information into 'fsck.run' */ FILE * progress; /* objectid maps */ id_map_t * proper_id_map; id_map_t * semantic_id_map; /* this objectid map is used to cure objectid sharing problem */ }; #define fsck_data(fs) ((struct fsck_data *)((fs)->fs_vp)) #define pass_0_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.pass0)) #define pass_1_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.pass1)) #define pass_2_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.pass2)) #define sem_pass_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.tree.semantic)) #define lost_found_pass_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.tree.lost_found)) #define pass_4_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.pass4)) #define fsck_check_stat(fs) (&(fsck_data(fs)->check)) #define proper_id_map(s) fsck_data(s)->proper_id_map #define semantic_id_map(s) fsck_data(s)->semantic_id_map #define fsck_source_bitmap(fs) fsck_data(fs)->rebuild.source_bitmap #define fsck_new_bitmap(fs) fsck_data(fs)->rebuild.new_bitmap #define fsck_allocable_bitmap(fs) fsck_data(fs)->rebuild.allocable_bitmap #define fsck_uninsertables(fs) fsck_data(fs)->rebuild.uninsertables #define fsck_deallocate_bitmap(fs) fsck_data(fs)->check.deallocate_bitmap #define fsck_interactive(fs) (fsck_data(fs)->options & OPT_INTERACTIVE) //#define fsck_fix_fixable(fs) (fsck_data(fs)->options & OPT_FIX_FIXABLE) #define fsck_run_one_step(fs) (fsck_data(fs)->options & OPT_SAVE_PASSES_DUMP) #define fsck_save_rollback(fs) (fsck_data(fs)->options & OPT_SAVE_ROLLBACK) /* change unknown modes (corrupted) to mode of regular files, fix file sizes which are bigger than a real file size, relocate files with shared objectids (this slows fsck down (when there are too many files sharing the same objectid), it will also remove other names pointing to this file */ #define fsck_adjust_file_size(fs) (fsck_data(fs)->options & OPT_ADJUST_FILE_SIZE) #define fsck_quiet(fs) (fsck_data(fs)->options & OPT_QUIET) #define fsck_silent(fs) (fsck_data(fs)->options & OPT_SILENT) #define fsck_in_background(fs) (fsck_data(fs)->options & OPT_BACKGROUND) #define fsck_hash_defined(fs) (fsck_data(fs)->options & OPT_HASH_DEFINED) #define fsck_skip_journal(fs) (fsck_data(fs)->options & OPT_SKIP_JOURNAL) #define fsck_yes_all(fs) (fsck_data(fs)->options & OPT_YES) #define fsck_mode(fs) (fsck_data(fs)->mode) #define fsck_log_file(fs) (fsck_data(fs)->log) #define fsck_progress_file(fs) ((fs && fsck_data(fs)->progress) ? fsck_data(fs)->progress : stderr) /* name of file where we store information for continuing */ #define state_dump_file(fs) fsck_data(fs)->rebuild.passes_dump_file_name /* name of file where we store rollback data */ #define state_rollback_file(fs) fsck_data(fs)->rebuild.rollback_file int fsck_user_confirmed (reiserfs_filsys_t * fs, char * q, char * a, int default_answer); void stage_report (int, reiserfs_filsys_t *); /* journal.c */ int replay_journal (reiserfs_filsys_t *); /*pass1: rebuild super block*/ void rebuild_sb (reiserfs_filsys_t * fs, char * filename, struct fsck_data * data); #define fsck_log(fmt, list...) \ {\ if (!fsck_silent (fs))\ reiserfs_warning (fsck_log_file (fs), fmt, ## list);\ } #define fsck_progress(fmt, list...) \ {\ reiserfs_warning (fsck_progress_file(fs), fmt, ## list);\ fflush (fsck_progress_file(fs));\ } #define FATAL 1 #define FIXABLE 2 void one_more_corruption(reiserfs_filsys_t *fs, int kind); void one_less_corruption(reiserfs_filsys_t *fs, int kind); /* #define one_more_corruption(fs,kind) fsck_check_stat (fs)->kind##_corruptions++ #define one_less_corruption(fs,kind) fsck_check_stat (fs)->kind##_corruptions-- */ #define fsck_exit(fmt, list...) \ {\ reiserfs_warning (fsck_progress_file(fs), fmt, ## list);\ exit (EXIT_USER);\ } reiserfsprogs-3.6.9/fsck/Makefile.am0000664000077100007710000000053707665645672013133 sbin_PROGRAMS = reiserfsck reiserfsck_SOURCES = main.c pass0.c pass1.c pass2.c semantic_check.c \ semantic_rebuild.c pass4.c lost+found.c ubitmap.c uobjectid.c ustree.c \ ufile.c check_tree.c info.c super.c fsck.h man_MANS = reiserfsck.8 EXTRA_DIST = $(man_MANS) LDADD = $(LDFLAGS) $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a reiserfsprogs-3.6.9/fsck/Makefile.in0000644000077100007710000003576207705315225013131 # Makefile.in generated by automake 1.7.2 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__quote = @am__quote@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ sbin_PROGRAMS = reiserfsck reiserfsck_SOURCES = main.c pass0.c pass1.c pass2.c semantic_check.c \ semantic_rebuild.c pass4.c lost+found.c ubitmap.c uobjectid.c ustree.c \ ufile.c check_tree.c info.c super.c fsck.h man_MANS = reiserfsck.8 EXTRA_DIST = $(man_MANS) LDADD = $(LDFLAGS) $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a subdir = fsck mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = sbin_PROGRAMS = reiserfsck$(EXEEXT) PROGRAMS = $(sbin_PROGRAMS) am_reiserfsck_OBJECTS = main.$(OBJEXT) pass0.$(OBJEXT) pass1.$(OBJEXT) \ pass2.$(OBJEXT) semantic_check.$(OBJEXT) \ semantic_rebuild.$(OBJEXT) pass4.$(OBJEXT) lost+found.$(OBJEXT) \ ubitmap.$(OBJEXT) uobjectid.$(OBJEXT) ustree.$(OBJEXT) \ ufile.$(OBJEXT) check_tree.$(OBJEXT) info.$(OBJEXT) \ super.$(OBJEXT) reiserfsck_OBJECTS = $(am_reiserfsck_OBJECTS) reiserfsck_LDADD = $(LDADD) reiserfsck_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \ $(top_srcdir)/reiserfscore/libcore.a reiserfsck_LDFLAGS = DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/check_tree.Po ./$(DEPDIR)/info.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/lost+found.Po ./$(DEPDIR)/main.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/pass0.Po ./$(DEPDIR)/pass1.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/pass2.Po ./$(DEPDIR)/pass4.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/semantic_check.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/semantic_rebuild.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/super.Po ./$(DEPDIR)/ubitmap.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/ufile.Po ./$(DEPDIR)/uobjectid.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/ustree.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(reiserfsck_SOURCES) NROFF = nroff MANS = $(man_MANS) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(reiserfsck_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu fsck/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(sbindir) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f || exit 1; \ else :; fi; \ done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ rm -f $(DESTDIR)$(sbindir)/$$f; \ done clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) reiserfsck$(EXEEXT): $(reiserfsck_OBJECTS) $(reiserfsck_DEPENDENCIES) @rm -f reiserfsck$(EXEEXT) $(LINK) $(reiserfsck_LDFLAGS) $(reiserfsck_OBJECTS) $(reiserfsck_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_tree.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lost+found.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pass0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pass1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pass2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pass4.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/semantic_check.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/semantic_rebuild.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/super.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ubitmap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ufile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uobjectid.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ustree.Po@am__quote@ distclean-depend: -rm -rf ./$(DEPDIR) .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: man8dir = $(mandir)/man8 install-man8: $(man8_MANS) $(man_MANS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(man8dir) @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.8*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ *) ext='8' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ done uninstall-man8: @$(NORMAL_UNINSTALL) @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.8*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ *) ext='8' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ rm -f $(DESTDIR)$(man8dir)/$$inst; \ done ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) installdirs: $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(man8dir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-man install-exec-am: install-sbinPROGRAMS install-info: install-info-am install-man: install-man8 installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am uninstall-man uninstall-sbinPROGRAMS uninstall-man: uninstall-man8 .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-sbinPROGRAMS ctags distclean distclean-compile \ distclean-depend distclean-generic distclean-tags distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-man8 install-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-info-am uninstall-man \ uninstall-man8 uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: reiserfsprogs-3.6.9/fsck/info.c0000664000077100007710000001325407665645672012176 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" int fsck_user_confirmed (reiserfs_filsys_t * fs, char * q, char * a, int default_answer) { if (!fsck_interactive (fs)) return default_answer; return user_confirmed (fsck_progress_file (fs), q, a); } void stage_report (int pass, reiserfs_filsys_t * fs) { switch (pass) { case 0: { struct pass0_stat * stat; /* what has been done on pass 0 */ stat = pass_0_stat (fs); fsck_progress ("\tRead blocks (but not data blocks) %lu\n", stat->dealt_with); fsck_progress ("\t\tLeaves among those %lu\n", stat->leaves); if (stat->leaves_corrected) fsck_progress ("\t\t\t- corrected leaves %lu\n", stat->leaves_corrected); if (stat->all_contents_removed) fsck_progress ("\t\t\t- leaves all contents of which could not be saved and deleted %lu\n", stat->all_contents_removed); if (stat->too_old_leaves) fsck_progress ("\t\t\t- too old leaves %lu (skipped)\n", stat->too_old_leaves); if (stat->wrong_pointers) fsck_progress ("\t\tpointers in indirect items to wrong area %lu (zeroed)\n", stat->wrong_pointers); fsck_progress ("\t\tObjectids found %lu\n", proper_id_map(fs)->count); } break; case 1: { struct pass1_stat * stat; /* what has been done on pass 1 */ stat = pass_1_stat (fs); fsck_progress ("\t%lu leaves read\n", stat->leaves); fsck_progress ("\t\t%lu inserted\n", stat->inserted_leaves); if (stat->pointed_leaves) fsck_progress ("\t\t\t- pointers in indirect items pointing to metadata %lu (zeroed)\n", stat->pointed_leaves); if (stat->saved_items) fsck_progress ("\tSaved %lu items\n", stat->saved_items); if (stat->uninsertable_leaves) fsck_progress ("\t\t%lu not inserted\n", stat->uninsertable_leaves); if (stat->non_unique_pointers) fsck_progress ("\tnon-unique pointers in indirect items (zeroed) %lu\n", stat->non_unique_pointers); } break; case 2: { struct pass2_stat * stat; /* what has been done on pass 2 */ stat = pass_2_stat (fs); if (stat->leaves) fsck_progress ("\tLeaves inserted item by item %lu\n", stat->leaves); if (stat->safe_non_unique_pointers) fsck_progress ("\t%lu \n", stat->safe_non_unique_pointers); if (stat->shared_objectids) fsck_progress ("\t%lu shared objectids\n", stat->shared_objectids); if (stat->relocated) fsck_progress ("\tFiles relocated because of key conflicts with a directory %lu\n", stat->relocated); if (stat->rewritten) fsck_progress ("\tFiles rewritten %lu\n", stat->rewritten); } break; case 3: /* semantic */ { struct semantic_stat * stat; /* what has been done on the semantic pass */ stat = sem_pass_stat (fs); fsck_progress ("\tFiles found: %ld\n", stat->regular_files); fsck_progress ("\tDirectories found: %ld\n", stat->directories); if (stat->symlinks) fsck_progress ("\tSymlinks found: %ld\n", stat->symlinks); if (stat->others) fsck_progress ("\tOthers: %ld\n", stat->others); if (stat->broken_files) fsck_progress ("\tBroken (of files/symlinks/others): %ld\n", stat->broken_files); if (stat->fixed_sizes) fsck_progress ("\tFiles with fixed size: %ld\n", stat->fixed_sizes); if (stat->deleted_entries) fsck_progress ("\tNames pointing to nowhere (removed): %ld\n", stat->deleted_entries); if (stat->oid_sharing) fsck_progress ("\tObjects having used objectids: %lu\n", stat->oid_sharing); if (stat->oid_sharing_files_relocated) fsck_progress ("\t\tfiles fixed %lu\n", stat->oid_sharing_files_relocated); if (stat->oid_sharing_dirs_relocated) fsck_progress ("\t\tdirs fixed %lu\n", stat->oid_sharing_dirs_relocated); } break; case 0x3a: /* lost+found pass */ { struct lost_found_stat * stat; /* what has been done on the semantic pass */ stat = lost_found_pass_stat (fs); if (stat->lost_found) fsck_progress ("\tObjects without names %lu\n", stat->lost_found); if (stat->empty_lost_dirs) fsck_progress ("\tEmpty lost dirs removed %lu\n", stat->empty_lost_dirs); if (stat->lost_found_dirs) fsck_progress ("\tDirs linked to /lost+found: %lu\n", stat->lost_found_dirs); if (stat->dir_recovered) fsck_progress ("\t\tDirs without stat data found %lu\n", stat->dir_recovered); if (stat->lost_found_files) fsck_progress ("\tFiles linked to /lost+found %lu\n", stat->lost_found_files); if (stat->oid_sharing) fsck_progress ("\tObjects having used objectids: %lu\n", stat->oid_sharing); if (stat->oid_sharing_files_relocated) fsck_progress ("\t\tfiles fixed %lu\n", stat->oid_sharing_files_relocated); if (stat->oid_sharing_dirs_relocated) fsck_progress ("\t\tdirs fixed %lu\n", stat->oid_sharing_dirs_relocated); } break; case 4: /* removing of unreachable */ { struct pass_4_stat * stat; /* what has been done on the semantic pass */ stat = pass_4_stat (fs); if (stat->deleted_items) fsck_progress ("\tDeleted unreachable items %lu\n", stat->deleted_items); } break; case 5: fsck_progress ("There are on the filesystem:\n" "\tLeaves %lu\n\tInternal nodes %lu\n" "\tDirectories %lu\n\tOther files %lu\n" "\tData block pointers %lu (%lu of them are zero)\n" "\tSafe links %lu\n", fsck_check_stat (fs)->leaves, fsck_check_stat (fs)->internals, fsck_check_stat (fs)->dirs, fsck_check_stat (fs)->files, fsck_check_stat (fs)->unfm_pointers, fsck_check_stat (fs)->zero_unfm_pointers, fsck_check_stat (fs)->safe); } /* switch */ memset (&fsck_data (fs)->rebuild.pass_u, 0, sizeof (fsck_data (fs)->rebuild.pass_u)); } reiserfsprogs-3.6.9/fsck/ufile.c0000664000077100007710000012102207705261642012322 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" static int do_items_have_the_same_type (struct item_head * ih, struct key * key) { return (get_type (&ih->ih_key) == get_type (key)) ? 1 : 0; } static int are_items_in_the_same_node (struct path * path) { return (PATH_LAST_POSITION (path) < B_NR_ITEMS (PATH_PLAST_BUFFER (path)) - 1) ? 1 : 0; } static void cut_last_unfm_pointer (struct path * path, struct item_head * ih) { set_ih_free_space(ih, 0); if (I_UNFM_NUM (ih) == 1) reiserfsck_delete_item (path, 0); else reiserfsck_cut_from_item (path, -((int)UNFM_P_SIZE)); } /* if this is not a symlink - make it of_this_size; otherwise find a size and return it in symlink_size; */ static unsigned long indirect_to_direct (struct path * path, __u64 len, int symlink) { struct buffer_head * bh = PATH_PLAST_BUFFER (path); struct item_head * ih = PATH_PITEM_HEAD (path); __u32 unfm_ptr; struct buffer_head * unfm_bh = 0; struct item_head ins_ih; char * buf; __u32 * indirect; char bad_drct[fs->fs_blocksize]; /* direct item to insert */ memset (&ins_ih, 0, sizeof (ins_ih)); if (symlink) { set_ih_key_format (&ins_ih, KEY_FORMAT_1); } else { set_ih_key_format (&ins_ih, get_ih_key_format (ih)); } set_key_dirid (&ins_ih.ih_key, get_key_dirid (&ih->ih_key)); set_key_objectid (&ins_ih.ih_key, get_key_objectid (&ih->ih_key)); set_type_and_offset (get_ih_key_format (&ins_ih), &ins_ih.ih_key, get_offset (&ih->ih_key) + (I_UNFM_NUM (ih) - 1) * bh->b_size, TYPE_DIRECT); // we do not know what length this item should be indirect = get_item (path); unfm_ptr = le32_to_cpu (indirect [I_UNFM_NUM (ih) - 1]); if (unfm_ptr && (unfm_bh = bread (bh->b_dev, unfm_ptr, bh->b_size))) { /* we can read the block */ buf = unfm_bh->b_data; } else { /* we cannot read the block */ if (unfm_ptr) fsck_log ("indirect_to_direct: Reading of the block (%lu), pointed to by the file %K, failed\n", unfm_ptr, &ih->ih_key); memset (bad_drct, 0, fs->fs_blocksize); buf = bad_drct; } /* if (len > MAX_DIRECT_ITEM_LEN (fs->fs_blocksize)) { fsck_log ("indirect_to_direct: canot create such a long item %d (%K), " "Cutting it down to %d byte\n", len, &ih->ih_key, MAX_DIRECT_ITEM_LEN (fs->fs_blocksize) - 8); len = MAX_DIRECT_ITEM_LEN (fs->fs_blocksize) - 8; } if (!len) { buf = bad_link; len = strlen (bad_link); } */ set_ih_item_len (&ins_ih, (get_ih_key_format (ih) == KEY_FORMAT_2) ? ROUND_UP(len) : len); set_ih_free_space (&ins_ih, MAX_US_INT); mark_ih_become_tail(ih); mark_buffer_dirty(bh); // last last unformatted node pointer path->pos_in_item = I_UNFM_NUM (ih) - 1; cut_last_unfm_pointer (path, ih); /* insert direct item */ if (reiserfs_search_by_key_4 (fs, &(ins_ih.ih_key), path) == ITEM_FOUND) reiserfs_panic ("indirect_to_direct: The direct item %k should not exist yet.", &(ins_ih.ih_key)); reiserfsck_insert_item (path, &ins_ih, (const char *)(buf)); brelse (unfm_bh); /* put to stat data offset of first byte in direct item */ return get_offset (&ins_ih.ih_key); //offset; } /* start_key is the key after which N items need to be deleted save_here is a pointer where deleted items need to be saved if save is set. start_key is the first undeleted item. return whether we are sure there is nothing else of this file */ int delete_N_items_after_key(struct key * start_key, struct si ** save_here, int skip_dir_items, int n_to_delete) { struct path path; // struct key key = *start_key; struct key * rkey; int count = 0; while (1) { reiserfs_search_by_key_4 (fs, start_key, &path); if (get_item_pos (&path) == B_NR_ITEMS (get_bh (&path))) { rkey = uget_rkey (&path); if (rkey && !not_of_one_file (start_key, rkey)) { /* file continues in the right neighbor */ copy_key (start_key, rkey); pathrelse (&path); continue; } /* there is no more items with this key */ pathrelse (&path); return 1; } if (is_stat_data_ih (get_ih(&path))) fix_obviously_wrong_sd_mode (&path); rkey = &(get_ih (&path))->ih_key; if (not_of_one_file (start_key, rkey)) { /* there are no more item with this key */ pathrelse (&path); return 1; } copy_key (start_key, rkey); /* ok, item found, but make sure that it is not a directory one */ if ((is_stat_data_key (rkey) && !not_a_directory (get_item (&path))) || (is_direntry_key (rkey))) { if (skip_dir_items) { /* item of directory found. Leave it in the tree */ set_offset (KEY_FORMAT_1, start_key, get_offset (start_key) + 1); pathrelse (&path); continue; } else { reiserfs_panic ("delete_N_items_after_key: No directory item of %K are " "expected", start_key); } } if (save_here != NULL) *save_here = save_and_delete_file_item (*save_here, &path); else reiserfsck_delete_item (&path, 0); count++; if (count == n_to_delete) break; pathrelse (&path); } return 0; } /* returns 1 when file looks correct, -1 if directory items appeared there, 0 - only holes in the file found */ /* when it returns, key->k_offset is offset of the last item of file */ /* sd_size is zero if we do not need to convert any indirect to direct */ int are_file_items_correct (struct item_head * sd_ih, void * sd, __u64 * size, __u32 * blocks, int mark_passed_items, int * symlink) { struct path path; struct item_head * ih; struct key * next_key, * key; __u32 sd_first_direct_byte = 0; __u64 sd_size; unsigned int i; int retval, was_tail = 0; int had_direct = 0; int key_version = get_ih_key_format (sd_ih); int next_is_another_object = 0; __u64 last_unfm_offset = 0; int will_convert = 0; int should_convert; should_convert = (fsck_mode (fs) != FSCK_REBUILD) || mark_passed_items; key = &sd_ih->ih_key; get_sd_size (sd_ih, sd, &sd_size); if (key_version == KEY_FORMAT_1) get_sd_first_direct_byte (sd_ih, sd, &sd_first_direct_byte); set_offset (key_version, key, 1); set_type (key_version, key, TYPE_DIRECT); /* correct size and st_blocks */ *size = 0; *blocks = 0; path.path_length = ILLEGAL_PATH_ELEMENT_OFFSET; do { retval = usearch_by_position (fs, key, key_version, &path); if (retval == POSITION_FOUND && path.pos_in_item != 0) die ("are_file_items_correct: All bytes we look for must be first items byte (position 0)."); switch (retval) { case POSITION_FOUND:/**/ ih = PATH_PITEM_HEAD (&path); if (ih_was_tail (ih)) { was_tail = 1; } set_type (key_version, key, get_type (&ih->ih_key)); if (mark_passed_items == 1) { mark_item_reachable (ih, PATH_PLAST_BUFFER (&path)); } // does not change path next_key = get_next_key_2 (&path); if (next_key == 0 || not_of_one_file (key, next_key) || (!is_indirect_key (next_key) && !is_direct_key(next_key))) { next_is_another_object = 1; will_convert = (is_indirect_ih (ih) && sd_size && (I_UNFM_NUM (ih) > 0)); if (will_convert) { last_unfm_offset = get_offset (key) + fs->fs_blocksize * (I_UNFM_NUM (ih) - 1); /* if symlink or [ 1. sd_size points somewhere into last unfm block 2. one item of the file was direct before for 3_6 || FDB points to the tail correctly for 3_5 3. we can have a tail in the file of a such size ] */ will_convert = will_convert && (sd_size >= last_unfm_offset) && (sd_size < last_unfm_offset + fs->fs_blocksize) && !STORE_TAIL_IN_UNFM (sd_size, sd_size - last_unfm_offset + 1, fs->fs_blocksize); will_convert = will_convert && (*symlink || ((key_version == KEY_FORMAT_1) && (sd_first_direct_byte == last_unfm_offset)) || ((key_version == KEY_FORMAT_2) && was_tail)); } } if (should_convert) { *symlink = *symlink && (will_convert || is_direct_key(&ih->ih_key)); if (!(*symlink) && key_version != get_ih_key_format (ih)) { if (fsck_mode(fs) == FSCK_CHECK) { fsck_log("are_file_items_correct: vpf-10250: block %lu, item (%d): The item format (%H)"\ " is not equal to SD format (%d)\n", get_bh(&path)->b_blocknr, PATH_LAST_POSITION(&path), ih, key_version); one_more_corruption (fs, FIXABLE); } else { fsck_log("are_file_items_correct: vpf-10280: block %lu, item (%d): The item format (%H)"\ " is not equal to SD format (%d) - fixed.\n", get_bh(&path)->b_blocknr, PATH_LAST_POSITION(&path), ih, key_version); set_type_and_offset (key_version, &ih->ih_key, get_offset (&ih->ih_key), get_type (&ih->ih_key)); set_ih_key_format(ih, key_version); mark_buffer_dirty(get_bh(&path)); } } if (*symlink && is_direct_key(&ih->ih_key)) { /* symlink. Check that it is of KEY_FORMAT_1 */ if (fsck_mode(fs) == FSCK_CHECK) { if ((get_ih_key_format(ih) != KEY_FORMAT_1) || (key_format(&ih->ih_key) != KEY_FORMAT_1)) { fsck_log("are_file_items_correct: vpf-10732: block %lu, item (%d): The symlink format (%H)"\ " is not equal to 3.5 format (%d)\n", get_bh(&path)->b_blocknr, PATH_LAST_POSITION(&path), ih, KEY_FORMAT_1); one_more_corruption (fs, FIXABLE); } } else { if ((get_ih_key_format(ih) != KEY_FORMAT_1) || (key_format(&ih->ih_key) != KEY_FORMAT_1)) { fsck_log("are_file_items_correct: vpf-10732: block %lu, item (%d): The symlink format (%H)"\ " is not equal to 3.5 format (%d)\n", get_bh(&path)->b_blocknr, PATH_LAST_POSITION(&path), ih, KEY_FORMAT_1); set_type_and_offset(KEY_FORMAT_1, &ih->ih_key, get_offset(&ih->ih_key), get_type(&ih->ih_key)); set_ih_key_format(ih, KEY_FORMAT_1); mark_buffer_dirty(get_bh(&path)); } } } if (will_convert) *size = sd_size; else *size = get_offset (&ih->ih_key) + get_bytes_number (ih, fs->fs_blocksize) - 1; if (get_type (&ih->ih_key) == TYPE_INDIRECT) { if (*symlink) /* symlinks must be calculated as dirs */ *blocks = dir_size2st_blocks (*size); else for (i = 0; i < I_UNFM_NUM (ih); i ++) { __u32 * ind = (__u32 *)get_item(&path); if (ind[i] != 0) *blocks += (fs->fs_blocksize >> 9); } } else if (get_type (&ih->ih_key) == TYPE_DIRECT) { if (*symlink) /* symlinks must be calculated as dirs */ *blocks = dir_size2st_blocks (*size); else if (!had_direct) *blocks += (fs->fs_blocksize >> 9); /* calculate only the first direct byte */ had_direct++; } } if (next_is_another_object) { /* next item does not exists or is of another object, therefore all items of file are correct */ if (will_convert) { if (fsck_mode (fs) == FSCK_CHECK) { /* here it can be symlink only */ fsck_log ("are_file_items_correct: The indirect item should be converted back" " to direct %K\n", &ih->ih_key); one_more_corruption (fs, FIXABLE); pathrelse (&path); } else { __u32 * ind = (__u32 *)get_item(&path); /* DEBUG message. fsck_log ("are_file_items_correct: The indirect item is converted back to direct %K\n", &ih->ih_key); */ if (ind [I_UNFM_NUM (ih) - 1] == 0) *blocks += (fs->fs_blocksize >> 9); /* path is released here. */ sd_first_direct_byte = indirect_to_direct (&path, sd_size - last_unfm_offset + 1, *symlink); /* last item of the file is direct item */ set_offset (key_version, key, sd_first_direct_byte); set_type (key_version, key, TYPE_DIRECT); } } else pathrelse (&path); return 1; } /* next item is item of this file */ if (get_offset (&ih->ih_key) + get_bytes_number(ih, fs->fs_blocksize) != get_offset (next_key)) { /* next item has incorrect offset (hole or overlapping) */ pathrelse (&path); return 0; } if (do_items_have_the_same_type (ih, next_key) == 1 && are_items_in_the_same_node (&path) == 1) { /* two indirect items or two direct items in the same leaf. FIXME: Second will be deleted */ pathrelse (&path); return 0; } /* items are of different types or are in different nodes */ /* if (get_offset (&ih->ih_key) + get_bytes_number (ih, fs->fs_blocksize) != get_offset (next_key)) { // indirect item free space is not set properly if (!is_indirect_ih (ih) ) //|| get_ih_free_space(ih) == 0) fsck_log ("are_file_items_correct: " "item must be indirect and must have invalid free space (%H)", ih); if (fsck_mode (fs) == FSCK_REBUILD) { set_ih_free_space(ih, 0); mark_buffer_dirty (PATH_PLAST_BUFFER (&path)); } } */ /* next item exists */ set_type_and_offset(key_version, key, get_offset (next_key), get_type(next_key)); if (comp_keys (key, next_key)) reiserfs_panic ("are_file_items_correct: Internal tree is in inconsistent state, " "the current item key %K and the next key %K must match", key, next_key); pathrelse (&path); break; case POSITION_NOT_FOUND: /* We always must have next key found. Exception is first byte. It does not have to exist */ if (get_offset (key) != 1) reiserfs_panic ("are_file_items_correct: Position (offset == %llu) in the middle of" "the file %K was not found.", get_offset(key), key); pathrelse (&path); return 0; case FILE_NOT_FOUND: if (get_offset (key) != 1) reiserfs_panic ("are_file_items_correct: File %K must be found as we found its StatData.", key); pathrelse (&path); return 1; case DIRECTORY_FOUND: pathrelse (&path); return -1; } } while (1); die ("are_file_items_correct: Cannot reach here"); return 0; } /* delete all items and put them back (after that file should have correct sequence of items. if should_relocate is specified then it relocates items to a new id. if should_change_ih is specified then the key in ih is changed also. */ void rewrite_file (struct item_head * ih, int should_relocate, int should_change_ih) { struct key key; struct si * si; __u32 new_objectid = 0; int moved_items; struct key old, new; int nothing_else = 0; /* starting with the leftmost one - look for all items of file, store and delete and */ key = ih->ih_key; set_type_and_offset (KEY_FORMAT_1, &key, SD_OFFSET, TYPE_STAT_DATA); si = 0; nothing_else = 0; nothing_else = delete_N_items_after_key (&key, &si, should_relocate /* do not skip dir items */, 10); if (should_relocate && (si || should_change_ih)) { /* get new objectid for relocation or get objectid with which file was relocated already */ new_objectid = objectid_for_relocation (&ih->ih_key); if (should_change_ih) set_key_objectid (&ih->ih_key, new_objectid); if (si) { old = si->si_ih.ih_key; set_key_objectid (&(si->si_ih.ih_key), new_objectid); new = si->si_ih.ih_key; } } moved_items = 0; while (si) { while (si && (nothing_else || si->si_next)) { if (should_relocate) { set_key_objectid (&(si->si_ih.ih_key), new_objectid); moved_items ++; } insert_item_separately (&(si->si_ih), si->si_dnm_data, 1/*was in tree*/); si = remove_saved_item (si); } if (!nothing_else) nothing_else = delete_N_items_after_key (&key, &si, should_relocate /* do not skip dir items */, 10); } if (moved_items) fsck_log ("rewrite_file: %d items of file %K moved to %K\n", moved_items, &old, &new); } /* file must have correct sequence of items and tail must be stored in unformatted pointer; pos in bh is a position of SD */ static int make_file_writeable (struct buffer_head * bh, int pos) /* struct item_head * sd_ih, void * sd */ { struct item_head *sd_ih = B_N_PITEM_HEAD (bh, pos); struct item_head sd_ih_copy; struct stat_data *sd = (struct stat_data *)B_N_PITEM (bh, pos); struct stat_data sd_copy; __u64 size; __u32 blocks; __u16 mode; int retval, symlink; sd_ih_copy = *sd_ih; memcpy (&sd_copy, sd, get_ih_item_len (sd_ih)); get_sd_mode (sd_ih, sd, &mode); symlink = S_ISLNK(mode); if (ih_writable(sd_ih)) return 1; else { mark_ih_writable(sd_ih); mark_buffer_dirty (bh); } retval = are_file_items_correct (&sd_ih_copy, &sd_copy, &size, &blocks, 0/*do not mark accessed*/, &symlink); if (retval == 1) /* file looks correct */ return 1; rewrite_file (sd_ih, 0, 0); /*fsck_data (fs)->rebuild.rewritten ++;*/ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ size = 0; if (are_file_items_correct (&sd_ih_copy, &sd_copy, &size, &blocks, 0/*do not mark accessed*/, &symlink) == 0) { fsck_log("WARNING: file was rewritten but still is not correct %K\n", &sd_ih->ih_key); return -1; } /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ return 1; } /* this inserts __first__ indirect item (having k_offset == 1 and only one unfm pointer) into tree */ static int create_first_item_of_file (struct item_head * ih, char * item, struct path * path, int was_in_tree) { __u32 unfm_ptr; __u32 * ni = 0; struct buffer_head * unbh; struct item_head indih; unsigned int i; int retval; mark_item_unreachable (&indih); copy_key (&(indih.ih_key), &(ih->ih_key)); set_ih_item_len (&indih, UNFM_P_SIZE); if (get_offset (&ih->ih_key) > fs->fs_blocksize) { /* insert indirect item containing 0 unfm pointer */ unfm_ptr = 0; set_ih_free_space (&indih, 0); retval = 0; } else { if (is_direct_ih (ih)) { /* copy direct item to new unformatted node. Save information about it */ int len = get_bytes_number (ih, fs->fs_blocksize); unbh = reiserfsck_get_new_buffer (PATH_PLAST_BUFFER (path)->b_blocknr); memset (unbh->b_data, 0, unbh->b_size); unfm_ptr = cpu_to_le32 (unbh->b_blocknr); memcpy (unbh->b_data + get_offset (&ih->ih_key) - 1, item, len); set_ih_free_space (&indih, fs->fs_blocksize - len - (get_offset (&ih->ih_key) - 1)); mark_ih_was_tail (&indih); mark_buffer_dirty (unbh); mark_buffer_uptodate (unbh, 1); brelse (unbh); retval = len; } else { /* take first unformatted pointer from an indirect item */ //free_sp = ih_get_free_space(0, ih, item); set_ih_item_len (&indih, get_ih_item_len (ih)); ni = getmem (get_ih_item_len (ih)); memcpy (ni, (item), get_ih_item_len (ih)); if (!was_in_tree) { for (i = 0; i < I_UNFM_NUM (ih); i++) { if (still_bad_unfm_ptr_2 (le32_to_cpu (ni[i]))) reiserfs_panic ("create_first_item_of_file: The file %K has a pointer to the bad block (%u)", &ih->ih_key, le32_to_cpu (unfm_ptr)); mark_block_used (le32_to_cpu (ni[i]), 0); } } retval = fs->fs_blocksize * get_ih_item_len (ih) / UNFM_P_SIZE; } } set_ih_key_format (&indih, get_ih_key_format (ih)); //ih_version(&indih) = ih_version(ih); set_offset (key_format (&(ih->ih_key)), &indih.ih_key, 1); set_type (key_format (&(ih->ih_key)), &indih.ih_key, TYPE_INDIRECT); if (ni) { reiserfsck_insert_item (path, &indih, (const char *)ni); freemem (ni); } else { reiserfsck_insert_item (path, &indih, (const char *)&unfm_ptr); } return retval; } /* path points to first part of tail. Function copies file tail into unformatted node and returns its block number. */ /* we convert direct item that is on the path to indirect. we need a number of free block for unformatted node. reiserfs_new_blocknrs will start from block number returned by this function */ static unsigned long block_to_start (struct path * path) { struct buffer_head * bh; struct item_head * ih; bh = PATH_PLAST_BUFFER (path); ih = PATH_PITEM_HEAD (path); if (get_offset(&ih->ih_key) == 1 || PATH_LAST_POSITION (path) == 0) return bh->b_blocknr; ih --; return (B_I_POS_UNFM_POINTER (bh, ih, I_UNFM_NUM (ih) - 1)) ?: bh->b_blocknr; } static void direct2indirect2 (unsigned long unfm, struct path * path) { struct item_head * ih; struct key key; struct buffer_head * unbh; __u32 ni; int copied = 0; int file_format; ih = PATH_PITEM_HEAD (path); copy_key (&key, &(ih->ih_key)); file_format = key_format (&key); if (get_offset (&key) % fs->fs_blocksize != 1) { /* look for first part of tail */ pathrelse (path); set_offset (file_format, &key, (get_offset (&key) & ~(fs->fs_blocksize - 1)) + 1); if (reiserfs_search_by_key_4 (fs, &key, path) != ITEM_FOUND) die ("direct2indirect: can not find first part of tail"); } unbh = reiserfsck_get_new_buffer (le32_to_cpu (unfm) ? le32_to_cpu (unfm) : block_to_start (path)); memset (unbh->b_data, 0, unbh->b_size); /* delete parts of tail coping their contents to new buffer */ do { __u64 len; ih = PATH_PITEM_HEAD (path); len = get_bytes_number(ih, fs->fs_blocksize); memcpy (unbh->b_data + copied, B_I_PITEM (PATH_PLAST_BUFFER (path), ih), len); // save_unfm_overwriting (unbh->b_blocknr, ih); copied += len; set_offset (file_format, &key, get_offset (&key) + len); reiserfsck_delete_item (path, 0); } while (reiserfs_search_by_key_4 (fs, &key, path) == ITEM_FOUND); pathrelse (path); /* paste or insert pointer to the unformatted node */ set_offset (file_format, &key, get_offset (&key) - copied); // set_offset (ih_key_format (ih), &key, get_offset (&key) - copied); // key.k_offset -= copied; ni = cpu_to_le32 (unbh->b_blocknr); if (usearch_by_position (fs, &key, file_format, path) == FILE_NOT_FOUND) { struct item_head insih; copy_key (&(insih.ih_key), &key); set_ih_key_format (&insih, file_format); set_type (get_ih_key_format (&insih), &insih.ih_key, TYPE_INDIRECT); set_ih_free_space (&insih, 0); mark_item_unreachable (&insih); set_ih_item_len (&insih, UNFM_P_SIZE); mark_ih_was_tail (&insih); reiserfsck_insert_item (path, &insih, (const char *)&(ni)); } else { ih = PATH_PITEM_HEAD (path); if (!is_indirect_ih(ih)) reiserfs_panic ("%s: The item, which is supposed to be deleted, found in the tree - %k", __FUNCTION__, &ih->ih_key); if (get_bytes_number (ih, fs->fs_blocksize) + get_offset (&ih->ih_key) != get_offset (&key)) reiserfs_panic ("%s: The item %k with the wrong offset found in the block %lu block", __FUNCTION__, &ih->ih_key, PATH_PLAST_BUFFER(path)->b_blocknr); mark_ih_was_tail (ih); mark_buffer_dirty (get_bh(path)); reiserfsck_paste_into_item (path, (const char *)&ni, UNFM_P_SIZE); } mark_buffer_dirty (unbh); mark_buffer_uptodate (unbh, 1); brelse (unbh); if (usearch_by_position (fs, &key, file_format, path) != POSITION_FOUND || !is_indirect_ih (PATH_PITEM_HEAD (path))) reiserfs_panic ("direct2indirect: The data %k, which are supposed to be converted, are not found", &key); return; } static int append_to_unformatted_node (struct item_head * comingih, struct item_head * ih, char * item, struct path * path, unsigned int coming_len) { struct buffer_head * bh, * unbh = NULL; __u64 end_of_data, free_space; __u16 offset = get_offset (&comingih->ih_key) % fs->fs_blocksize - 1; __u32 unfm_ptr; int zero_number; bh = PATH_PLAST_BUFFER (path); unfm_ptr = le32_to_cpu (B_I_POS_UNFM_POINTER (bh, ih, I_UNFM_NUM (ih) - 1)); /* append to free space of the last unformatted node of indirect item ih */ free_space = get_offset (&ih->ih_key) + fs->fs_blocksize * I_UNFM_NUM (ih) - get_offset (&comingih->ih_key); if (free_space < coming_len) reiserfs_panic ("%s: block %lu: The unformatted node %u, pointed by the file %k, does not have enough free space" "for appending %llu bytes", __FUNCTION__, bh->b_blocknr, unfm_ptr, &ih->ih_key, coming_len); if (fs->fs_blocksize < free_space) reiserfs_panic ("%s: block %lu: The unformatted node %u, pointed by the file %k, does not have enough free space" "for appending %llu bytes", __FUNCTION__, bh->b_blocknr, &ih->ih_key, unfm_ptr, &ih->ih_key, coming_len); end_of_data = fs->fs_blocksize - free_space; zero_number = offset - end_of_data; if (unfm_ptr && !not_data_block (fs, unfm_ptr)) { unbh = bread (fs->fs_dev, unfm_ptr, fs->fs_blocksize); if (!is_block_used (unfm_ptr)) reiserfs_panic ("%s: block %lu: The unformatted node %u, pointed by the file %k, is marked as unused", __FUNCTION__, bh->b_blocknr, unfm_ptr, &ih->ih_key); if (unbh == 0) unfm_ptr = 0; } if (!unfm_ptr || not_data_block (fs, unfm_ptr)) { /* indirect item points to block which can not be pointed or to 0, in any case we have to allocate new node */ /*if (unfm_ptr == 0 || unfm_ptr >= SB_BLOCK_COUNT (fs)) {*/ unbh = reiserfsck_get_new_buffer (bh->b_blocknr); memset (unbh->b_data, 0, unbh->b_size); B_I_POS_UNFM_POINTER (bh, ih, I_UNFM_NUM (ih) - 1) = unbh->b_blocknr; /*mark_block_unformatted (unbh->b_blocknr);*/ mark_buffer_dirty (bh); } memset (unbh->b_data + end_of_data, 0, zero_number); memcpy (unbh->b_data + offset, item, coming_len); // save_unfm_overwriting (unbh->b_blocknr, comingih); free_space -= (zero_number + coming_len); set_ih_free_space(ih, get_ih_free_space(ih) - (zero_number + coming_len)); memset (unbh->b_data + offset + coming_len, 0, free_space); // mark_buffer_uptodate (unbh, 0); mark_buffer_uptodate (unbh, 1); mark_buffer_dirty (unbh); brelse (unbh); pathrelse (path); return coming_len; } /* this appends file with one unformatted node pointer (since balancing algorithm limitation). This pointer can be 0, or new allocated block or pointer from indirect item that is being inserted into tree */ int reiserfsck_append_file (struct item_head * comingih, char * item, int pos, struct path * path, int was_in_tree) { __u32 * ni; struct buffer_head * unbh; int retval; struct item_head * ih = PATH_PITEM_HEAD (path); __u32 bytes_number; int i, count = 0; if (!is_indirect_ih (ih)) reiserfs_panic ("reiserfsck_append_file: Operation is not allowed for non-indirect item %k", &ih->ih_key); if (is_direct_ih (comingih)) { unsigned int coming_len = get_bytes_number (comingih, fs->fs_blocksize); if (get_offset (&comingih->ih_key) < get_offset (&ih->ih_key) + fs->fs_blocksize * I_UNFM_NUM (ih)) { /* direct item fits to free space of indirect item */ return append_to_unformatted_node (comingih, ih, item, path, coming_len); } unbh = reiserfsck_get_new_buffer (PATH_PLAST_BUFFER (path)->b_blocknr); memset (unbh->b_data, 0, unbh->b_size); memcpy (unbh->b_data + get_offset (&comingih->ih_key) % unbh->b_size - 1, item, coming_len); mark_buffer_dirty (unbh); mark_buffer_uptodate (unbh, 1); ni = getmem (UNFM_P_SIZE); *ni = cpu_to_le32 (unbh->b_blocknr); count = 1; brelse (unbh); retval = coming_len; } else { /* coming item is indirect item */ bytes_number = get_bytes_number (ih, fs->fs_blocksize); if (get_offset (&comingih->ih_key) + pos * fs->fs_blocksize != get_offset (&ih->ih_key) + bytes_number) reiserfs_panic ("reiserfsck_append_file: file %K: Cannot append indirect pointers of the offset " "(%LLu) at the position %LLu\n", &comingih->ih_key, get_offset (&comingih->ih_key) + pos * fs->fs_blocksize, get_offset (&ih->ih_key) + bytes_number); /* take unformatted pointer from an indirect item */ count = I_UNFM_NUM(comingih) - pos; ni = getmem (count * UNFM_P_SIZE); memcpy (ni, (item + pos * UNFM_P_SIZE), count * UNFM_P_SIZE); if (!was_in_tree) { for (i = 0; i < count; i++ ) { if (still_bad_unfm_ptr_2 (le32_to_cpu (ni[i]))) die ("reiserfsck_append_file: Trying to insert a pointer to illegal block (%u)", le32_to_cpu (ni[i])); mark_block_used (le32_to_cpu (ni[i]), 0); } } retval = fs->fs_blocksize * count; } reiserfsck_paste_into_item (path, (const char *)ni, count * UNFM_P_SIZE); freemem (ni); return retval; } int must_there_be_a_hole (struct item_head * comingih, struct path * path) { struct item_head * ih = PATH_PITEM_HEAD (path); if (is_direct_ih (ih)) { direct2indirect2 (0, path); ih = PATH_PITEM_HEAD (path); } path->pos_in_item = I_UNFM_NUM (ih); return (get_offset (&comingih->ih_key) - get_offset (&ih->ih_key)) / fs->fs_blocksize - I_UNFM_NUM (ih); /* if (get_offset (&ih->ih_key) + (I_UNFM_NUM (ih) + 1) * fs->fs_blocksize <= get_offset (&comingih->ih_key)) return 1; return 0;*/ } int reiserfs_append_zero_unfm_ptr (struct path * path, int p_count) { __u32 * ni; int count; if (is_direct_ih (PATH_PITEM_HEAD (path))) /* convert direct item to indirect */ direct2indirect2 (0, path); count = MAX_INDIRECT_ITEM_LEN (fs->fs_blocksize) / UNFM_P_SIZE; if (p_count <= count) count = p_count; ni = getmem (count * UNFM_P_SIZE); memset (ni, 0, count * UNFM_P_SIZE); reiserfsck_paste_into_item (path, (const char *)ni, count * UNFM_P_SIZE); freemem(ni); return 0; } /* write direct item to unformatted node */ /* coming item is direct */ static int overwrite_by_direct_item (struct item_head * comingih, char * item, struct path * path) { __u32 unfm_ptr; struct buffer_head * unbh, * bh; struct item_head * ih; int offset; __u64 coming_len = get_bytes_number (comingih, fs->fs_blocksize); bh = PATH_PLAST_BUFFER (path); ih = PATH_PITEM_HEAD (path); unfm_ptr = le32_to_cpu (B_I_POS_UNFM_POINTER (bh, ih, path->pos_in_item)); unbh = 0; if (unfm_ptr != 0 && unfm_ptr < get_sb_block_count (fs->fs_ondisk_sb)) { /**/ unbh = bread (fs->fs_dev, unfm_ptr, bh->b_size); if (!is_block_used (unfm_ptr)) die ("overwrite_by_direct_item: block %lu, item %d, pointer %d: The pointed block" "(%u) being overwritten is marked as unused.", bh->b_blocknr, PATH_LAST_POSITION(path), path->pos_in_item, unfm_ptr); if (unbh == 0) unfm_ptr = 0; } if (unfm_ptr == 0 || unfm_ptr >= get_sb_block_count (fs->fs_ondisk_sb)) { if ((unbh = reiserfsck_get_new_buffer (bh->b_blocknr)) != NULL) { memset (unbh->b_data, 0, unbh->b_size); B_I_POS_UNFM_POINTER (bh, ih, path->pos_in_item) = cpu_to_le32 (unbh->b_blocknr); mark_buffer_dirty (bh); } else { die ("overwrite_by_direct_item: Could not allocate a new block for new data"); } } offset = (get_offset (&comingih->ih_key) % bh->b_size) - 1; if (offset + coming_len > bh->b_size) die ("overwrite_by_direct_item: The length of the file after insertion (offset=%lu, length=%u)" "will exceed the maximal possible length.", ( long unsigned ) get_offset (&comingih->ih_key), ( unsigned ) coming_len); memcpy (unbh->b_data + offset, item, coming_len); // save_unfm_overwriting (unbh->b_blocknr, comingih); if ((path->pos_in_item == (I_UNFM_NUM (ih) - 1)) && (bh->b_size - 0/*ih_free_space (ih)*/) < (offset + coming_len)) { set_ih_free_space (ih, bh->b_size - (offset + coming_len)) ; mark_buffer_dirty (bh); } mark_buffer_dirty (unbh); // mark_buffer_uptodate (unbh, 0); mark_buffer_uptodate (unbh, 1); brelse (unbh); return coming_len; } #if 0 void overwrite_unfm_by_unfm (unsigned long unfm_in_tree, unsigned long coming_unfm, int bytes_in_unfm) { struct overwritten_unfm_segment * unfm_os_list;/* list of overwritten segments of the unformatted node */ struct overwritten_unfm_segment unoverwritten_segment; struct buffer_head * bh_in_tree, * coming_bh; if (!test_bit (coming_unfm % (fs->fs_blocksize * 8), SB_AP_BITMAP (fs)[coming_unfm / (fs->fs_blocksize * 8)]->b_data)) /* block (pointed by indirect item) is free, we do not have to keep its contents */ return; /* coming block is marked as used in disk bitmap. Put its contents to block in tree preserving everything, what has been overwritten there by direct items */ unfm_os_list = find_overwritten_unfm (unfm_in_tree, bytes_in_unfm, &unoverwritten_segment); if (unfm_os_list) { /* add_event (UNFM_OVERWRITING_UNFM);*/ bh_in_tree = bread (fs->fs_dev, unfm_in_tree, fs->fs_blocksize); coming_bh = bread (fs->fs_dev, coming_unfm, fs->fs_blocksize); if (bh_in_tree == 0 || coming_bh == 0) return; while (get_unoverwritten_segment (unfm_os_list, &unoverwritten_segment)) { if (unoverwritten_segment.ous_begin < 0 || unoverwritten_segment.ous_end > bytes_in_unfm - 1 || unoverwritten_segment.ous_begin > unoverwritten_segment.ous_end) die ("overwrite_unfm_by_unfm: invalid segment found (%d %d)", unoverwritten_segment.ous_begin, unoverwritten_segment.ous_end); memcpy (bh_in_tree->b_data + unoverwritten_segment.ous_begin, coming_bh->b_data + unoverwritten_segment.ous_begin, unoverwritten_segment.ous_end - unoverwritten_segment.ous_begin + 1); mark_buffer_dirty (bh_in_tree); } brelse (bh_in_tree); brelse (coming_bh); } } #endif /* put unformatted node pointers from incoming item over the in-tree ones */ static int overwrite_by_indirect_item (struct item_head * comingih, __u32 * coming_item, struct path * path, int * pos_in_coming_item) { struct buffer_head * bh = PATH_PLAST_BUFFER (path); struct item_head * ih = PATH_PITEM_HEAD (path); int written; __u32 * item_in_tree; int src_unfm_ptrs, dest_unfm_ptrs, to_copy, i, dirty = 0; item_in_tree = (__u32 *)B_I_PITEM (bh, ih) + path->pos_in_item; coming_item += *pos_in_coming_item; dest_unfm_ptrs = I_UNFM_NUM (ih) - path->pos_in_item; src_unfm_ptrs = I_UNFM_NUM (comingih) - *pos_in_coming_item; if (dest_unfm_ptrs >= src_unfm_ptrs) { /* whole coming item (comingih) fits into item in tree (ih) starting with path->pos_in_item */ //free_sp = ih_get_free_space(0, comingih, (char *)coming_item); written = get_bytes_number (comingih, fs->fs_blocksize) - /* free_sp - */ *pos_in_coming_item * fs->fs_blocksize; *pos_in_coming_item = I_UNFM_NUM (comingih); to_copy = src_unfm_ptrs; if (dest_unfm_ptrs == src_unfm_ptrs) set_ih_free_space(ih, 0 /* free_sp */ ); } else { /* only part of coming item overlaps item in the tree */ *pos_in_coming_item += dest_unfm_ptrs; written = dest_unfm_ptrs * fs->fs_blocksize; to_copy = dest_unfm_ptrs; set_ih_free_space(ih, 0); } for (i = 0; i < to_copy; i ++) { if (coming_item[i] != 0 && item_in_tree[i] == 0) { /* overwrite holes only by correct a pointer in the coming item which must be correct */ item_in_tree[i] = coming_item[i]; mark_block_used (le32_to_cpu (coming_item[i]), 0); dirty ++; } } if (dirty) mark_buffer_dirty (bh); return written; } static int reiserfsck_overwrite_file (struct item_head * comingih, char * item, struct path * path, int * pos_in_coming_item, int was_in_tree) { __u32 unfm_ptr; int written = 0; struct item_head * ih = PATH_PITEM_HEAD (path); if (not_of_one_file (ih, &(comingih->ih_key))) reiserfs_panic ("reiserfsck_overwrite_file: The file to be overwritten %K must be of" " the same as the new data %K", &ih->ih_key, &comingih->ih_key); if (is_direct_ih (ih)) { unfm_ptr = 0; if (is_indirect_ih (comingih)) { if (get_offset (&ih->ih_key) % fs->fs_blocksize != 1) reiserfs_panic ("reiserfsck_overwrite_file: The second part of the tail %k can not" " be overwritten by indirect item %k", &ih->ih_key, &comingih->ih_key); /* use pointer from coming indirect item */ unfm_ptr = le32_to_cpu (*(__u32 *)(item + *pos_in_coming_item * UNFM_P_SIZE)); if (!was_in_tree) { if (still_bad_unfm_ptr_2 (unfm_ptr)) die ("reiserfsck_overwrite_file: The pointer to the unformatted block (%u)" " points to the bad area.", unfm_ptr); } } /* */ direct2indirect2 (unfm_ptr, path); } if (is_direct_ih (comingih)) { written = overwrite_by_direct_item (comingih, item, path); } else { if (was_in_tree) reiserfs_panic ("reiserfsck_overwrite_file: Item %k we are going to overwrite with" " %k cannot not be in the tree yet", &ih->ih_key, &comingih->ih_key); written = overwrite_by_indirect_item (comingih, (__u32 *)item, path, pos_in_coming_item); } return written; } /* */ int reiserfsck_file_write (struct item_head * ih, char * item, int was_in_tree) { struct path path; int count, pos_in_coming_item; int retval, written; struct key key; int file_format = KEY_FORMAT_UNDEFINED; int relocated = 0; if (!was_in_tree) { __u16 mode; /* We already inserted all SD items. If we cannot find SD of this item - skip it */ memset (&key, 0, sizeof (key)); check_again: copy_short_key (&key, &(ih->ih_key)); if (reiserfs_search_by_key_4 (fs, &key, &path) != ITEM_FOUND) { fsck_log ("vpf-10260: The file we are inserting the new item (%H) into has no" " StatData, insertion was skipped\n", ih); pathrelse (&path); return 0; } /*SD found*/ file_format = get_ih_key_format (get_ih(&path)); get_sd_mode (get_ih(&path), get_item(&path), &mode); if (file_format != get_ih_key_format (ih)) { /* Not for symlinks and not for items which should be relocted. */ if (((S_ISDIR(mode) && is_direntry_ih(ih)) || (!S_ISDIR(mode) && !is_direntry_ih(ih))) && !S_ISLNK(mode)) { set_type_and_offset (file_format, &ih->ih_key, get_offset (&ih->ih_key), get_type (&ih->ih_key)); set_ih_key_format(ih, file_format); } } if (!relocated && should_relocate (ih)) { rewrite_file (ih, 1, 1/*change new_ih*/); pathrelse(&path); relocated = 1; /* object has been relocated but we should not mark it as used in semantic map, as it does not exist at pass2 and we do not get here for relocation as was_in_tree == 1 */ goto check_again; } if (make_file_writeable (get_bh(&path), get_item_pos (&path)) == -1) { /* write was not completed. Skip that item. Maybe it should be saved to lost_found */ fsck_log ("reiserfsck_file_write: WARNING: The file we are inserting the new item %k into was" " not recovered and is still in inconsistent state, insertion was skipped\n", &ih->ih_key); pathrelse(&path); return 0; } pathrelse (&path); } count = get_bytes_number (ih, fs->fs_blocksize); pos_in_coming_item = 0; copy_key (&key, &(ih->ih_key)); while (count) { retval = usearch_by_position (fs, &key, key_format (&key), &path); /* if there are items of bigger offset than we are looking for and there is no item between wamted offset and SD, insert first item */ if (retval == POSITION_NOT_FOUND && ( PATH_LAST_POSITION (&path) >= B_NR_ITEMS (get_bh(&path)) || get_offset (&get_ih(&path)->ih_key) > get_offset (&key))) retval = FILE_NOT_FOUND; if (retval == DIRECTORY_FOUND) reiserfs_panic ("The directory was found at the place of the file we are going to insert" " the item %k into", key); if (retval == POSITION_FOUND) { written = reiserfsck_overwrite_file (ih, item, &path, &pos_in_coming_item, was_in_tree); count -= written; set_offset (key_format (&key), &key, get_offset (&key) + written); } if (retval == FILE_NOT_FOUND) { written = create_first_item_of_file (ih, item, &path, was_in_tree); count -= written; set_offset (key_format (&key), &key, get_offset (&key) + written ); } if (retval == POSITION_NOT_FOUND) { if (is_direct_ih (ih)) { mark_ih_was_tail (get_ih(&path)); mark_buffer_dirty (get_bh(&path)); } if ((written = must_there_be_a_hole (ih, &path)) > 0) { reiserfs_append_zero_unfm_ptr (&path, written); }else { written = reiserfsck_append_file (ih, item, pos_in_coming_item, &path, was_in_tree); count -= written; set_offset (key_format (&key), &key, get_offset (&key) + written); pos_in_coming_item += written / fs->fs_blocksize; } } if (count < 0) reiserfs_panic ("reiserfsck_file_write: We wrote into the file %K more bytes than needed - count (%d) < 0.", &key, count); pathrelse (&path); } /* This is a test for writing into the file. If not sure that file data are consistent after reiserfsck_file_write - uncomment this clause: */ /* if (!was_in_tree && are_file_items_correct (&ih->ih_key, (file_format == KEY_FORMAT_UNDEFINED) ? get_ih_key_format (ih) : file_format, &size, &blocks, 0, symlink, 0) == 0) reiserfs_panic ("reiserfsck_file_write: item was not inserted properly\n");*/ return get_bytes_number (ih, fs->fs_blocksize); } void one_more_corruption(reiserfs_filsys_t *fs, int kind) { if (kind == FATAL) fsck_check_stat (fs)->fatal_corruptions++; else if (kind == FIXABLE) fsck_check_stat (fs)->fixable_corruptions++; } void one_less_corruption(reiserfs_filsys_t *fs, int kind) { if (kind == FATAL) fsck_check_stat (fs)->fatal_corruptions--; else if (kind == FIXABLE) fsck_check_stat (fs)->fixable_corruptions--; } reiserfsprogs-3.6.9/fsck/semantic_check.c0000444000077100007710000005766107705265615014177 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by reiserfsprogs/README */ #include "fsck.h" static struct key *trunc_links = NULL; static __u32 links_num = 0; int wrong_mode (struct key * key, __u16 * mode, __u64 real_size, int symlink); int wrong_st_blocks(struct key * key, __u32 * blocks, __u32 sd_blocks, __u16 mode, int new_format); int wrong_st_size (struct key * key, unsigned long long max_file_size, int blocksize, __u64 * size, __u64 sd_size, int type); int wrong_first_direct_byte (struct key * key, int blocksize, __u32 * first_direct_byte, __u32 sd_first_direct_byte, __u32 size); void get_object_key (struct reiserfs_de_head * deh, struct key * key, struct key * entry_key, struct item_head * ih); void print_name (char * name, int len); void erase_name (int len); struct path_key { struct short_key { __u32 k_dir_id; __u32 k_objectid; } key; struct path_key * next, * prev; }; struct path_key * head_key = NULL; struct path_key * tail_key = NULL; static int check_path_key(struct key * key) { struct path_key * cur = head_key; while(cur != NULL) { if (!comp_short_keys(&cur->key, key)) { fsck_log("\nsemantic check: The directory %k has 2 names.", key); return LOOP_FOUND; } cur = cur->next; } return 0; } static int add_path_key(struct key * key) { if (check_path_key(key)) return LOOP_FOUND; if (tail_key == NULL) { tail_key = getmem(sizeof(struct path_key)); head_key = tail_key; tail_key->prev = NULL; }else{ tail_key->next = getmem(sizeof(struct path_key)); tail_key->next->prev = tail_key; tail_key = tail_key->next; } copy_short_key (&tail_key->key, key); tail_key->next = NULL; return 0; } void del_path_key() { if (tail_key == NULL) die("Wrong path_key structure"); if (tail_key->prev == NULL) { freemem(tail_key); tail_key = head_key = NULL; }else{ tail_key = tail_key->prev; freemem(tail_key->next); tail_key->next = NULL; } } /* path is path to stat data. If file will be relocated - new_ih will contain a key file was relocated with */ static int check_check_regular_file (struct path * path, void * sd, struct item_head * new_ih) { int is_new_file; // struct key key, sd_key; __u16 mode; __u32 nlink; __u64 real_size, sd_size; __u32 blocks, sd_blocks; /* proper values and value in stat data */ __u32 first_direct_byte, sd_first_direct_byte; struct item_head * ih, sd_ih; int fix_sd; int symlnk = 0; int retval = OK; __u32 tmp_position; ih = get_ih (path); if (new_ih) { /* this objectid is used already */ *new_ih = *ih; pathrelse (path); rewrite_file (new_ih, 1, 1); linked_already(&new_ih->ih_key); one_less_corruption (fs, FIXABLE); sem_pass_stat (fs)->oid_sharing_files_relocated ++; retval = RELOCATED; if (reiserfs_search_by_key_4 (fs, &(new_ih->ih_key), path) == ITEM_NOT_FOUND) reiserfs_panic ("check_check_regular_file: Could not find a StatData of " "the relocated file %K", &new_ih->ih_key); /* stat data is marked unreachable again due to relocation, fix that */ ih = get_ih (path); sd = get_item (path); } if (get_ih_item_len (ih) == SD_SIZE) is_new_file = 1; else is_new_file = 0; get_sd_nlink (ih, sd, &nlink); get_sd_mode (ih, sd, &mode); get_sd_size (ih, sd, &sd_size); get_sd_blocks (ih, sd, &sd_blocks); /* if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { // check and set nlink first nlink ++; set_sd_nlink (ih, sd, &nlink); mark_buffer_dirty (bh); if (nlink > 1) return OK; } */ if (!is_new_file) get_sd_first_direct_byte (ih, sd, &sd_first_direct_byte); if (S_ISLNK (mode)) symlnk = 1; sd_ih = *ih; // sd_key = sd_ih.ih_key; pathrelse (path); if (are_file_items_correct (&sd_ih, sd, &real_size, &blocks, 0/* do not mark reachable */, &symlnk) != 1) { one_more_corruption (fs, FATAL); fsck_log ("check_regular_file: The file %K with the corrupted structure found\n", &sd_ih.ih_key); } else { fix_sd = 0; fix_sd += wrong_mode (&sd_ih.ih_key, &mode, real_size, symlnk); if (!is_new_file) fix_sd += wrong_first_direct_byte (&sd_ih.ih_key, fs->fs_blocksize, &first_direct_byte, sd_first_direct_byte, real_size); if (reiserfs_bin_search(&sd_ih.ih_key, trunc_links, links_num, sizeof(sd_ih.ih_key), &tmp_position, comp_short_keys) != POSITION_FOUND) { fix_sd += wrong_st_size (&sd_ih.ih_key, is_new_file ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1, fs->fs_blocksize, &real_size, sd_size, symlnk ? TYPE_SYMLINK : 0); } else { real_size = sd_size; } fix_sd += wrong_st_blocks (&sd_ih.ih_key, &blocks, sd_blocks, mode, is_new_file); if (fix_sd) { if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { struct buffer_head * bh; /* find stat data and correct it */ set_type_and_offset (KEY_FORMAT_1, &sd_ih.ih_key, SD_OFFSET, TYPE_STAT_DATA); if (reiserfs_search_by_key_4 (fs, &sd_ih.ih_key, path) != ITEM_FOUND) { fsck_log ("check_regular_file: A StatData of the file %K cannot be " "found\n", &sd_ih.ih_key); one_more_corruption (fs, FATAL); return STAT_DATA_NOT_FOUND; } bh = get_bh (path); ih = get_ih (path); sd = get_item (path); set_sd_size (ih, sd, &real_size); set_sd_blocks (ih, sd, &blocks); set_sd_mode (ih, sd, &mode); if (!is_new_file) set_sd_first_direct_byte (ih, sd, &first_direct_byte); mark_buffer_dirty (bh); } else { fsck_check_stat (fs)->fixable_corruptions += fix_sd; } } } return retval; } /* returns buffer, containing found directory item.*/ static char * get_next_directory_item ( struct key * key, /* on return this will contain key of next item in the tree */ struct key * parent, struct item_head * ih, __u32 * pos_in_item, int dir_format) { INITIALIZE_PATH (path); char * dir_item; struct key * rdkey; struct buffer_head * bh; struct reiserfs_de_head * deh; int i; int retval; start_again: retval = reiserfs_search_by_entry_key (fs, key, &path); if (retval != POSITION_FOUND && get_offset (key) != DOT_OFFSET) reiserfs_panic ("get_next_directory_item: The current directory %k cannot be found", key); /* leaf containing directory item */ bh = PATH_PLAST_BUFFER (&path); *pos_in_item = path.pos_in_item; *ih = *get_ih (&path); deh = B_I_DEH (bh, ih); /* position was not found for '.' or there is no '..' */ if (retval != POSITION_FOUND || ((get_offset (key) == DOT_OFFSET) && (get_ih_entry_count (ih) < 2 || name_in_entry_length (ih, deh + 1, 1) != 2 || strncmp (name_in_entry (deh + 1, 1), "..", 2)))) { fsck_log ("get_next_directory_item: The %s %k cannot be found in %k", (retval == POSITION_NOT_FOUND) ? "entry" : "directory", key, &ih->ih_key); if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { /* add "." and ".." exist */ pathrelse (&path); reiserfs_add_entry (fs, key, ".", name_length (".", dir_format), key, 0); reiserfs_add_entry (fs, key, "..", name_length ("..", dir_format), parent, 0); fsck_log (" - entry was added\n"); goto start_again; } else { one_more_corruption (fs, FIXABLE); fsck_log ("\n"); if (retval == DIRECTORY_NOT_FOUND) return 0; } } /* make sure, that ".." exists as well */ /* if (get_offset (key) == DOT_OFFSET) { if (get_ih_entry_count (ih) < 2 || name_in_entry_length (ih, deh + 1, 1) != 2 || strncmp (name_in_entry (deh + 1, 1), "..", 2)) { fsck_log ("get_next_directory_item: \"..\" not found in %H\n", ih); pathrelse (&path); return 0; } } */ /* mark hidden entries as visible, set "." and ".." correctly */ deh += *pos_in_item; for (i = *pos_in_item; i < get_ih_entry_count (ih); i ++, deh ++) { /* int namelen; char * name; name = name_in_entry (deh, i); namelen = name_in_entry_length (ih, deh, i); if (de_hidden (deh)) // handled in check_tree reiserfs_panic ("get_next_directory_item: item %k: hidden entry %d \'%.*s\'\n", key, i, namelen, name); */ if (get_deh_offset (deh) == DOT_OFFSET) { if (not_of_one_file (&(deh->deh2_dir_id), key)) { /* "." must point to the directory it is in */ //deh->deh_objectid != REISERFS_ROOT_PARENT_OBJECTID)/*????*/ { fsck_log ("get_next_directory_item: The entry \".\" of the directory %K " "pointes to %K, instead of %K", key, (struct key *)(&(deh->deh2_dir_id)), key); if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { set_deh_dirid (deh, get_key_dirid (key)); set_deh_objectid (deh, get_key_objectid (key)); mark_buffer_dirty (bh); fsck_log (" - corrected\n"); } else fsck_log ("\n"); } } if (get_deh_offset (deh) == DOT_DOT_OFFSET) { /* set ".." so that it points to the correct parent directory */ if (comp_short_keys (&(deh->deh2_dir_id), parent)) { fsck_log ("get_next_directory_item: The entry \"..\" of the directory %K " "pointes to %K, instead of %K", key, (struct key *)(&(deh->deh2_dir_id))); if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { set_deh_dirid (deh, get_key_dirid (parent)); set_deh_objectid (deh, get_key_objectid (parent)); mark_buffer_dirty (bh); fsck_log (" - corrected\n"); } else fsck_log ("\n"); } } } /* copy directory item to the temporary buffer */ dir_item = getmem (get_ih_item_len (ih)); memcpy (dir_item, B_I_PITEM (bh, ih), get_ih_item_len (ih)); /* next item key */ if (PATH_LAST_POSITION (&path) == (B_NR_ITEMS (bh) - 1) && (rdkey = uget_rkey (&path))) copy_key (key, rdkey); else { set_key_dirid (key, 0); set_key_objectid (key, 0); } if (fsck_mode (fs) == FSCK_REBUILD) mark_item_reachable (get_ih (&path), bh); pathrelse (&path); return dir_item; } /* semantic pass of --check */ static int check_semantic_pass (struct key * key, struct key * parent, int dot_dot, struct item_head * new_ih) { struct path path; void * sd; __u32 nlink; int is_new_dir; struct buffer_head * bh; struct item_head * ih; int retval; char * dir_item; __u32 pos_in_item; struct item_head tmp_ih; struct key next_item_key, entry_key, object_key; __u64 dir_size = 0; __u32 blocks; __u64 sd_size; __u32 sd_blocks; int fix_sd; /*int relocate;*/ int dir_format = 0; __u16 mode; retval = OK; /* start_again: when directory was relocated */ if (!KEY_IS_STAT_DATA_KEY (key)) { fsck_log ("check_semantic_pass: The key %k must be key of a StatData\n", key); one_more_corruption (fs, FATAL); return STAT_DATA_NOT_FOUND; } /* look for stat data of an object */ if (reiserfs_search_by_key_4 (fs, key, &path) == ITEM_NOT_FOUND) { pathrelse (&path); return STAT_DATA_NOT_FOUND; } /* stat data has been found */ ih = get_ih (&path); sd = get_item(&path); get_sd_nlink (ih, sd, &nlink); /* It seems quite difficult to relocate objects on fix-fixable - * rewrite_file calls reiserfs_file_write which can convert tails * to unfm, plus unreachable, was_tail flags, etc. */ if ((/* relocate = */ should_be_relocated(&ih->ih_key))) { /* if (fsck_mode(fs) == FSCK_CHECK) relocate = 0; */ one_more_corruption(fs, FATAL); } if (fix_obviously_wrong_sd_mode (&path)) { one_more_corruption (fs, FIXABLE); pathrelse (&path); return OK; } if (nlink == 0) { fsck_log ("%s: block %lu: The StatData %k has bad nlink number (%u)\n", __FUNCTION__, get_bh(&path)->b_blocknr, &ih->ih_key, nlink); one_more_corruption (fs, FATAL); } if (not_a_directory (sd)) { fsck_check_stat (fs)->files ++; retval = check_check_regular_file (&path, sd, /* relocate ? new_ih : */ 0); pathrelse (&path); return retval; } /* if (relocate) { if (!new_ih) reiserfs_panic ("check_semantic_pass: Memory is not prepared for relocation of " "%K", &ih->ih_key); *new_ih = *ih; pathrelse (&path); sem_pass_stat (fs)->oid_sharing_dirs_relocated ++; relocate_dir (new_ih, 1); linked_already(&new_ih->ih_key); one_less_corruption (fs, FIXABLE); *key = new_ih->ih_key; retval = RELOCATED; goto start_again; } */ /* if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { // it looks like stat data of a directory found if (nlink) { // we saw this directory already if (!dot_dot) { // this name is not ".." - and hard links are not allowed on directories pathrelse (&path); return STAT_DATA_NOT_FOUND; } else { // ".." found nlink ++; set_sd_nlink (ih, sd, &nlink); mark_buffer_dirty (get_bh (&path)); pathrelse (&path); return OK; } } // do not run it for dot_dot on check at all nlink = 2; if (get_key_objectid (key) == REISERFS_ROOT_OBJECTID) nlink ++; set_sd_nlink (ih, sd, &nlink); mark_buffer_dirty (get_bh (&path)); } */ /* directory stat data found */ if (get_ih_item_len (ih) == SD_SIZE) is_new_dir = 1; else is_new_dir = 0; /* save stat data's size and st_blocks */ get_sd_size (ih, sd, &sd_size); get_sd_blocks (ih, sd, &sd_blocks); get_sd_mode (ih, sd, &mode); dir_format = (get_ih_item_len (get_ih (&path)) == SD_SIZE) ? KEY_FORMAT_2 : KEY_FORMAT_1; /* release path pointing to stat data */ pathrelse (&path); fsck_check_stat (fs)->dirs ++; set_key_dirid (&next_item_key, get_key_dirid (key)); set_key_objectid (&next_item_key, get_key_objectid (key)); set_key_offset_v1 (&next_item_key, DOT_OFFSET); set_key_uniqueness (&next_item_key, DIRENTRY_UNIQUENESS); dir_size = 0; while ((dir_item = get_next_directory_item (&next_item_key, parent, &tmp_ih, &pos_in_item, dir_format)) != 0) { /* dir_item is copy of the item in separately allocated memory, item_key is a key of next item in the tree */ int i; char * name = 0; int namelen, entry_len; struct reiserfs_de_head * deh = (struct reiserfs_de_head *)dir_item + pos_in_item; for (i = pos_in_item; i < get_ih_entry_count (&tmp_ih); i ++, deh ++) { struct item_head relocated_ih; int ret = OK; if (name) { free (name); name = 0; } namelen = name_in_entry_length (&tmp_ih, deh, i); asprintf (&name, "%.*s", namelen, name_in_entry (deh, i)); entry_len = entry_length (&tmp_ih, deh, i); get_object_key (deh, &object_key, &entry_key, &tmp_ih); if ((dir_format == KEY_FORMAT_2) && (entry_len % 8 != 0)) { /* not alighed directory of new format - delete it */ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { fsck_log ("Entry %K (\"%.*s\") in the directory %K is not formated " "properly - deleted\n", (struct key *)&(deh->deh2_dir_id), namelen, name, &tmp_ih.ih_key); reiserfs_remove_entry (fs, &entry_key); entry_len = name_length (name, dir_format); reiserfs_add_entry (fs, key, name, entry_len, (struct key *)&(deh->deh2_dir_id), 0); } else { fsck_log ("Entry %K (\"%.*s\") in the directory %K is not formated " "properly.\n", (struct key *)&(deh->deh2_dir_id), namelen, name, &tmp_ih.ih_key); one_more_corruption (fs, FIXABLE); } } print_name (name, namelen); if (!is_properly_hashed (fs, name, namelen, get_deh_offset (deh))) { one_more_corruption (fs, FATAL); fsck_log ("check_semantic_pass: Hash mismatch detected for (%.*s) in " "directory %K\n", namelen, name, &tmp_ih.ih_key); } if (is_dot (name, namelen) || (is_dot_dot (name, namelen))) { /* do not go through "." and ".." */ ret = OK; } else { if ((ret = add_path_key (&object_key)) == 0) { ret = check_semantic_pass (&object_key, key, is_dot_dot(name, namelen), &relocated_ih); del_path_key (); } } erase_name (namelen); /* check what check_semantic_tree returned */ switch (ret) { case OK: dir_size += DEH_SIZE + entry_len; break; case STAT_DATA_NOT_FOUND: fsck_log ("check_semantic_pass: Name \"%.*s\" in directory %K points to " "nowhere\n", namelen, name, &tmp_ih.ih_key); case LOOP_FOUND: if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { reiserfs_remove_entry (fs, &entry_key); fsck_log (" - removed"); } else { one_more_corruption (fs, FIXABLE); } fsck_log ("\n"); break; case DIRECTORY_HAS_NO_ITEMS: fsck_log ("check_semantic_pass: Name \"%.*s\" in directory %K points a " "directory without body\n", namelen, name, &tmp_ih.ih_key); /* fixme: stat data should be deleted as well */ /* if (fsck_fix_fixable (fs)) { reiserfs_remove_entry (fs, &entry_key); fsck_data(fs)->deleted_entries ++; fsck_log (" - removed"); } fsck_log ("\n");*/ break; case RELOCATED: /* file was relocated, update key in corresponding directory entry */ if (reiserfs_search_by_entry_key (fs, &entry_key, &path) != POSITION_FOUND) { fsck_log("Cannot find a name of the relocated file %K in the directory " "%K\n", &entry_key, &tmp_ih.ih_key); } else { /* update key dir entry points to */ struct reiserfs_de_head * tmp_deh; tmp_deh = B_I_DEH (get_bh (&path), get_ih (&path)) + path.pos_in_item; fsck_log ("The directory %K pointing to %K (\"%.*s\") updated to point " "to ", &tmp_ih.ih_key, &tmp_deh->deh2_dir_id, namelen, name); set_deh_dirid (tmp_deh, get_key_dirid (&relocated_ih.ih_key)); set_deh_objectid (tmp_deh, get_key_objectid (&relocated_ih.ih_key)); fsck_log ("%K (\"%.*s\")\n", &tmp_deh->deh2_dir_id, namelen, name); mark_buffer_dirty (get_bh (&path)); } dir_size += DEH_SIZE + entry_len; pathrelse (&path); break; } } /* for */ freemem (dir_item); free (name); name = 0; if (not_of_one_file (&next_item_key, key)) /* next key is not of this directory */ break; } /* while (dir_item) */ if (dir_size == 0) /* FIXME: is it possible? */ return DIRECTORY_HAS_NO_ITEMS; /* calc correct value of sd_blocks field of stat data */ blocks = dir_size2st_blocks (dir_size); fix_sd = 0; fix_sd += wrong_st_blocks (key, &blocks, sd_blocks, mode, is_new_dir); fix_sd += wrong_st_size (key, is_new_dir ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1, fs->fs_blocksize, &dir_size, sd_size, TYPE_DIRENTRY); if (fix_sd) { if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { /* we have to fix either sd_size or sd_blocks, so look for stat data again */ if (reiserfs_search_by_key_4 (fs, key, &path) != ITEM_FOUND) { fsck_log ("check_semantic_tree: The StatData of the file %K was not found\n", key); one_more_corruption(fs, FATAL); return STAT_DATA_NOT_FOUND; } bh = get_bh (&path); ih = get_ih (&path); sd = get_item (&path); set_sd_size (ih, sd, &dir_size); set_sd_blocks (ih, sd, &blocks); mark_buffer_dirty (bh); pathrelse (&path); } else { fsck_check_stat (fs)->fixable_corruptions += fix_sd; } } return retval; } int check_safe_links () { struct path safe_link_path, path; struct key safe_link_key = {-1, 0, {{0, 0}}}; struct key key = {0, 0, {{0, 0}}}; struct key * rkey; struct item_head * tmp_ih; while (1) { if (get_key_dirid (&safe_link_key) == 0) break; reiserfs_search_by_key_4 (fs, &safe_link_key, &safe_link_path); if (get_blkh_nr_items ( B_BLK_HEAD (get_bh(&safe_link_path))) <= PATH_LAST_POSITION (&safe_link_path)) { pathrelse (&safe_link_path); break; } tmp_ih = get_ih(&safe_link_path); if (get_key_dirid(&tmp_ih->ih_key) != (__u32)-1 || get_key_objectid(&tmp_ih->ih_key) == (__u32)-1) { pathrelse (&safe_link_path); break; } if (get_ih_item_len (tmp_ih) != 4) reiserfs_panic ("Safe Link %k cannot be of the size %d", &tmp_ih->ih_key, get_ih_item_len (tmp_ih)); set_key_dirid(&key, le32_to_cpu(*(__u32 *)get_item(&safe_link_path))); set_key_objectid(&key, get_key_objectid(&tmp_ih->ih_key)); if ( (rkey = get_next_key_2 (&safe_link_path)) == NULL ) set_key_dirid (&safe_link_key, 0); else safe_link_key = *rkey; if (reiserfs_search_by_key_4 (fs, &key, &path) == ITEM_NOT_FOUND) { /*sware on check, delete on fix-fixable*/ if (fsck_mode(fs) == FSCK_CHECK) { fsck_log ("Invalid safe link %k: cannot find the pointed object (%K)\n", &tmp_ih->ih_key, &key); one_more_corruption (fs, FIXABLE); } else if (fsck_mode(fs) == FSCK_FIX_FIXABLE) { fsck_log ("Invalid safe link %k: cannot find the pointed object (%K) - " "safe link was deleted\n", &tmp_ih->ih_key, &key); *(__u32 *)get_item(&safe_link_path) = (__u32)0; pathrelse (&path); reiserfsck_delete_item (&safe_link_path, 0); continue; } } else if (get_offset(&tmp_ih->ih_key) == 0x1) { /* Truncate */ if (!not_a_directory (get_item(&path))) { /*truncate on directory should not happen*/ /*sware on check, delete on fix-fixable*/ if (fsck_mode(fs) == FSCK_CHECK) { fsck_log ("Invalid 'truncate' safe link %k, cannot happen for " "directory (%K)\n", &tmp_ih->ih_key, &key); one_more_corruption (fs, FIXABLE); } else if (fsck_mode(fs) == FSCK_FIX_FIXABLE) { fsck_log ("Invalid 'truncate' safe link %k, cannot happen for " "a directory (%K) - safe link was deleted\n", &tmp_ih->ih_key, &key); *(__u32 *)get_item(&safe_link_path) = (__u32)0; pathrelse (&path); reiserfsck_delete_item (&safe_link_path, 0); continue; } } else { /* save 'safe truncate links' to avoid swaring on wrong sizes. */ __u32 position; if (reiserfs_bin_search (&key, trunc_links, links_num, sizeof(key), &position, comp_short_keys) != POSITION_FOUND) { blocklist__insert_in_position(&key, (void *)&trunc_links, &links_num, sizeof(key), &position); } } } pathrelse (&path); pathrelse (&safe_link_path); } return OK; } void release_safe_links () { freemem(trunc_links); } /* called when --check is given */ void semantic_check (void) { if (fsck_data (fs)->check.bad_nodes) { fsck_progress ("Bad nodes were found, Semantic pass skipped\n"); goto clean; } if (fsck_data (fs)->check.fatal_corruptions) { fsck_progress ("Fatal corruptions were found, Semantic pass skipped\n"); goto clean; } fsck_progress ("Checking Semantic tree:\n"); if (fsck_mode(fs) == FSCK_FIX_FIXABLE) { /*create new_bitmap, and initialize new_bitmap & allocable bitmap*/ fsck_new_bitmap (fs) = reiserfs_create_bitmap(get_sb_block_count(fs->fs_ondisk_sb)); reiserfs_bitmap_copy (fsck_new_bitmap (fs), fs->fs_bitmap2); fsck_allocable_bitmap (fs) = reiserfs_create_bitmap(get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_copy (fsck_allocable_bitmap (fs), fs->fs_bitmap2); fs->block_allocator = reiserfsck_reiserfs_new_blocknrs; fs->block_deallocator = reiserfsck_reiserfs_free_block; } check_safe_links (); if (check_semantic_pass (&root_dir_key, &parent_root_dir_key, 0, 0) != OK) { fsck_log ("check_semantic_tree: No root directory found"); one_more_corruption (fs, FATAL); } release_safe_links (); if (fsck_mode(fs) == FSCK_FIX_FIXABLE) { reiserfs_delete_bitmap (fs->fs_bitmap2); reiserfs_bitmap_delta (fsck_new_bitmap (fs), fsck_deallocate_bitmap (fs)); fs->fs_bitmap2 = fsck_new_bitmap (fs); reiserfs_delete_bitmap (fsck_allocable_bitmap (fs)); fsck_allocable_bitmap (fs) = NULL; set_sb_free_blocks (fs->fs_ondisk_sb, reiserfs_bitmap_zeros (fs->fs_bitmap2)); mark_buffer_dirty (fs->fs_super_bh); add_badblock_list(fs, 0); } fsck_progress ("finished\n"); clean: if (fsck_deallocate_bitmap (fs)) reiserfs_delete_bitmap (fsck_deallocate_bitmap (fs)); } reiserfsprogs-3.6.9/fsck/main.c0000444000077100007710000011704507705265615012154 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" #include #include #include "../include/config.h" #include "../version.h" extern int screen_width; extern int screen_savebuffer_len; extern char *screen_savebuffer; reiserfs_filsys_t * fs; char * badblocks_file; #define print_usage_and_exit() { \ fsck_progress ("\nUsage: %s [mode] [options] " \ " device\n" \ "\n" \ "Modes:\n" \ " --check\t\t\tconsistency checking (default)\n" \ " --fix-fixable\t\t\tfix corruptions which can be fixed without \n" \ " \t\t\t\t--rebuild-tree\n" \ " --rebuild-sb\t\t\tsuper block checking and rebuilding if needed\n" \ " \t\t\t\t(may require --rebuild-tree afterwards)\n" \ " --rebuild-tree\t\tforce fsck to rebuild filesystem from scratch\n" \ " \t\t\t\t(takes a long time)\n" \ " --clean-attributes\t\tclean garbage in reserved fields in StatDatas \n" \ "Options:\n" \ " -j | --journal device\t\tspecify journal if relocated\n" \ " -l | --logfile file\t\tmake fsck to complain to specifed file\n" \ " -n | --nolog\t\t\tmake fsck to not complain\n" \ " -z | --adjust-size\t\tfix file sizes to real size\n" \ " -q | --quiet\t\t\tno speed info\n" \ " -y | --yes\t\t\tno confirmations\n" \ " -V\t\t\t\tprints version and exits\n" \ " -a and -p\t\t\tsome light-weight auto checks for bootup\n" \ " -f and -r\t\t\tignored\n" \ "Expert options:\n" \ " --no-journal-available\tdo not open nor replay journal\n" \ " -S | --scan-whole-partition\tbuild tree of all blocks of the device\n\n", \ argv[0]); \ \ exit(EXIT_OK); \ } /* " -B badblocks-file\n"\ " \t\t\tlist of all bad blocks on the fs\n"\ -B works with --fix-fixable fixes indirect pointers pointed to badblocks, adds badblocks to badblock list in fs. and with --rebuild builds the tree without pointers to badblocks (internal, indirect), adds badblocks to badblock list in fs. */ /* Hidden usage: Modes: " --rollback-fsck-changes\n\t\t\trollback all changes made by fsck\n"\ Options: " -b | --scan-marked-in-bitmap file\n"\ " \t\t\tbuild tree of blocks marked in the bitmapfile\n"\ " -R | --rollback-data file\n"\ " \t\t\tback up all changes to this file or rollback from this file\n"\ " \t\t\tpreviously backed up changes with --rollback-fsck-changes\n"\ " -d dumpfile\n"\ " \t\t\tto test fsck pass by pass - dump into dumpfile all needed\n"\ " \t\t\tinfo for the next pass and load on the start of the next pass\n"\ " -i | --interactive\tmake fsck to stop after every stage\n"\ " -h | --hash hashname\n"\ " -g | --background\n"\ " -t \t\tdo test\n"\ */ /* fsck is called with one non-optional argument - file name of device containing reiserfs. This function parses other options, sets flags based on parsing and returns non-optional argument */ static char * parse_options (struct fsck_data * data, int argc, char * argv []) { int c; static int mode = FSCK_CHECK; static int flag; data->rebuild.scan_area = USED_BLOCKS; while (1) { static struct option options[] = { /* modes */ {"check", no_argument, &mode, FSCK_CHECK}, {"fix-fixable", no_argument, &mode, FSCK_FIX_FIXABLE}, {"rebuild-sb", no_argument, &mode, FSCK_SB}, {"rebuild-tree", no_argument, &mode, FSCK_REBUILD}, {"rollback-fsck-changes", no_argument, &mode, FSCK_ROLLBACK_CHANGES}, {"clean-attributes", no_argument, &mode, FSCK_CLEAN_ATTRIBUTES}, /* options */ {"logfile", required_argument, 0, 'l'}, {"interactive", no_argument, 0, 'i'}, {"adjust-size", no_argument, 0, 'z'}, {"quiet", no_argument, 0, 'q'}, {"yes", no_argument, 0, 'y'}, {"nolog", no_argument, 0, 'n'}, /* if file exists ad reiserfs can be load of it - only blocks marked used in that bitmap will be read */ {"scan-marked-in-bitmap", required_argument, 0, 'b'}, {"create-passes-dump", required_argument, 0, 'd'}, /* all blocks will be read */ {"scan-whole-partition", no_argument, 0, 'S'}, /* useful for -S */ {"hash", required_argument, 0, 'h'}, /* preparing rollback data*/ {"rollback-data", required_argument, 0, 'R'}, {"journal", required_argument, 0, 'j'}, {"no-journal-available", no_argument, &flag, OPT_SKIP_JOURNAL}, // {"bad-block-file", required_argument, 0, 'B'}, /* start reiserfsck in background and exit */ {"background", no_argument, 0, 'g'}, {0, 0, 0, 0} }; int option_index; c = getopt_long (argc, argv, "iql:nb:Szd:R:h:j:gafVrpyt:", options, &option_index); if (c == -1) break; switch (c) { case 0: /* long-only options */ if (flag == OPT_SKIP_JOURNAL) { /* no journal available */ data->options |= OPT_SKIP_JOURNAL; flag = 0; } break; case 'i': /* --interactive */ data->options |= OPT_INTERACTIVE; break; case 'q': /* --quiet */ data->options |= OPT_QUIET; break; case 'y': /* --quiet */ data->options |= OPT_YES; break; case 'l': /* --logfile */ data->log_file_name = optarg; /*asprintf (&data->log_file_name, "%s", optarg);*/ data->log = fopen (optarg, "w"); if (!data->log) fprintf (stderr, "reiserfsck: Cannot not open \'%s\': %s", optarg, strerror(errno)); break; case 'n': /* --nolog */ data->options |= OPT_SILENT; break; case 'b': /* --scan-marked-in-bitmap */ /* will try to load a bitmap from a file and read only blocks marked in it. That bitmap could be created by previous run of reiserfsck with -c */ data->rebuild.bitmap_file_name = optarg; /*asprintf (&data->rebuild.bitmap_file_name, "%s", optarg);*/ data->rebuild.scan_area = EXTERN_BITMAP; break; case 'S': /* --scan-whole-partition */ data->rebuild.scan_area = ALL_BLOCKS; break; #if 0 case 'J': /* take all blocks which are leaves in journal area and put them into tree item by item (DO NOT USE IT UNTIL YOU KNOW WHAT ARE YOU DOING) */ data->rebuild.use_journal_area = 1; break; #endif case 'd': /* --create-passes-dump */ asprintf (&data->rebuild.passes_dump_file_name, "%s", optarg); data->options |= OPT_SAVE_PASSES_DUMP; break; case 'z': /* --adjust-file-size */ data->options |= OPT_ADJUST_FILE_SIZE; break; case 'h': /* --hash: suppose that this hash was used on a filesystem */ asprintf (&data->rebuild.defined_hash, "%s", optarg); if (name2func (data->rebuild.defined_hash) == 0) reiserfs_panic ("reiserfsck: Unknown hash is specified: %s", data->rebuild.defined_hash); data->options |= OPT_HASH_DEFINED; break; case 'j': /* specified relocated journal device */ data->journal_dev_name = optarg; break; case 'R': /* preparing rollback data */ asprintf (&data->rebuild.rollback_file, "%s", optarg); data->options |= OPT_SAVE_ROLLBACK; break; case 'B': /* list of phisically corrupted blocks */ asprintf (&badblocks_file, "%s", optarg); data->options |= BADBLOCKS_FILE; break; case 'g': /* --background */ data->options |= OPT_BACKGROUND; break; case 'a': case 'p': mode = FSCK_AUTO; break; case 'f': case 'r': /* ignored */ break; case 'V': /* cause fsck to do nothing */ mode = DO_NOTHING; break; case 't': mode = DO_TEST; data->rebuild.test = atoi (optarg); break; default: print_usage_and_exit(); } } if (optind != argc - 1 && mode != DO_NOTHING) /* only one non-option argument is permitted */ print_usage_and_exit(); if (mode != FSCK_REBUILD && (data->rebuild.scan_area == EXTERN_BITMAP || data->rebuild.scan_area == ALL_BLOCKS || data->options & OPT_SAVE_PASSES_DUMP)) /* wrong options for this mode */ print_usage_and_exit(); /* if (data->options & OPT_ADJUST_FILE_SIZE) { if ((mode != FSCK_REBUILD) && (mode != FSCK_FIX_FIXABLE)) print_usage_and_exit(); } */ if (data->options & OPT_SAVE_ROLLBACK) { if (mode == FSCK_SB) print_usage_and_exit(); } if (mode == FSCK_ROLLBACK_CHANGES) { if ((data->options & OPT_SAVE_ROLLBACK) == 0) print_usage_and_exit(); } if ((data->options & BADBLOCKS_FILE) && ((mode == FSCK_SB) || (mode == FSCK_CLEAN_ATTRIBUTES) || (mode == FSCK_CHECK))) print_usage_and_exit(); if ((mode == FSCK_REBUILD) && (data->options & OPT_YES)) data->options &= ~OPT_YES; data->mode = mode; if (!data->log) data->log = stdout; return argv[optind]; } #define REBUILD_WARNING \ " *************************************************************\n\ ** Do not run the program with --rebuild-tree unless **\n\ ** something is broken and MAKE A BACKUP before using it. **\n\ ** If you have bad sectors on a drive it is usually a bad **\n\ ** idea to continue using it. Then you probably should get **\n\ ** a working hard drive, copy the file system from the bad **\n\ ** drive to the good one -- dd_rescue is a good tool for **\n\ ** that -- and only then run this program. **\n\ ** If you are using the latest reiserfsprogs and it fails **\n\ ** please email bug reports to reiserfs-list@namesys.com, **\n\ ** providing as much information as possible -- your **\n\ ** hardware, kernel, patches, settings, all reiserfsck **\n\ ** messages (including version), the reiserfsck logfile, **\n\ ** check the syslog file for any related information. **\n\ ** If you would like advice on using this program, support **\n\ ** is available for $25 at www.namesys.com/support.html. **\n\ *************************************************************\n\ \nWill rebuild the filesystem (%s) tree\n" #define START_WARNING \ " *************************************************************\n\ ** If you are using the latest reiserfsprogs and it fails **\n\ ** please email bug reports to reiserfs-list@namesys.com, **\n\ ** providing as much information as possible -- your **\n\ ** hardware, kernel, patches, settings, all reiserfsck **\n\ ** messages (including version), the reiserfsck logfile, **\n\ ** check the syslog file for any related information. **\n\ ** If you would like advice on using this program, support **\n\ ** is available for $25 at www.namesys.com/support.html. **\n\ *************************************************************\n\ \n" void warn_what_will_be_done (char * file_name, struct fsck_data * data) { FILE * warn_to; warn_to = (data->progress ?: stderr); if (data->mode == FSCK_REBUILD) reiserfs_warning (warn_to, REBUILD_WARNING, file_name); else reiserfs_warning (warn_to, START_WARNING); /* warn about fsck mode */ switch (data->mode) { case FSCK_CHECK: reiserfs_warning (warn_to, "Will read-only check consistency of the " "filesystem on %s\n", file_name); break; case FSCK_FIX_FIXABLE: reiserfs_warning (warn_to, "Will check consistency of the filesystem " "on %s\n", file_name); reiserfs_warning (warn_to, "and will fix what can be fixed without " "--rebuild-tree\n"); break; case FSCK_SB: reiserfs_warning (warn_to, "Will check superblock and rebuild it if " "needed\n"); break; case FSCK_REBUILD: if (data->options & OPT_SAVE_PASSES_DUMP) { reiserfs_warning (warn_to, "Will run only 1 step of the rebuilding, " "write state file '%s' and exit\n", data->rebuild.passes_dump_file_name); } else if (data->options & OPT_INTERACTIVE) reiserfs_warning (warn_to, "Will stop after every stage and ask for " "confirmation before continuing\n"); if (data->rebuild.bitmap_file_name) reiserfs_warning (warn_to, "Will try to load a bitmap--of all " "ReiserFS leaves in the partition--from the file \n'%s'\n", data->rebuild.bitmap_file_name); if (data->options & OPT_ADJUST_FILE_SIZE) reiserfs_warning (warn_to, "\tWill set file sizes in their metadata " "to real file sizes actually found by fsck.\n"); if (data->options & OPT_HASH_DEFINED) reiserfs_warning (warn_to, "\tSuppose \"%s\" hash is in use\n", data->rebuild.defined_hash); break; case FSCK_ROLLBACK_CHANGES: reiserfs_warning (warn_to, "Will rollback all data saved in %s into %s\n", data->rebuild.rollback_file, file_name); break; case FSCK_CLEAN_ATTRIBUTES: reiserfs_warning (warn_to, "Will clean file attributes on %s\n", file_name); break; case FSCK_AUTO: return; } if (data->options & OPT_SAVE_ROLLBACK && data->mode != FSCK_ROLLBACK_CHANGES) reiserfs_warning (warn_to, "Will save all blocks to be changed into " "file '%s'\n", data->rebuild.rollback_file); if (data->options & BADBLOCKS_FILE) reiserfs_warning (warn_to, "Bad block list will contain only blocks specified in '%s' " "file\n", badblocks_file); reiserfs_warning (warn_to, "Will put log info to '%s'\n", (data->log == stdout) ? "stdout" : (data->log_file_name ? : "fsck.run")); if (!(data->options & OPT_YES) && !user_confirmed (warn_to, "\nDo you want to " "run this program?[N/Yes] (note need to type Yes if you do):", "Yes\n")) exit (EXIT_USER); } static dma_info_t dma_info; static dma_info_t old_dma_info; void check_dma() { old_dma_info = dma_info; if (get_dma_info(&dma_info) == -1) { fsck_log("get_dma_info failed %s\n", strerror (errno)); return; } if (dma_info.dma != old_dma_info.dma) { if (dma_info.dma == 0) { printf("\n********************************************************************\n"); printf("* Warning: It was just detected that dma mode was turned off while *\n"); printf("* operating -- probably due to some problem with your hardware. *\n"); printf("* Please check your hardware and have a look into the syslog file. *\n"); printf("* Note: running with --rebuild-tree on faulty hardware may destroy *\n"); printf("* your data. *\n"); printf("********************************************************************\n"); if (fsck_log_file (fs) != stdout) fsck_log("WARNING: dma mode has been turned off.\n"); } } if (dma_info.speed != old_dma_info.speed) { if (dma_info.speed < old_dma_info.speed) { printf("\n********************************************************************\n"); printf("* Warning: It was just detected that dma speed was descreased while*\n"); printf("* operating -- probably due to some problem with your hardware. *\n"); printf("* Please check your hardware and have a look into the syslog file. *\n"); printf("* Note: running with --rebuild-tree on faulty hardware may destroy *\n"); printf("* your data. *\n"); printf("********************************************************************\n"); if (fsck_log_file (fs) != stdout) fsck_log("WARNING: dma speed has been descreased.\n"); } } alarm(1); } void register_timer() { memset(&dma_info, 0, sizeof(dma_info)); memset(&old_dma_info, 0, sizeof(old_dma_info)); dma_info.fd = fs->fs_dev; if (prepare_dma_check(&dma_info) != 0) return; if (get_dma_info(&dma_info) == -1) { fsck_log("get_dma_info failed %s\n", strerror (errno)); return; } if (dma_info.dma == 0) { printf("\n******************************************************\n"); printf("* Warning: The dma on your hard drive is turned off. *\n"); printf("* This may really slow down the fsck process. *\n"); printf("******************************************************\n"); if (fsck_log_file (fs) != stdout) fsck_log("WARNING: DMA is turned off\n"); } signal(SIGALRM, check_dma); alarm(1); } static void reset_super_block (reiserfs_filsys_t * fs) { struct reiserfs_super_block * sb; struct reiserfs_journal_header * jh; sb = fs->fs_ondisk_sb; set_sb_free_blocks (sb, get_sb_block_count (sb)); set_sb_root_block (sb, 0); set_sb_tree_height (sb, ~0); /* make file system invalid unless fsck finished () */ set_sb_fs_state (sb, get_sb_fs_state (sb) | FS_FATAL); /* if ( is_reiser2fs_jr_magic_string (sb) ) {??? set_sb_version (sb, REISERFS_VERSION_3); } if (is_reiser2fs_magic_string (sb)) { set_sb_version (sb, REISERFS_FORMAT_3_6); } if (is_reiserfs_magic_string (sb)) { set_sb_version (sb, REISERFS_FORMAT_3_5); } */ /* make sure that hash code in super block match to set hash function */ set_sb_hash_code (sb, func2code (fs->fs_hash_function)); if (fsck_hash_defined (fs)) { /* --hash was specifed */ fs->fs_hash_function = name2func (fsck_data (fs)->rebuild.defined_hash); set_sb_hash_code (sb, func2code (fs->fs_hash_function)); } if (reiserfs_journal_opened (fs)) { jh = (struct reiserfs_journal_header *)fs->fs_jh_bh->b_data; /* reset journal params if needed. */ if (memcmp(sb_jp(sb), &jh->jh_journal, sizeof (struct journal_params))) { if (is_reiserfs_jr_magic_string (sb)) memcpy (sb_jp(sb), &jh->jh_journal, sizeof (struct journal_params)); else { set_sb_reserved_for_journal (sb, 0); set_jp_journal_dev (sb_jp(sb), 0); set_jp_journal_magic (sb_jp(sb) ,0); set_jp_journal_1st_block (sb_jp(sb), get_journal_start_must (fs)); set_jp_journal_size (sb_jp(sb), journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize)); set_jp_journal_max_trans_len (sb_jp(sb), advise_journal_max_trans_len( get_jp_journal_max_trans_len (sb_jp(sb)), get_jp_journal_size (sb_jp(sb)), fs->fs_blocksize, 0)); set_jp_journal_max_batch (sb_jp(sb), advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb)))); set_jp_journal_max_commit_age (sb_jp(sb), advise_journal_max_commit_age()); set_jp_journal_max_trans_age (sb_jp(sb), advise_journal_max_trans_age()); set_jp_journal_dev (&jh->jh_journal, 0); set_jp_journal_magic (&jh->jh_journal ,0); set_jp_journal_1st_block (&jh->jh_journal, get_jp_journal_1st_block(sb_jp(sb))); set_jp_journal_size (&jh->jh_journal, get_jp_journal_size(sb_jp(sb))); set_jp_journal_max_trans_len (&jh->jh_journal, get_jp_journal_max_trans_len(sb_jp(sb))); set_jp_journal_max_batch (&jh->jh_journal, get_jp_journal_max_batch(sb_jp(sb))); set_jp_journal_max_commit_age (&jh->jh_journal, get_jp_journal_max_commit_age(sb_jp(sb))); set_jp_journal_max_trans_age (&jh->jh_journal, get_jp_journal_max_trans_age(sb_jp(sb))); } } } /* objectid map is not touched */ mark_buffer_dirty (fs->fs_super_bh); bwrite (fs->fs_super_bh); if (!(fsck_data(fs)->options & OPT_SAVE_PASSES_DUMP)) mark_buffer_do_not_flush (fs->fs_super_bh); } #define START_FROM_THE_BEGINNING 1 #define START_FROM_PASS_1 2 #define START_FROM_PASS_2 3 #define START_FROM_SEMANTIC 4 #define START_FROM_LOST_FOUND 5 #define START_FROM_PASS_4 6 /* this decides where to start from */ static int where_to_start_from (reiserfs_filsys_t * fs) { int ret; FILE * fp = 0; int last_run_state; last_run_state = get_sb_fs_state (fs->fs_ondisk_sb); if (last_run_state == 0 || !fsck_run_one_step (fs)) /**/ return START_FROM_THE_BEGINNING; /* We are able to perform the next step only if there is a file with the previous * step results. */ fp = open_file (state_dump_file (fs), "r"); if (fp == 0) { set_sb_fs_state (fs->fs_ondisk_sb, 0); return START_FROM_THE_BEGINNING; } /* check start and end magics of dump file */ ret = is_stage_magic_correct (fp); if (ret <= 0 || ret != last_run_state) return START_FROM_THE_BEGINNING; switch (last_run_state) { case PASS_0_DONE: /* skip pass 0 */ if (!fsck_user_confirmed (fs, "Pass 0 seems finished. Start from pass 1?(Yes)", "Yes\n", 1)) fsck_exit ("Run without -d then\n"); load_pass_0_result (fp, fs); fclose (fp); return START_FROM_PASS_1; case PASS_1_DONE: /* skip pass 1 */ if (!fsck_user_confirmed (fs, "Passes 0 and 1 seems finished. Start from " "pass 2?(Yes)", "Yes\n", 1)) { fsck_exit ("Run without -d then\n"); } load_pass_1_result (fp, fs); fclose (fp); return START_FROM_PASS_2; case TREE_IS_BUILT: if (!fsck_user_confirmed (fs, "Internal tree of filesystem looks built. " "Skip rebuilding?(Yes)", "Yes\n", 1)) { fsck_exit ("Run without -d then\n"); } load_pass_2_result (fs); fclose (fp); return START_FROM_SEMANTIC; case SEMANTIC_DONE: if (!fsck_user_confirmed (fs, "Passes 0 and 1 seems finished. Start from " "pass 2?(Yes)", "Yes\n", 1)) { fsck_exit ("Run without -d then\n"); } load_semantic_result (fp, fs); fclose (fp); return START_FROM_LOST_FOUND; case LOST_FOUND_DONE: if (!fsck_user_confirmed (fs, "Passes 0 and 1 seems finished. Start from " "pass 2?(Yes)", "Yes\n", 1)) { fsck_exit ("Run without -d then\n"); } load_lost_found_result (fs); fclose (fp); return START_FROM_PASS_4; } return START_FROM_THE_BEGINNING; } static void mark_filesystem_consistent (reiserfs_filsys_t * fs) { if (!is_opened_rw (fs)) return; if (!reiserfs_journal_opened (fs)) { /* make sure journal is not standard */ if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb)) die ("Filesystem with default journal must be opened."); fsck_progress ("WARNING: You must use reiserfstune to specify a new " "journal before mounting it.\n"); /* mark filesystem such that it is not mountable until * new journaldevice is defined */ set_jp_journal_magic (sb_jp (fs->fs_ondisk_sb), NEED_TUNE); } set_sb_umount_state (fs->fs_ondisk_sb, FS_CLEANLY_UMOUNTED); set_sb_fs_state (fs->fs_ondisk_sb, FS_CONSISTENT); mark_buffer_dirty (fs->fs_super_bh); } static void reiserfsck_replay_journal (reiserfs_filsys_t * fs) { struct reiserfs_super_block *on_place_sb; int sb_size = reiserfs_super_block_size(fs->fs_ondisk_sb); /* keep the super_block in the separate memory to avoid problems with replaying * broken parameters. */ on_place_sb = (struct reiserfs_super_block *)fs->fs_super_bh->b_data; fs->fs_ondisk_sb = getmem (sb_size); memcpy (fs->fs_ondisk_sb, on_place_sb, sb_size); replay_journal (fs); /* Copy checked reliable sb fields from backed up sb to a new one. */ set_sb_block_count(on_place_sb, get_sb_block_count(fs->fs_ondisk_sb)); memcpy(sb_jp(on_place_sb), sb_jp(fs->fs_ondisk_sb), sizeof(struct journal_params)); set_sb_block_size(on_place_sb, get_sb_block_size(fs->fs_ondisk_sb)); set_sb_oid_maxsize(on_place_sb, get_sb_oid_maxsize(fs->fs_ondisk_sb)); memcpy(on_place_sb->s_v1.s_magic, fs->fs_ondisk_sb->s_v1.s_magic, 10); set_sb_hash_code(on_place_sb, get_sb_hash_code(fs->fs_ondisk_sb)); set_sb_bmap_nr(on_place_sb, get_sb_bmap_nr(fs->fs_ondisk_sb)); set_sb_version(on_place_sb, get_sb_version(fs->fs_ondisk_sb)); set_sb_reserved_for_journal(on_place_sb, get_sb_reserved_for_journal(fs->fs_ondisk_sb)); if (sb_size == SB_SIZE) { set_sb_v2_flags(on_place_sb, get_sb_v2_flags(fs->fs_ondisk_sb)); memcpy(on_place_sb->s_uuid, fs->fs_ondisk_sb->s_uuid, 16); memcpy(on_place_sb->s_label, fs->fs_ondisk_sb->s_label, 16); } /* get rid of SB copy */ freemem (fs->fs_ondisk_sb); fs->fs_ondisk_sb = on_place_sb; } static void the_end (reiserfs_filsys_t * fs) { struct reiserfs_super_block * sb; sb = fs->fs_ondisk_sb; /* put bitmap and objectid map on place */ reiserfs_delete_bitmap (fs->fs_bitmap2); fs->fs_bitmap2 = fsck_new_bitmap (fs); if (!fs->fs_bitmap2->bm_dirty) die ("Bitmap not dirty"); // id_map_flush(proper_id_map (fs), fs); id_map_flush(semantic_id_map (fs), fs); id_map_free(proper_id_map (fs)); id_map_free(semantic_id_map (fs)); /* set_sb_free_blocks (sb, reiserfs_bitmap_zeros (fsck_new_bitmap (fs)));*/ mark_filesystem_consistent (fs); clear_buffer_do_not_flush (fs->fs_super_bh); /* write all dirty blocks */ fsck_progress ("Syncing.."); fs->fs_dirt = 1; clean_after_dma_check(fs->fs_dev, &dma_info); reiserfs_close (fs); fsck_progress ("finished\n"); } static void rebuild_tree (reiserfs_filsys_t * fs) { time_t t; int ret; if (is_mounted (fs->fs_file_name)) { fsck_progress ("rebuild_tree: Cannot rebuild tree of mounted filesystem\n"); exit(EXIT_USER); } init_rollback_file (state_rollback_file(fs), &fs->fs_blocksize, fsck_data(fs)->log); reiserfs_reopen (fs, O_RDWR); if (!fsck_skip_journal (fs)) { if (reiserfs_journal_params_check(fs)) { reiserfs_close(fs); exit(EXIT_FATAL); } /* rebuild starts with journal replaying */ if (!fsck_skip_journal (fs)) reiserfsck_replay_journal (fs); } ret = reiserfs_open_ondisk_bitmap (fs); if (ret < 0) { fsck_progress ("reiserfsck: Could not open bitmap\n"); reiserfs_close (fs); exit(EXIT_OPER); } else if (ret > 0) { fsck_log("Zero bit found in on-disk bitmap after the last valid bit. " "Fixed.\n"); } time (&t); fsck_progress ("###########\n" "reiserfsck --rebuild-tree started at %s" "###########\n", ctime (&t)); switch (where_to_start_from (fs)) { case START_FROM_THE_BEGINNING: reset_super_block (fs); pass_0 (fs); case START_FROM_PASS_1: reset_super_block (fs); pass_1 (fs); case START_FROM_PASS_2: pass_2 (fs); case START_FROM_SEMANTIC: pass_3_semantic (fs); /* if --lost+found is set - link unaccessed directories to lost+found directory */ case START_FROM_LOST_FOUND: pass_3a_look_for_lost (fs); case START_FROM_PASS_4: /* 4. look for unaccessed items in the leaves */ pass_4_check_unaccessed_items (); the_end (fs); } close_rollback_file (); time (&t); fsck_progress ("###########\n" "reiserfsck finished at %s" "###########\n", ctime (&t)); exit (EXIT_OK); } /* check umounted or read-only mounted filesystems only */ static void prepare_fs_for_check(reiserfs_filsys_t * fs) { /* The method could be called from auto_check already. */ if (fs->fs_flags == O_RDWR) return; reiserfs_reopen (fs, O_RDWR); if (is_mounted (fs->fs_file_name)) { /* filesystem seems mounted. */ if (fsck_mode (fs) == FSCK_CLEAN_ATTRIBUTES) { fsck_progress ("Partition %s is mounted, cannot clean attributes " "on mounted device\n", fs->fs_file_name); reiserfs_close (fs); exit(EXIT_USER); } if (!is_mounted_read_only (fs->fs_file_name)) { fsck_progress ("Partition %s is mounted with write permissions, " "cannot check it\n", fs->fs_file_name); reiserfs_close (fs); exit(EXIT_USER); } if (!reiserfs_journal_opened (fs)) { /* just to make sure */ reiserfs_panic ("Journal is not opened"); } else if (reiserfs_journal_params_check(fs)) { reiserfs_close (fs); exit(EXIT_FATAL); } fsck_progress ("Filesystem seems mounted read-only. Skipping journal " "replay.\n"); if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { fsck_progress ("--fix-fixable ignored\n"); fsck_mode (fs) = FSCK_CHECK; } } else if (!fsck_skip_journal (fs)) { if (reiserfs_journal_params_check(fs)) { reiserfs_close (fs); exit(EXIT_FATAL); } /* filesystem is not mounted, replay journal before checking */ reiserfsck_replay_journal (fs); } } static void clean_attributes (reiserfs_filsys_t * fs) { time_t t; time (&t); if (get_sb_umount_state (fs->fs_ondisk_sb) != FS_CLEANLY_UMOUNTED) { fsck_progress ("Filesystem does not look cleanly umounted\n" "Check consistency of the partition first.\n"); exit(EXIT_USER); } if (get_sb_fs_state (fs->fs_ondisk_sb) != FS_CONSISTENT) { fsck_progress ("Filesystem seems to be in unconsistent state.\n" "Check consistency of the partition first.\n"); exit(EXIT_USER); } if (get_reiserfs_format (fs->fs_ondisk_sb) != REISERFS_FORMAT_3_6) { fsck_progress ("Filesystems of 3_5 format do not support extended " "attributes.\n"); exit(EXIT_USER); } fsck_progress ("###########\n" "reiserfsck --clean-attributes started at %s" "###########\n", ctime (&t)); init_rollback_file (state_rollback_file(fs), &fs->fs_blocksize, fsck_data(fs)->log); prepare_fs_for_check(fs); do_clean_attributes (fs); clean_after_dma_check(fs->fs_dev, &dma_info); reiserfs_close (fs); close_rollback_file (); fsck_progress ("###########\n" "reiserfsck finished at %s" "###########\n", ctime (&t)); exit (EXIT_FIXED); } /* Do not allow buffers to be flushed after finishing to avoid another bitmap * reading on mounting. */ static void fsck_sleep() { int res; res = fork(); if (res == -1) { reiserfs_panic ("reiserfsck: Fork failed: %s", strerror(errno)); } else if (res == 0) { /* Make the child process to sleep for 5 secs. */ sleep(5); } } static int auto_check (reiserfs_filsys_t *fs) { __u16 state; int retval = 0; print_super_block (stdout, fs, fs->fs_file_name, fs->fs_super_bh, 1); state = get_sb_fs_state (fs->fs_ondisk_sb); if ((state & FS_FATAL) == FS_FATAL) { fprintf(stderr, "Filesystem seems to have fatal corruptions. Running " "with --rebuild-tree is required.\n"); goto error; } if ((state & FS_ERROR) == FS_ERROR) { fprintf(stderr, "Some corruptions on the filesystem were detected. Switching to " "the --fix-fixable mode.\n"); /* run fixable pass. */ return 0; } if (state != FS_CONSISTENT) fprintf(stderr, "Some strange state was specified in the super block. " "Do usual check.\n"); prepare_fs_for_check(fs); /* Check bitmaps. */ retval = reiserfs_open_ondisk_bitmap (fs); if (retval > 0) { fsck_log("Zero bit found in on-disk bitmap after the last valid bit. " "Switching to --fix-fixable mode.\n"); /* run fixable pass. */ return 0; } else if (retval < 0) { fsck_progress ("reiserfsck: Could not open bitmap\n"); goto error; } if (get_sb_block_count (fs->fs_ondisk_sb) - get_sb_free_blocks(fs->fs_ondisk_sb) != fs->fs_bitmap2->bm_set_bits) { fsck_log("Wrong amount of used blocks. Switching to the --fix-fixable mode.\n"); /* run fixable pass. */ return 0; } check_fs_tree (fs); if (fsck_data (fs)->check.fatal_corruptions) { fprintf(stderr, "%lu fatal corruption(s) found in the root block. Running " "with the --rebuild-tree is required.\n", fsck_data (fs)->check.fatal_corruptions); goto fatal_error; } else if (fsck_data (fs)->check.fixable_corruptions) { /* seems that this cannot happen. */ fprintf(stderr, "%lu fixable corruption(s) found. Switching to " "the --fix-fixable mode.\n", fsck_data (fs)->check.fixable_corruptions); fsck_data (fs)->check.fixable_corruptions = 0; /* run fixable pass. */ return 0; } clean_after_dma_check(fs->fs_dev, &dma_info); fsck_sleep(); reiserfs_close (fs); /* do not do anything else. */ exit (EXIT_OK); fatal_error: set_sb_fs_state(fs->fs_ondisk_sb, FS_FATAL); mark_buffer_dirty (fs->fs_super_bh); bwrite(fs->fs_super_bh); error: clean_after_dma_check(fs->fs_dev, &dma_info); reiserfs_close(fs); exit(EXIT_FATAL); } /* check umounted or read-only mounted filesystems only */ static void check_fs (reiserfs_filsys_t * fs) { int retval = EXIT_OK; time_t t; time (&t); if (fsck_mode (fs) != FSCK_FIX_FIXABLE) { fsck_progress ("###########\n" "reiserfsck --check started at %s" "###########\n", ctime (&t)); } else { fsck_progress ("###########\n" "reiserfsck --fix-fixable started at %s" "###########\n", ctime (&t)); } init_rollback_file (state_rollback_file(fs), &fs->fs_blocksize, fsck_data(fs)->log); prepare_fs_for_check (fs); if (!fs->fs_bitmap2) /* It could be done on auto_check already. */ retval = reiserfs_open_ondisk_bitmap (fs); if (retval > 0) { if (fsck_mode(fs) != FSCK_FIX_FIXABLE) { fsck_log("Zero bit found in on-disk bitmap after the last valid " "bit.\n"); one_more_corruption(fs, FIXABLE); } else { fsck_log("Zero bit found in on-disk bitmap after the last valid " "bit. Fixed.\n"); } } else if (retval < 0) { fsck_progress ("reiserfsck: Could not open bitmap\n"); reiserfs_close (fs); exit(EXIT_OPER); } check_fs_tree (fs); semantic_check (); if (fsck_data (fs)->check.fatal_corruptions) { fsck_progress ("%lu found corruptions can be fixed only when running with " "--rebuild-tree\n", fsck_data (fs)->check.fatal_corruptions); set_sb_fs_state (fs->fs_ondisk_sb, FS_FATAL); mark_buffer_dirty (fs->fs_super_bh); retval = EXIT_FATAL; } else if (fsck_data (fs)->check.fixable_corruptions) { /* fixable corruptions found */ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { /* fixable corruptions found and fix-fixable has not fixed them, * do rebuild-tree */ fsck_progress ("Fatal error: %lu fixable corruptions found after " "--fix-fixable.\n", fsck_data (fs)->check.fixable_corruptions); retval = EXIT_OPER; } else { fsck_progress ("%lu found corruptions can be fixed when running with " "--fix-fixable\n", fsck_data (fs)->check.fixable_corruptions); retval = EXIT_FIXABLE; } set_sb_fs_state (fs->fs_ondisk_sb, FS_ERROR); mark_buffer_dirty (fs->fs_super_bh); } else { fsck_progress ("No corruptions found\n"); stage_report (5, fs); retval = fsck_mode(fs) == FSCK_CHECK ? EXIT_OK : EXIT_FIXED; mark_filesystem_consistent (fs); } if (fsck_mode (fs) == FSCK_FIX_FIXABLE) id_map_flush(proper_id_map (fs), fs); id_map_free(proper_id_map (fs)); clean_after_dma_check(fs->fs_dev, &dma_info); reiserfs_close (fs); close_rollback_file (); clear_relocated_list(); time (&t); fsck_progress ("###########\n" "reiserfsck finished at %s" "###########\n", ctime (&t)); exit(retval); } static int open_devices_for_rollback (char * file_name, struct fsck_data * data) { int fd; fd = open (file_name, O_RDWR | O_LARGEFILE); if (fd == -1) { reiserfs_warning (stderr, "reiserfsck: Cannot not open the fs " "partition %s\n", file_name); return -1; } fs = getmem (sizeof (*fs)); fs->fs_dev = fd; fs->fs_vp = data; asprintf (&fs->fs_file_name, "%s", file_name); if (data->journal_dev_name && strcmp (data->journal_dev_name, file_name)) { fs->fs_journal_dev = open (data->journal_dev_name, O_RDWR | O_LARGEFILE); if (fs->fs_journal_dev == -1) { reiserfs_warning (stderr, "Cannot open journal partition\n"); return -1; } } if (open_rollback_file (state_rollback_file(fs), fsck_data(fs)->log)) return -1; return 0; } static void fsck_rollback (reiserfs_filsys_t * fs) { time_t t; time (&t); fsck_progress ("###########\n" "reiserfsck --rollback-fsck-changes started at %s" "###########\n", ctime (&t)); do_fsck_rollback (fs->fs_dev, fs->fs_journal_dev, fsck_progress_file (fs)); close_rollback_file (); close (fs->fs_journal_dev); free (fs->fs_file_name); fs->fs_file_name = 0; close (fs->fs_dev); freemem (fs); time (&t); fsck_progress ("###########\n" "reiserfsck finished at %s" "###########\n", ctime (&t)); exit(EXIT_FIXED); } int main (int argc, char * argv []) { char * file_name; struct fsck_data * data; struct rlimit rlim = {0xffffffff, 0xffffffff}; int retval; char *width; width = getenv("COLUMNS"); if ( width ) screen_width = atoi(width); if (screen_width == 0) screen_width = 80; // We default to 80 characters wide screen screen_width--; screen_savebuffer_len=screen_width; screen_savebuffer=getmem(screen_width+1); memset(screen_savebuffer,0,screen_savebuffer_len+1); lost_found_dir_key.k2_dir_id = cpu_to_le32(lost_found_dir_key.k2_dir_id); lost_found_dir_key.k2_objectid = cpu_to_le32(lost_found_dir_key.k2_objectid); /* this is only needed (and works) when running under 2.4 on regular files */ if (setrlimit (RLIMIT_FSIZE, &rlim) == -1) { reiserfs_warning (stderr, "Cannot change the system limit for file size " "with setrlimit: %s\n", strerror(errno)); } data = getmem (sizeof (struct fsck_data)); file_name = parse_options (data, argc, argv); if (data->mode != FSCK_AUTO) print_banner ("reiserfsck"); if (data->mode == DO_NOTHING) { freemem (data); exit(EXIT_OK); } if (data->options & OPT_BACKGROUND) { /* running in background reiserfsck appends progress information into 'fsck.run'. Logs get there if log file was not specified*/ data->options |= OPT_QUIET; data->progress = fopen ("fsck.run", "a+"); if (!data->progress) reiserfs_panic ("reiserfsck: Cannot not open \"fsck.run\""); if (data->log == stdout) /* no log file specifed - redirect log into 'fsck.run' */ data->log = data->progress; retval = fork (); if (retval == -1) { reiserfs_panic ("reiserfsck: Fork failed: %s", strerror(errno)); } else if (retval != 0) { exit(EXIT_OPER); } reiserfs_warning (stderr, "\nReiserfsck is running in background as " "[%d],\nmake sure that it gets all the confirmations from stdin " "that it requests.\n\n", getpid ()); } /* This asks for confirmation also. */ if (data->mode != FSCK_AUTO) warn_what_will_be_done(file_name, data); if (data->mode == FSCK_ROLLBACK_CHANGES) { if (open_devices_for_rollback (file_name, data) == -1) exit(EXIT_OPER); } else { fs = reiserfs_open (file_name, O_RDONLY, 0, data, data->mode != FSCK_SB); if (data->mode != FSCK_SB) { if (no_reiserfs_found (fs)) die ("Failed to open the filesystem.\n\n" "If the partition table has not been changed, and the partition is\n" "valid and it really contains a reiserfs partition, then the\n" "superblock is corrupted and you need to run this utility with\n" "--rebuild-sb.\n"); if (fsck_skip_journal (fs) && !is_reiserfs_jr_magic_string (fs->fs_ondisk_sb)) { reiserfs_warning (stderr, "Filesystem with default journal found, " "--no-journal-available is ignored\n"); fsck_data(fs)->options &= ~OPT_SKIP_JOURNAL; } if (!fsck_skip_journal (fs)) { if (reiserfs_open_journal(fs, data->journal_dev_name, O_RDONLY)) { fsck_progress ("Failed to open the journal device (%s).\n", data->journal_dev_name); reiserfs_close (fs); exit(EXIT_OPER); } } if (data->options & BADBLOCKS_FILE) { if (create_badblock_bitmap (fs, badblocks_file) != 0) { badblocks_file = NULL; data->options &= ~BADBLOCKS_FILE; } } register_timer(); } } switch (data->mode) { case FSCK_SB: rebuild_sb (fs, file_name, data); break; case FSCK_AUTO: /* perform some light-weight checks. If error, do fixable job. */ if (auto_check (fs)) break; data->mode = FSCK_FIX_FIXABLE; case FSCK_CHECK: case FSCK_FIX_FIXABLE: check_fs (fs); break; case FSCK_REBUILD: case DO_TEST: rebuild_tree (fs); break; case FSCK_ROLLBACK_CHANGES: fsck_rollback (fs); break; case FSCK_CLEAN_ATTRIBUTES: clean_attributes (fs); } exit(EXIT_OPER); } reiserfsprogs-3.6.9/fsck/semantic_rebuild.c0000444000077100007710000011071507705265615014536 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" int screen_width; int screen_curr_pos; char *screen_savebuffer; int screen_savebuffer_len; #define MIN(a, b) (((a)>(b))?(b):(a)) /* semantic pass progress */ void print_name (char * name, int len) { int i; if (fsck_quiet (fs)) return; if ( len + screen_curr_pos + 1 > screen_savebuffer_len) { char *t; t = expandmem(screen_savebuffer, screen_savebuffer_len + 1, len + screen_curr_pos - screen_savebuffer_len + 1); if (!t) { fsck_progress("\nOut of memory\n"); return; // ???? } screen_savebuffer = t; screen_savebuffer_len = len + screen_curr_pos + 1; } strcat(screen_savebuffer,"/"); strncat(screen_savebuffer,name,len); i = screen_curr_pos; screen_curr_pos += len+1; for ( ; i= screen_width ) { int t_preface=MIN(screen_curr_pos-screen_width,4); printf("%.*s%.*s", t_preface, "... ", screen_width-t_preface - 1, screen_savebuffer + ( screen_curr_pos - (screen_width - t_preface)) + 1); } else { int space_used=printf("%s", screen_savebuffer); for ( i=space_used; i < screen_width; i++) printf(" "); for ( i=space_used; i < screen_width; i++) printf("\b"); } } fflush (stdout); } /* *size is "real" file size, sd_size - size from stat data */ int wrong_st_size (struct key * key, unsigned long long max_file_size, int blocksize, __u64 * size, __u64 sd_size, int type) { if (sd_size <= max_file_size) { if (sd_size == *size) return 0; if (type == TYPE_DIRENTRY) { /* directory size must match to the sum of length of its entries */ fsck_log ("vpf-10650: The directory %K has the wrong size in the StatData " "(%Ld)%s(%Ld)\n", key, sd_size, fsck_mode(fs) == FSCK_CHECK ? ", should be " : " - corrected to ", *size); return 1; } if (sd_size > *size) { /* size in stat data can be bigger than size calculated by items */ if (fsck_adjust_file_size (fs) || type == TYPE_SYMLINK) { /* but it -o is given - fix that */ fsck_log ("vpf-10660: The file %K has too big size in the StatData " "(%Ld)%s(%Ld)\n", key, sd_size, fsck_mode(fs) == FSCK_CHECK ? ", should be " : " - corrected to ", *size); sem_pass_stat (fs)->fixed_sizes ++; return 1; } *size = sd_size; return 0; } if (!(*size % blocksize)) { /* last item is indirect */ if (((sd_size & ~(blocksize - 1)) == (*size - blocksize)) && sd_size % blocksize) { /* size in stat data is correct */ *size = sd_size; return 0; } } else { /* last item is a direct one */ if (!(*size % 8)) { if (((sd_size & ~7) == (*size - 8)) && sd_size % 8) { /* size in stat data is correct */ *size = sd_size; return 0; } } } } fsck_log ("vpf-10670: The file %K has the wrong size in the StatData (%Ld)%s(%Ld)\n", key, sd_size, fsck_mode(fs) == FSCK_CHECK ? ", should be " : " - corrected to ", *size); sem_pass_stat (fs)->fixed_sizes ++; return 1; } /* sd_blocks is 32 bit only */ /* old stat data shares sd_block and sd_dev - do not wipe sd_rdev out */ /* we should fix it as following: |------------------------------------------------------------------| | | 3.6 | 3.5 | |---------------------------------------------------| | | | blocks | r_dev|generation | blocks/r_dev | |------------------------------------------------------------------| | fifo, sockets | 0 | generation | 0 | | chr/blk_dev | 0 | maj:min | maj:min | | file, dir, link | blocks | generation | blocks | |------------------------------------------------------------------| */ int wrong_st_blocks (struct key * key, __u32 * blocks, __u32 sd_blocks, __u16 mode, int new_format) { int ret = 0; if (S_ISREG (mode) || S_ISLNK (mode) || S_ISDIR (mode)) { if (*blocks != sd_blocks) { fsck_log ("vpf-10680: The %s %K has the wrong block count in the StatData " "(%u)%s(%u)\n", S_ISDIR (mode) ? "directory" : "file", key, sd_blocks, fsck_mode(fs) == FSCK_CHECK ? ", should be " : " - corrected to ", *blocks); ret = 1; } } else if (new_format || (S_ISFIFO (mode) || S_ISSOCK (mode))) { if (sd_blocks != 0) { fsck_log ("vpf-10690: The object %K has the wrong block count in the StatData " "(%u)%s(%u)\n", key, sd_blocks, fsck_mode(fs) == FSCK_CHECK ? ", should be " : " - corrected to ", 0); *blocks = 0; ret = 1; } } return ret; } /* int wrong_st_rdev (struct key * key, __u32 * sd_rdev, __u16 mode, int new_format) { int ret = 0; if (!new_format) return 0; if (!S_ISCHR (mode) && !S_ISBLK (mode)) { if (*sd_rdev != 0) { fsck_log ("%s %K has wrong sd_rdev %u, has to be 0\n", S_ISDIR (mode) ? "dir" : "file", key, *sd_rdev); *sd_rdev = 0; ret = 1; } } return ret; } */ /* only regular files and symlinks may have items but stat data. Symlink should have body */ int wrong_mode (struct key * key, __u16 * mode, __u64 real_size, int symlink) { int retval = 0; if (S_ISLNK (*mode) && !symlink) { fsck_log ("The file %K (%M) is too big to be the symlink%s regfile\n", key, *mode, fsck_mode(fs) == FSCK_CHECK ? ", should be the" : " - corrected " "to the"); *mode &= ~S_IFMT; *mode |= S_IFREG; retval = 1; } if (ftypelet (*mode) != '?') { /* mode looks reasonable */ if (S_ISREG (*mode) || S_ISLNK (*mode)) return retval; /* device, pipe, socket have no items */ if (!real_size) return retval; } /* there are items, so change file mode to regular file. Otherwise - file bodies do not get deleted */ if (fsck_mode(fs) == FSCK_CHECK) { fsck_log ("The object %K has wrong mode (%M)\n", key, *mode); } else { fsck_log("The object %K has wrong mode (%M) - corrected to %M\n", key, *mode, (S_IFREG | 0600)); } *mode = (S_IFREG | 0600); return 1; } /* key is a key of last file item */ int wrong_first_direct_byte (struct key * key, int blocksize, __u32 * first_direct_byte, __u32 sd_first_direct_byte, __u32 size) { if (!size || is_indirect_key (key)) { /* there is no direct item */ *first_direct_byte = NO_BYTES_IN_DIRECT_ITEM; if (sd_first_direct_byte != NO_BYTES_IN_DIRECT_ITEM) { if (fsck_mode(fs) == FSCK_CHECK) { fsck_log ("The file %K: The wrong info about the tail in the StatData, " "first_direct_byte (%d) - should be (%d)\n", key, sd_first_direct_byte, *first_direct_byte); } else { fsck_log ("The file %K: The wrong info about the tail in the StatData, " "first_direct_byte (%d) - corrected to (%d)\n", key, sd_first_direct_byte, *first_direct_byte); } return 1; } return 0; } /* there is direct item */ *first_direct_byte = (get_offset (key) & ~(blocksize - 1)) + 1; if (*first_direct_byte != sd_first_direct_byte) { if (fsck_mode(fs) == FSCK_CHECK) { fsck_log ("The file %K: The wrong info about the tail in the StatData, " "first_direct_byte (%d) - should be (%d)\n", key, sd_first_direct_byte, *first_direct_byte); } else { fsck_log ("The file %K: The wrong info about the tail in the StatData, " "first_direct_byte (%d) - corrected to (%d)\n", key, sd_first_direct_byte, *first_direct_byte); } return 1; } return 0; } /* delete all items (but directory ones) with the same key 'ih' has (including stat data of not a directory) and put them back at the other place */ void relocate_dir (struct item_head * ih, int change_ih) { struct key key; struct key * rkey; struct path path; struct item_head * path_ih; struct si * si; __u32 new_objectid; /* starting with the leftmost one - look for all items of file, store them and delete */ key = ih->ih_key; set_type_and_offset (KEY_FORMAT_1, &key, SD_OFFSET, TYPE_STAT_DATA); si = 0; while (1) { reiserfs_search_by_key_4 (fs, &key, &path); if (get_item_pos (&path) == B_NR_ITEMS (get_bh (&path))) { rkey = uget_rkey (&path); if (rkey && !not_of_one_file (&key, rkey)) { /* file continues in the right neighbor */ key = *rkey; pathrelse (&path); continue; } /* there is no more items of a directory */ pathrelse (&path); break; } if (is_stat_data_ih (get_ih(&path))) fix_obviously_wrong_sd_mode (&path); path_ih = get_ih (&path); if (not_of_one_file (&key, &(path_ih->ih_key))) { /* there are no more item with this key */ pathrelse (&path); break; } /* ok, item found, but make sure that it is not a directory one */ if ((is_stat_data_ih (path_ih) && not_a_directory (get_item (&path))) || is_direct_ih (path_ih) || is_indirect_ih (path_ih)) { /* item of not a directory found. Leave it in the tree. FIXME: should not happen */ key = path_ih->ih_key; set_offset (KEY_FORMAT_1, &key, get_offset (&key) + 1); pathrelse (&path); continue; } /* directory stat data ro directory item */ si = save_and_delete_file_item (si, &path); } if (!si) { fsck_log ("relocate_dir: WARNING: No one item of the directory %K found\n", &key); return; } /* get new objectid for relocation or get objectid with which file was relocated already */ new_objectid = objectid_for_relocation (&ih->ih_key); set_key_objectid (&ih->ih_key, new_objectid); /* put all items removed back into tree */ while (si) { fsck_log ("relocate_dir: Moving %k to ", &si->si_ih.ih_key); set_key_objectid (&si->si_ih.ih_key, new_objectid); fsck_log ("%k\n", &si->si_ih.ih_key); if (get_offset (&(si->si_ih.ih_key)) == DOT_OFFSET) { /* fix "." entry to point to a directtory properly */ struct reiserfs_de_head * deh; deh = (struct reiserfs_de_head *)si->si_dnm_data; set_deh_objectid (deh, new_objectid); } insert_item_separately (&(si->si_ih), si->si_dnm_data, 1/*was in tree*/); si = remove_saved_item (si); } } /* path is path to stat data. If file will be relocated - new_ih will contain a key file was relocated with */ int rebuild_check_regular_file (struct path * path, void * sd, struct item_head * new_ih) { int is_new_file; // struct key sd_key; __u16 mode; __u32 nlink; __u64 real_size, saved_size; __u32 blocks, saved_blocks; /* proper values and value in stat data */ __u32 first_direct_byte, saved_first_direct_byte; struct buffer_head * bh; struct item_head * ih, sd_ih; int fix_sd; int symlnk = 0; int retval; retval = OK; /* stat data of a file */ ih = get_ih (path); bh = get_bh (path); if (new_ih) { /* this objectid is used already */ *new_ih = *ih; pathrelse (path); rewrite_file (new_ih, 1, 1); linked_already(&new_ih->ih_key); sem_pass_stat (fs)->oid_sharing_files_relocated ++; retval = RELOCATED; if (reiserfs_search_by_key_4 (fs, &(new_ih->ih_key), path) == ITEM_NOT_FOUND) reiserfs_panic ("%s: Could not find the StatData of the relocated file %k", __FUNCTION__, &(new_ih->ih_key)); /* stat data is marked unreachable again due to relocation, fix that */ ih = get_ih (path); bh = get_bh (path); mark_item_reachable (ih, bh); sd = get_item (path); } id_map_mark(semantic_id_map(fs), get_key_objectid (&ih->ih_key)); /* check and set nlink first */ get_sd_nlink (ih, sd, &nlink); nlink ++; set_sd_nlink (ih, sd, &nlink); mark_buffer_dirty (bh); if (nlink > 1) return retval; /* firts name of a file found */ if (get_ih_item_len (ih) == SD_SIZE) is_new_file = 1; else is_new_file = 0; get_sd_mode (ih, sd, &mode); get_sd_size (ih, sd, &saved_size); get_sd_blocks (ih, sd, &saved_blocks); if (!is_new_file) get_sd_first_direct_byte (ih, sd, &saved_first_direct_byte); /* we met this file first time */ if (S_ISREG (mode)) { sem_pass_stat(fs)->regular_files ++; } else if (S_ISLNK (mode)) { symlnk = 1; sem_pass_stat (fs)->symlinks ++; } else { sem_pass_stat (fs)->others ++; } sd_ih = *ih; // sd_key = sd_ih.ih_key; pathrelse (path); if (are_file_items_correct (&sd_ih, sd, &real_size, &blocks, 1/*mark items reachable*/, &symlnk) != 1) { /* unpassed items will be deleted in pass 4 as they left unaccessed */ sem_pass_stat (fs)->broken_files ++; } fix_sd = 0; fix_sd += wrong_mode (/*&sd_key, */ &sd_ih.ih_key, &mode, real_size, symlnk); if (!is_new_file) fix_sd += wrong_first_direct_byte (&sd_ih.ih_key, fs->fs_blocksize, &first_direct_byte, saved_first_direct_byte, real_size); fix_sd += wrong_st_size (/*&sd_key,*/ &sd_ih.ih_key, is_new_file ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1, fs->fs_blocksize, &real_size, saved_size, symlnk ? TYPE_SYMLINK : 0); fix_sd += wrong_st_blocks (&sd_ih.ih_key, &blocks, saved_blocks, mode, is_new_file); if (fix_sd) { /* find stat data and correct it */ set_type_and_offset (KEY_FORMAT_1, &sd_ih.ih_key, SD_OFFSET, TYPE_STAT_DATA); if (reiserfs_search_by_key_4 (fs, &sd_ih.ih_key, path) != ITEM_FOUND) reiserfs_panic ("%s: The StatData of the file %k could not be found", __FUNCTION__, &sd_ih.ih_key); bh = get_bh (path); ih = get_ih (path); sd = get_item (path); set_sd_size (ih, sd, &real_size); set_sd_blocks (ih, sd, &blocks); set_sd_mode (ih, sd, &mode); if (!is_new_file) set_sd_first_direct_byte (ih, sd, &first_direct_byte); mark_buffer_dirty (bh); } return retval; } static int is_rootdir_key (struct key * key) { if (comp_keys (key, &root_dir_key)) return 0; return 1; } /* returns buffer, containing found directory item.*/ static char * get_next_directory_item (struct key * key, /* on return this will contain key of next item in the tree */ struct key * parent, struct item_head * ih,/*not in tree*/ __u32 * pos_in_item) { INITIALIZE_PATH (path); char * dir_item; struct key * rdkey; struct buffer_head * bh; struct reiserfs_de_head * deh; int i; int retval; if ((retval = reiserfs_search_by_entry_key (fs, key, &path)) != POSITION_FOUND) reiserfs_panic ("get_next_directory_item: The current directory %k cannot be " "found", key); /* leaf containing directory item */ bh = PATH_PLAST_BUFFER (&path); *pos_in_item = path.pos_in_item; *ih = *get_ih (&path); deh = B_I_DEH (bh, ih); /* make sure, that ".." exists as well */ if (get_offset (key) == DOT_OFFSET) { if (get_ih_entry_count (ih) < 2 || name_in_entry_length (ih, deh + 1, 1) != 2 || strncmp (name_in_entry (deh + 1, 1), "..", 2)) { fsck_log ("get_next_directory_item: The entry \"..\" cannot be found in %k\n", &ih->ih_key); pathrelse (&path); return 0; } } /* mark hidden entries as visible, set "." and ".." correctly */ deh += *pos_in_item; for (i = *pos_in_item; i < get_ih_entry_count (ih); i ++, deh ++) { int namelen; char * name; name = name_in_entry (deh, i); namelen = name_in_entry_length (ih, deh, i); if (de_hidden (deh)) reiserfs_panic ("get_next_directory_item: item %k: hidden entry %d \'%.*s\'\n", key, i, namelen, name); if (get_deh_offset (deh) == DOT_OFFSET) { if (not_of_one_file (&(deh->deh2_dir_id), key)) { /* "." must point to the directory it is in */ //deh->deh_objectid != REISERFS_ROOT_PARENT_OBJECTID)/*????*/ { fsck_log ("get_next_directory_item: The entry \".\" of the directory %K pointes to %K, instead of %K", key, (struct key *)(&(deh->deh2_dir_id)), key); set_deh_dirid (deh, get_key_dirid (key)); set_deh_objectid (deh, get_key_objectid (key)); mark_buffer_dirty (bh); fsck_log (" - corrected\n"); } } if (get_deh_offset (deh) == DOT_DOT_OFFSET) { /* set ".." so that it points to the correct parent directory */ if (comp_short_keys (&(deh->deh2_dir_id), parent)) { fsck_log ("get_next_directory_item: The entry \"..\" of the directory %K pointes to %K, instead of %K", key, (struct key *)(&(deh->deh2_dir_id)), parent); set_deh_dirid (deh, get_key_dirid (parent)); set_deh_objectid (deh, get_key_objectid (parent)); mark_buffer_dirty (bh); fsck_log (" - corrected\n"); } } } /* copy directory item to the temporary buffer */ dir_item = getmem (get_ih_item_len (ih)); memcpy (dir_item, B_I_PITEM (bh, ih), get_ih_item_len (ih)); /* next item key */ if (PATH_LAST_POSITION (&path) == (B_NR_ITEMS (bh) - 1) && (rdkey = uget_rkey (&path))) copy_key (key, rdkey); else { set_key_dirid (key, 0); set_key_objectid (key, 0); } if (fsck_mode (fs) == FSCK_REBUILD) mark_item_reachable (get_ih (&path), bh); pathrelse (&path); return dir_item; } // get key of an object pointed by direntry and the key of the entry itself void get_object_key (struct reiserfs_de_head * deh, struct key * key, struct key * entry_key, struct item_head * ih) { /* entry points to this key */ set_key_dirid (key, get_deh_dirid (deh)); set_key_objectid (key, get_deh_objectid (deh)); set_key_offset_v1 (key, SD_OFFSET); set_key_uniqueness (key, 0); /* key of entry */ set_key_dirid (entry_key, get_key_dirid (&ih->ih_key)); set_key_objectid (entry_key, get_key_objectid (&ih->ih_key)); set_key_offset_v1 (entry_key, get_deh_offset (deh)); set_key_uniqueness (entry_key, DIRENTRY_UNIQUENESS); } int fix_obviously_wrong_sd_mode (struct path * path) { struct key * next_key = NULL; __u16 mode; int retval = 0; next_key = reiserfs_next_key (path); if (!next_key || not_of_one_file (next_key, &get_ih(path)->ih_key)) return 0; /* next item exists and of the same file. Fix the SD mode */ if (not_a_directory (get_item (path)) && is_direntry_key (next_key)) { /* make SD mode SD of dir */ get_sd_mode (get_ih (path), get_item (path), &mode); fsck_log ("The directory %K had wrong mode %M", &get_ih(path)->ih_key, mode); if (fsck_mode(fs) != FSCK_CHECK) { mode &= ~S_IFMT; mode |= S_IFDIR; fsck_log (" - corrected to %M\n", mode); set_sd_mode (get_ih (path), get_item (path), &mode); mark_buffer_dirty (get_bh(path)); } else { fsck_log ("\n"); retval = 1; } } else if (!not_a_directory (get_item (path)) && !is_direntry_key (next_key)) { /* make SD mode SD of regular file */ get_sd_mode (get_ih (path), get_item (path), &mode); fsck_log ("The file %K had wrong mode %M", &get_ih(path)->ih_key, mode); if (fsck_mode(fs) != FSCK_CHECK) { mode &= ~S_IFMT; mode |= S_IFREG; fsck_log (" - corrected to %M\n", mode); set_sd_mode (get_ih (path), get_item (path), &mode); mark_buffer_dirty (get_bh(path)); } else { fsck_log ("\n"); retval = 1; } } return retval; } /* check recursively the semantic tree. Returns OK if entry points to good object, STAT_DATA_NOT_FOUND if stat data was not found or RELOCATED when file was relocated because its objectid was already marked as used by another file */ int rebuild_semantic_pass (struct key * key, struct key * parent, int dot_dot, struct item_head * new_ih) { struct path path; void * sd; int is_new_dir; __u32 nlink; struct buffer_head * bh; struct item_head * ih; int retval, retval1; char * dir_item; __u32 pos_in_item; struct item_head tmp_ih; struct key item_key, entry_key, object_key; __u64 dir_size; __u32 blocks; __u64 saved_size; __u32 saved_blocks; int fix_sd; int relocate; int dir_format = 0; __u16 mode; retval = OK; start_again: /* when directory was relocated */ if (!KEY_IS_STAT_DATA_KEY (key)) reiserfs_panic ("rebuild_semantic_pass: The key %k must be key of a StatData", key); /* look for stat data of an object */ if (reiserfs_search_by_key_4 (fs, key, &path) == ITEM_NOT_FOUND) { pathrelse (&path); if (is_rootdir_key (key)) /* root directory has to exist at this point */ reiserfs_panic ("rebuild_semantic_pass: The root directory StatData was not found"); return STAT_DATA_NOT_FOUND; } /* stat data has been found */ bh = get_bh (&path); ih = get_ih (&path); sd = get_item(&path); /* */ get_sd_nlink (ih, sd, &nlink); relocate = 0; if (!nlink) { /* we reached the stat data for the first time */ if (id_map_mark(semantic_id_map(fs), get_key_objectid (&ih->ih_key))) { /* calculate number of found files/dirs who are using objectid which is used by another file */ sem_pass_stat (fs)->oid_sharing ++; if (1/*fsck_adjust_file_size (fs)*/) /* this works for files only */ relocate = 1; } mark_item_reachable (ih, bh); } fix_obviously_wrong_sd_mode (&path); if (not_a_directory (sd)) { retval = rebuild_check_regular_file (&path, sd, relocate ? new_ih : 0); pathrelse (&path); return retval; } if (relocate) { if (!new_ih) reiserfs_panic ("rebuild_semantic_pass: Memory is not prepared for relocation of %K", &ih->ih_key); *new_ih = *ih; pathrelse (&path); sem_pass_stat (fs)->oid_sharing_dirs_relocated ++; relocate_dir (new_ih, 1); linked_already(&new_ih->ih_key); *key = new_ih->ih_key; retval = RELOCATED; goto start_again; } /* it looks like stat data of a directory found */ if (nlink) { /* we saw this directory already */ if (!dot_dot) { /* this name is not ".." - and hard links are not allowed on directories */ pathrelse (&path); return STAT_DATA_NOT_FOUND; } else { /* ".." found */ nlink ++; set_sd_nlink (ih, sd, &nlink); mark_buffer_dirty (bh); pathrelse (&path); return OK; } } /* we see the directory first time */ sem_pass_stat (fs)->directories ++; nlink = 2; if (get_key_objectid (key) == REISERFS_ROOT_OBJECTID) nlink ++; set_sd_nlink (ih, sd, &nlink); mark_buffer_dirty (bh); if (get_ih_item_len (ih) == SD_SIZE) is_new_dir = 1; else is_new_dir = 0; /* { struct key * tmp; // check next item: if it is not a directory item of the same file // therefore sd_mode is corrupted so we just reset it to regular file // mode tmp = reiserfs_next_key (&path); if (tmp && !not_of_one_file (tmp, key) && !is_direntry_key (tmp)) { __u16 mode; get_sd_mode (ih, sd, &mode); fsck_log ("file %K had broken mode %M, ", key, mode); mode &= ~S_IFMT; mode |= S_IFREG; fsck_log ("fixed to %M\n", mode); set_sd_mode (ih, sd, &mode); nlink = 0; set_sd_nlink (ih, sd, &nlink); retval = rebuild_check_regular_file (&path, sd, 0); //no relocate pathrelse (&path); return retval; } } */ dir_format = (get_ih_item_len (get_ih (&path)) == SD_SIZE) ? KEY_FORMAT_2 : KEY_FORMAT_1; /* save stat data's size and st_blocks */ get_sd_size (ih, sd, &saved_size); get_sd_blocks (ih, sd, &saved_blocks); get_sd_mode (ih, sd, &mode); /* release path pointing to stat data */ pathrelse (&path); /* make sure that "." and ".." exist */ reiserfs_add_entry (fs, key, ".", name_length (".", dir_format), key, 1 << IH_Unreachable); reiserfs_add_entry (fs, key, "..", name_length ("..", dir_format), parent, 1 << IH_Unreachable); set_key_dirid (&item_key, get_key_dirid (key)); set_key_objectid (&item_key, get_key_objectid (key)); set_key_offset_v1 (&item_key, DOT_OFFSET); set_key_uniqueness (&item_key, DIRENTRY_UNIQUENESS); dir_size = 0; while ((dir_item = get_next_directory_item (&item_key, parent, &tmp_ih, &pos_in_item)) != 0) { /* dir_item is copy of the item in separately allocated memory, item_key is a key of next item in the tree */ int i; char * name = 0; int namelen, entry_len; struct reiserfs_de_head * deh = (struct reiserfs_de_head *)dir_item + pos_in_item; for (i = pos_in_item; i < get_ih_entry_count (&tmp_ih); i ++, deh ++) { struct item_head relocated_ih; if (name) { free (name); name = 0; } namelen = name_in_entry_length (&tmp_ih, deh, i); asprintf (&name, "%.*s", namelen, name_in_entry (deh, i)); entry_len = entry_length (&tmp_ih, deh, i); get_object_key (deh, &object_key, &entry_key, &tmp_ih); if ((dir_format == KEY_FORMAT_2) && (entry_len % 8 != 0)) { /* not alighed directory of new format - delete it */ fsck_log ("Entry %K (\"%.*s\") in the directory %K is not formated properly - fixed.\n", (struct key *)&(deh->deh2_dir_id), namelen, name, &tmp_ih.ih_key); reiserfs_remove_entry (fs, &entry_key); entry_len = name_length (name, dir_format); reiserfs_add_entry (fs, key, name, entry_len, (struct key *)&(deh->deh2_dir_id), 0); } /* if ((dir_format == KEY_FORMAT_1) && (namelen != entry_len)) { // aligned entry in directory of old format - remove and insert it back fsck_log ("Entry %K (\"%.*s\") in the directory %K is not formated properly - deleted\n", (struct key *)&(deh->deh2_dir_id), namelen, name, &tmp_ih.ih_key); reiserfs_remove_entry (fs, &entry_key); entry_len = name_length (name, dir_format); reiserfs_add_entry (fs, key, name, entry_len, (struct key *)&(deh->deh2_dir_id), 0); } */ if (is_dot (name, namelen)) { dir_size += DEH_SIZE + entry_len; continue; } print_name (name, namelen); if (!is_properly_hashed (fs, name, namelen, get_deh_offset (deh))) reiserfs_panic ("rebuild_semantic_pass: Hash mismatch detected for (\"%.*s\") in directory %K\n", namelen, name, &tmp_ih.ih_key); retval1 = rebuild_semantic_pass (&object_key, key, is_dot_dot (name, namelen), &relocated_ih); erase_name (namelen); switch (retval1) { case OK: dir_size += DEH_SIZE + entry_len; break; case STAT_DATA_NOT_FOUND: case DIRECTORY_HAS_NO_ITEMS: if (get_offset (&entry_key) == DOT_DOT_OFFSET && get_key_objectid (&object_key) == REISERFS_ROOT_PARENT_OBJECTID) { /* ".." of root directory can not be found */ dir_size += DEH_SIZE + entry_len; continue; } fsck_log ("%s: The entry %K (\"%.*s\") in directory %K points to nowhere - is removed\n", __FUNCTION__, &object_key, namelen, name, &tmp_ih.ih_key); reiserfs_remove_entry (fs, &entry_key); sem_pass_stat (fs)->deleted_entries ++; break; case RELOCATED: /* file was relocated, update key in corresponding directory entry */ if (reiserfs_search_by_entry_key (fs, &entry_key, &path) != POSITION_FOUND) { fsck_log ("WARNING: Cannot find the name of the relocated file %K in the directory %K\n", &object_key, &tmp_ih.ih_key); } else { /* update key dir entry points to */ struct reiserfs_de_head * tmp_deh; tmp_deh = B_I_DEH (get_bh (&path), get_ih (&path)) + path.pos_in_item; fsck_log ("The entry %K (\"%.*s\") in directory %K updated to point to ", &object_key, namelen, name, &tmp_ih.ih_key); set_deh_dirid (tmp_deh, get_key_dirid (&relocated_ih.ih_key)); set_deh_objectid (tmp_deh, get_key_objectid (&relocated_ih.ih_key)); fsck_log ("%K\n", &tmp_deh->deh2_dir_id); mark_buffer_dirty (get_bh (&path)); } dir_size += DEH_SIZE + entry_len; pathrelse (&path); break; } } /* for */ freemem (dir_item); free (name); name = 0; if (not_of_one_file (&item_key, key)) /* next key is not of this directory */ break; } /* while (dir_item) */ if (dir_size == 0) /* FIXME: is it possible? */ return DIRECTORY_HAS_NO_ITEMS; /* calc correct value of sd_blocks field of stat data */ blocks = dir_size2st_blocks (dir_size); fix_sd = 0; fix_sd += wrong_st_blocks (key, &blocks, saved_blocks, mode, is_new_dir); fix_sd += wrong_st_size (key, is_new_dir ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1, fs->fs_blocksize, &dir_size, saved_size, TYPE_DIRENTRY); if (fix_sd) { /* we have to fix either sd_size or sd_blocks, so look for stat data again */ if (reiserfs_search_by_key_4 (fs, key, &path) != ITEM_FOUND) reiserfs_panic ("rebuild_semantic_pass: The StatData of the file %K was not found", key); bh = get_bh (&path); ih = get_ih (&path); sd = get_item (&path); set_sd_size (ih, sd, &dir_size); set_sd_blocks (ih, sd, &blocks); mark_buffer_dirty (bh); pathrelse (&path); } return retval; } int is_dot (char * name, int namelen) { return (namelen == 1 && name[0] == '.') ? 1 : 0; } int is_dot_dot (char * name, int namelen) { return (namelen == 2 && name[0] == '.' && name[1] == '.') ? 1 : 0; } int not_a_directory (void * sd) { /* mode is at the same place and of the same size in both stat datas (v1 and v2) */ struct stat_data_v1 * sd_v1 = sd; return !(S_ISDIR (le16_to_cpu (sd_v1->sd_mode))); } int not_a_regfile (void * sd) { /* mode is at the same place and of the same size in both stat datas (v1 and v2) */ struct stat_data_v1 * sd_v1 = sd; return !(S_ISREG (le16_to_cpu (sd_v1->sd_mode))); } void zero_nlink (struct item_head * ih, void * sd) { int zero = 0; if (get_ih_item_len (ih) == SD_V1_SIZE && get_ih_key_format (ih) != KEY_FORMAT_1) { fsck_log ("zero_nlink: The StatData %k of the wrong format version (%d) - corrected to (%d)\n", ih, get_ih_key_format (ih), KEY_FORMAT_1); set_ih_key_format (ih, KEY_FORMAT_1); } if (get_ih_item_len (ih) == SD_SIZE && get_ih_key_format (ih) != KEY_FORMAT_2) { fsck_log ("zero_nlink: The StatData %k of the wrong format version (%d) - corrected to (%d)\n", ih, get_ih_key_format (ih), KEY_FORMAT_2); set_ih_key_format (ih, KEY_FORMAT_2); } set_sd_nlink (ih, sd, &zero); } void modify_item (struct item_head * ih, void * item) { zero_nlink (ih, item); mark_item_unreachable (ih); } /* mkreiserfs should have created this */ static void make_sure_lost_found_exists (reiserfs_filsys_t * fs) { int retval; INITIALIZE_PATH (path); unsigned int gen_counter; __u32 objectid; __u64 sd_size; __u32 sd_blocks; struct buffer_head * bh; struct item_head * ih; void * sd; int item_len; /* look for "lost+found" in the root directory */ retval = reiserfs_find_entry (fs, &root_dir_key, "lost+found", &gen_counter, &lost_found_dir_key); if (!retval) { objectid = id_map_alloc(proper_id_map(fs)); if (!objectid) { fsck_progress ("Could not allocate an objectid for \"/lost+found\", \ lost files will not be linked\n"); return; } set_key_dirid (&lost_found_dir_key, REISERFS_ROOT_OBJECTID); set_key_objectid (&lost_found_dir_key, objectid); } /* look for stat data of "lost+found" */ retval = reiserfs_search_by_key_4 (fs, &lost_found_dir_key, &path); if (retval == ITEM_NOT_FOUND) lost_found_dir_format = create_dir_sd (fs, &path, &lost_found_dir_key, modify_item); else { struct item_head * ih = get_ih (&path); if (!is_stat_data_ih (ih)) reiserfs_panic ("It must be lost+found's stat data %k\n", &ih->ih_key); fix_obviously_wrong_sd_mode (&path); if (not_a_directory (get_item (&path))) { fsck_progress ("\"/lost+found\" exists, but it is not a directory, \ lost files will not be linked\n"); set_key_objectid (&lost_found_dir_key, 0); pathrelse (&path); return; } lost_found_dir_format = (get_ih_item_len (get_ih (&path)) == SD_SIZE) ? KEY_FORMAT_2 : KEY_FORMAT_1; pathrelse (&path); } /* add "." and ".." if any of them do not exist */ reiserfs_add_entry (fs, &lost_found_dir_key, ".", name_length (".", lost_found_dir_format), &lost_found_dir_key, 1 << IH_Unreachable); reiserfs_add_entry (fs, &lost_found_dir_key, "..", name_length ("..", lost_found_dir_format), &root_dir_key, 1 << IH_Unreachable); item_len = reiserfs_add_entry (fs, &root_dir_key, "lost+found", name_length ("lost+found", root_dir_format), &lost_found_dir_key, 1 << IH_Unreachable); if (item_len) { if (reiserfs_search_by_key_4 (fs, &root_dir_key, &path) == ITEM_NOT_FOUND) reiserfs_panic ("%s: StatData of the root directory must exists", __FUNCTION__); bh = get_bh (&path); ih = get_ih (&path); sd = get_item(&path); get_sd_size (ih, sd, &sd_size); sd_size += item_len; set_sd_size (ih, sd, &sd_size); sd_blocks = dir_size2st_blocks (sd_size); set_sd_blocks (ih, sd, &sd_blocks); mark_buffer_dirty (bh); pathrelse (&path); } return; } /* Result of the rebuild pass will be saved in the state file which is needed to start * fsck again from the next pass. */ static void save_rebuild_semantic_result (reiserfs_filsys_t * fs) { FILE * file; int retval; file = open_file ("temp_fsck_file.deleteme", "w+"); if (!file) return; reiserfs_begin_stage_info_save (file, SEMANTIC_DONE); /* Method not implemented yet. reiserfs_objectid_map_save (file, semantic_id_map (fs)); */ reiserfs_end_stage_info_save (file); close_file (file); retval = rename ("temp_fsck_file.deleteme", state_dump_file (fs)); if (retval != 0) fsck_progress ("%s: Could not rename the temporary file temp_fsck_file.deleteme to %s", __FUNCTION__, state_dump_file (fs)); } /* we have nothing to load from a state file, but we have to fetch on-disk bitmap, copy it to allocable bitmap, and fetch objectid map */ void load_semantic_result (FILE * file, reiserfs_filsys_t * fs) { fsck_new_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_copy (fsck_new_bitmap (fs), fs->fs_bitmap2); fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_copy (fsck_allocable_bitmap (fs), fs->fs_bitmap2); fs->block_allocator = reiserfsck_reiserfs_new_blocknrs; fs->block_deallocator = reiserfsck_reiserfs_free_block; /* we need objectid map on semantic pass to be able to relocate files */ proper_id_map (fs) = id_map_init(); /* Not implemented yet. fetch_objectid_map (proper_id_map (fs), fs); semantic_id_map (fs) = reiserfs_objectid_map_load (file); */ } static void before_pass_3 (reiserfs_filsys_t * fs) { semantic_id_map (fs) = id_map_init(); } static void after_pass_3 (reiserfs_filsys_t * fs) { /* update super block: objectid map, fsck state */ set_sb_fs_state (fs->fs_ondisk_sb, SEMANTIC_DONE); mark_buffer_dirty (fs->fs_super_bh); /* write all dirty blocks */ fsck_progress ("Flushing.."); id_map_flush(proper_id_map (fs), fs); fs->fs_dirt = 1; reiserfs_flush_to_ondisk_bitmap (fsck_new_bitmap(fs), fs); reiserfs_flush (fs); fsck_progress ("finished\n"); stage_report (3, fs); if (!fsck_run_one_step (fs)) { if (fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1)) /* reiserfsck continues */ return; } save_rebuild_semantic_result (fs); id_map_free(proper_id_map (fs)); proper_id_map (fs) = 0; fs->fs_dirt = 1; reiserfs_close (fs); exit(0); } /* this is part of rebuild tree */ void pass_3_semantic (reiserfs_filsys_t * fs) { before_pass_3 (fs); fsck_progress ("Pass 3 (semantic):\n"); /* when warnings go not to stderr - separate them in the log */ if (fsck_log_file (fs) != stderr) fsck_log ("####### Pass 3 #########\n"); if (!fs->fs_hash_function) reiserfs_panic ("Hash function should be selected already"); make_sure_root_dir_exists (fs, modify_item, 1 << IH_Unreachable); make_sure_lost_found_exists (fs); id_map_mark(proper_id_map(fs), get_key_objectid(&root_dir_key)); id_map_mark(proper_id_map(fs), get_key_objectid(&lost_found_dir_key)); /* link all relocated files into /lost+found directory */ link_relocated_files (); rebuild_semantic_pass (&root_dir_key, &parent_root_dir_key, 0/*!dot_dot*/, 0/*reloc_ih*/); add_badblock_list(fs, 1); after_pass_3 (fs); } reiserfsprogs-3.6.9/fsck/uobjectid.c0000664000077100007710000002062007665645672013206 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" /* when --check fsck builds a map of objectids of files it finds in the tree when --rebuild-tree - fsck builds map of objectids it inserts into tree */ #define ALLOC_SIZE 1024 #define MAX_ID (~0ul) /* 2 bytes for the counter */ #define BM_SIZE (ALLOC_SIZE - sizeof(__u16)) #define BM_INTERVAL (BM_SIZE * 8) #define INDEX_COUNT (MAX_ID / BM_INTERVAL) #define id_map_interval(map, id) (map->index + (id / BM_INTERVAL)) #define id_map_local_count(interval) (interval + BM_SIZE) typedef struct sb_id_map { __u32 * m_begin; __u32 m_size, m_used_slot_count; } sb_id_map_t; id_map_t *id_map_init() { id_map_t *map; __u32 i; map = getmem(sizeof(id_map_t)); map->index = mem_alloc(INDEX_COUNT * sizeof(void *)); for (i = 0; i < INDEX_COUNT; i++) { if (map->index[i] != (void *)0) map->index[i] = (void *)0; } id_map_mark(map, 0); id_map_mark(map, 1); /* id == 0 should not be there, just for convinient usage */ map->count--; return map; } void id_map_free(id_map_t *map) { __u32 i; for (i = 0; i < INDEX_COUNT; i++) { if (map->index[i] != (void *)0 && map->index[i] != (void *)1) freemem(map->index[i]); } freemem(map->index); freemem(map); } int id_map_test(id_map_t *map, __u32 id) { void **interval = id_map_interval(map, id); if (*interval == (void *)0) return 0; if (*interval == (void *)1) return 1; return misc_test_bit(id % BM_INTERVAL, *interval); } int id_map_mark(id_map_t *map, __u32 id) { void **interval = id_map_interval(map, id); if (*interval == (void *)0) *interval = getmem(ALLOC_SIZE); if (*interval == (void *)1) return 1; if (misc_test_bit(id % BM_INTERVAL, *interval)) return 1; misc_set_bit(id % BM_INTERVAL, *interval); (*(__u16 *)id_map_local_count(*interval))++; map->count++; if ((*(__u16 *)id_map_local_count(*interval)) == BM_INTERVAL) { /* Dealloc fully used bitmap */ freemem(*interval); *interval = (void *)1; } if (map->last_used < (id / BM_INTERVAL)) map->last_used = id / BM_INTERVAL; return 0; } /* call this for proper_id_map only!! */ __u32 id_map_alloc(id_map_t *map) { __u32 i, zero_count; __u32 id = 0, first = ~0ul; for (i = 0, zero_count = 0; zero_count < 10 && i < INDEX_COUNT - 1; i++) { if (map->index[i] == (void *)0) { if (zero_count == 0) first = i; zero_count++; } else if (map->index[i] != (void *)1) break; } if (map->index[i] != (void *)1 && map->index[i] != (void *)0) { id = misc_find_first_zero_bit(map->index[i], BM_INTERVAL); if (id >= BM_INTERVAL) die ("Id is out of interval size, interval looks corrupted."); id += i * BM_INTERVAL; } else if (first != ~0ul) { id = first * BM_INTERVAL; if (id == 0) id = 2; } else die ("%s: No more free objectid is available.", __FUNCTION__); id_map_mark(map, id); return id; } /* this could be used if some more sofisticated flushing will be needed. */ /* static void sb_id_map_pack(sb_id_map_t *map) { map->m_begin[1] = map->m_begin[map->m_used_slot_count - 1]; memset(map->m_begin + 2, 0, map->m_used_slot_count - 2); map->m_used_slot_count = 2; }*/ static __u32 id_map_next_bound(id_map_t *map, __u32 start) { __u32 index = start / BM_INTERVAL; __u32 offset = start % BM_INTERVAL; int look_for; if (map->index[index] == (void *)0) look_for = 1; else if (map->index[index] == (void *)1) look_for = 0; else look_for = !misc_test_bit(offset, map->index[index]); offset++; start_again: if (look_for) { while (index < INDEX_COUNT && map->index[index] == (void *)0) index++; if (index == INDEX_COUNT) return 0; if (map->index[index] == (void *)1) return index * BM_INTERVAL; offset = misc_find_next_set_bit(map->index[index], BM_INTERVAL, offset); if (offset >= BM_INTERVAL) { offset = 0; index++; goto start_again; } return index * BM_INTERVAL + offset; } else { while (index < INDEX_COUNT && map->index[index] == (void *)1) index++; if (index == INDEX_COUNT) return 0; if (map->index[index] == (void *)0) return index * BM_INTERVAL; offset = misc_find_next_zero_bit(map->index[index], BM_INTERVAL, offset); if (offset >= BM_INTERVAL) { offset = 0; index++; goto start_again; } return index * BM_INTERVAL + offset; } } void id_map_flush(struct id_map * map, reiserfs_filsys_t * fs) { int size, max, i; __u32 id, prev_id; __u32 * sb_objectid_map; size = reiserfs_super_block_size (fs->fs_ondisk_sb); sb_objectid_map = (__u32 *)((char *)(fs->fs_ondisk_sb) + size); max = ((fs->fs_blocksize - size) >> 3 << 1); set_sb_oid_maxsize (fs->fs_ondisk_sb, max); sb_objectid_map[0] = id = 1; for (i = 1; i < max - 1; i++) { sb_objectid_map[i] = id = id_map_next_bound(map, id); if (id == 0) { if (i % 2) die ("%s: Used interval is not closed on flushing.", __FUNCTION__); break; } } if (map->index[map->last_used] == (void *)0) die ("Object id map looks corrupted - last used interval cannot be zeroed."); i++; if (i == max) { if (id == 0) die ("Objectid interval does not contain any set bit what is expected."); if (map->index[map->last_used] == (void *)1) { prev_id = BM_INTERVAL - 1; } else { prev_id = ~0ul; if (id < map->last_used * BM_INTERVAL) id = 0; else id %= BM_INTERVAL; if (misc_test_bit(id, map->index[map->last_used])) prev_id = id; while ((id = misc_find_next_set_bit(map->index[map->last_used], BM_INTERVAL, (id + 1))) != BM_INTERVAL) { prev_id = id; } if (prev_id == ~0ul) die ("Objectid interval does not contain any set bit what is expected."); prev_id++; } sb_objectid_map[max - 1] = prev_id + map->last_used * BM_INTERVAL; } else { i--; memset(sb_objectid_map + i, 0, (max - i) * sizeof (__u32)); } set_sb_oid_cursize (fs->fs_ondisk_sb, i); } /* FIXME: these 3 methods must be implemented also. void fetch_objectid_map (struct id_map * map, reiserfs_filsys_t * fs) { int sb_size; __u32 * sb_objectid_map; sb_size = reiserfs_super_block_size (fs->fs_ondisk_sb); sb_objectid_map = (__u32 *)((char *)(fs->fs_ondisk_sb) + sb_size); if (map->m_page_count != 1) die ("fetch_objectid_map: can not fetch long map"); make_id_space(map, 0); memcpy (map->m_begin, sb_objectid_map, get_sb_oid_cursize (fs->fs_ondisk_sb) * sizeof (__u32)); map->m_used_slot_count = get_sb_oid_cursize (fs->fs_ondisk_sb); } #define OBJMAP_START_MAGIC 375331 #define OBJMAP_END_MAGIC 7700472 void reiserfs_objectid_map_save (FILE * fp, struct id_map * id_map) { __u32 v; int i; v = OBJMAP_START_MAGIC; fwrite (&v, 4, 1, fp); v = id_map->m_used_slot_count; fwrite (&v, 4, 1, fp); for (i = 0; i < id_map->m_page_count - 1; i++) { fwrite ((char *)id_map->m_begin + MAP_SIZE * i, 4, 1, fp); } for (i = 0; i < id_map->m_used_slot_count * sizeof(__u32) - (id_map->m_page_count - 1) * MAP_SIZE; i++) { fwrite ((char *)id_map->m_begin + MAP_SIZE * (id_map->m_page_count - 1) + i, 4, 1, fp); } v = OBJMAP_END_MAGIC; fwrite (&v, 4, 1, fp); } struct id_map * reiserfs_objectid_map_load (FILE * fp) { __u32 v; int i; struct id_map * id_map; fread (&v, 4, 1, fp); if (v != OBJMAP_START_MAGIC) { reiserfs_warning (stderr, "reiserfs_objectid_map_load: no objectid map begin magic found"); return 0; } // read bit size of objectid map fread (&v, 4, 1, fp); id_map = init_id_map (MAP_NOT_PACKED); id_map->m_used_slot_count = v; id_map->m_page_count = v / MAP_SIZE + 1; id_map->m_begin = expandmem (id_map->m_begin, 0, id_map->m_page_count * MAP_SIZE); for (i = 0; i < id_map->m_page_count - 1; i++) { fread ((char *)id_map->m_begin + MAP_SIZE * i, 4, 1, fp); } for (i = 0; i < id_map->m_used_slot_count * sizeof(__u32) - (id_map->m_page_count - 1) * MAP_SIZE; i++) { fread ((char *)id_map->m_begin + MAP_SIZE * (id_map->m_page_count - 1) + i, 4, 1, fp); } fread (&v, 4, 1, fp); if (v != OBJMAP_END_MAGIC) { reiserfs_warning (stderr, "reiserfs_objectid_map_load: no objectid map end magic found"); return 0; } fflush (stderr); return id_map; } */ reiserfsprogs-3.6.9/fsck/pass0.c0000664000077100007710000020106607705261642012253 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" /* * Pass0 scans the used part of the partition. It creates two maps which will * be used on the pass 1. These are a map of nodes looking like leaves and * a map of "bad" unformatted nodes. After pass 0 we can detect unformatted * node pointers pointing to leaves. */ /* leaves */ reiserfs_bitmap_t * leaves_bitmap; #define pass0_is_leaf(block) __is_marked (leaves, block) #define pass0_mark_leaf(block) __mark (leaves, block) /* nodes which are referred to from only one indirect item */ reiserfs_bitmap_t * good_unfm_bitmap; #define pass0_is_good_unfm(block) __is_marked (good_unfm, block) #define pass0_mark_good_unfm(block) __mark (good_unfm, block) #define pass0_unmark_good_unfm(block) __unmark (good_unfm, block) /* nodes which are referred to from more than one indirect item */ reiserfs_bitmap_t * bad_unfm_bitmap; #define pass0_is_bad_unfm(block) __is_marked (bad_unfm, block) #define pass0_mark_bad_unfm(block) __mark (bad_unfm, block) #define pass0_unmark_bad_unfm(block) __unmark (bad_unfm, block) static int correct_direct_item_offset (__u64 offset, int format) { if (format == KEY_FORMAT_2) { return (offset && ((offset - 1) % 8 == 0)); } else { return (offset); } return 0; } /* bitmaps which are built on pass 0 and are used on pass 1 */ static void make_aux_bitmaps (reiserfs_filsys_t * fs) { struct reiserfs_super_block * sb; sb = fs->fs_ondisk_sb; /* bitmap of leaves found on the device */ leaves_bitmap = reiserfs_create_bitmap (get_sb_block_count (sb)); good_unfm_bitmap = reiserfs_create_bitmap (get_sb_block_count (sb)); bad_unfm_bitmap = reiserfs_create_bitmap (get_sb_block_count (sb)); } void delete_aux_bitmaps (void) { reiserfs_delete_bitmap (leaves_bitmap); reiserfs_delete_bitmap (good_unfm_bitmap); reiserfs_delete_bitmap (bad_unfm_bitmap); } /* register block some indirect item points to */ static void register_unfm (unsigned long block) { if (!pass0_is_good_unfm (block) && !pass0_is_bad_unfm (block)) { /* this block was not pointed by other indirect items yet */ pass0_mark_good_unfm (block); return; } if (pass0_is_good_unfm (block)) { /* block was pointed once already, unmark it in bitmap of good unformatted nodes and mark in bitmap of bad pointers */ pass0_unmark_good_unfm (block); pass0_mark_bad_unfm (block); return; } assert (pass0_is_bad_unfm (block)); } /* 'upper' item is correct if 'upper + 2' exists and its key is greater than key of 'upper' */ static int upper_correct (struct buffer_head * bh, struct item_head * upper, int upper_item_num) { if (upper_item_num + 2 < B_NR_ITEMS (bh)) { if (comp_keys (&upper->ih_key, &(upper + 2)->ih_key) != -1) /* item-num's item is out of order of order */ return 0; return 1; } /* there is no item above the "bad pair" */ return 2; } /* 'lower' item is correct if 'lower - 2' exists and its key is smaller than key of 'lower' */ static int lower_correct (struct buffer_head * bh, struct item_head * lower, int lower_item_num) { if (lower_item_num - 2 >= 0) { if (comp_keys (&(lower - 2)->ih_key, &lower->ih_key) != -1) return 0; return 1; } return 2; } /* return 1 if something was changed */ static int correct_key_format (struct item_head * ih, int symlink) { int dirty = 0; if (is_stat_data_ih (ih)) { /* for stat data we have no way to check whether key format in item head matches to the key format found from the key directly */ if (get_ih_item_len (ih) == SD_V1_SIZE) { if (get_ih_key_format (ih) != KEY_FORMAT_1) { /*fsck_log ("correct_key_format: ih_key_format of (%H) is set to format 1\n", ih);*/ set_ih_key_format (ih, KEY_FORMAT_1); return 1; } return 0; } if (get_ih_item_len (ih) == SD_SIZE) { if (get_ih_key_format (ih) != KEY_FORMAT_2) { /*fsck_log ("correct_key_format: ih_key_format of (%H) is set to format 2\n", ih);*/ set_ih_key_format (ih, KEY_FORMAT_2); return 1; } return 0; } die ("stat_data item of the wrong length"); } if (symlink && is_direct_ih(ih) && (key_format(&ih->ih_key) != KEY_FORMAT_1)) { /* All symlinks are of 3.5 format */ /*fsck_log ("correct_key_format: Symlink keys should be of 3.5 format. %k - fixed.\n", &ih->ih_key); */ set_type_and_offset(KEY_FORMAT_1, &ih->ih_key, get_offset(&ih->ih_key), get_type(&ih->ih_key)); } if (key_format (&ih->ih_key) != get_ih_key_format (ih)) { /*fsck_log ("correct_key_format: ih_key_format of (%H) is set to format found in the key\n", ih);*/ set_ih_key_format (ih, key_format (&ih->ih_key)); dirty = 1; } if (is_direct_ih (ih) && get_offset (&ih->ih_key) > fs->fs_blocksize * 4) { /*fsck_log ("correct_key_format: %H made of indirect type\n", ih);*/ set_type (key_format (&ih->ih_key), &ih->ih_key, TYPE_INDIRECT); if (get_offset (&ih->ih_key) % fs->fs_blocksize != 1) fsck_log ("correct_key_format: Item header's key has the wrong offset %H\n", ih); dirty = 1; } return dirty; } #if 0 /* fixme: we might try all available hashes */ static int prob_name (reiserfs_filsys_t * fs, char ** name, int max_len, __u32 deh_offset) { int start; /* */ int len; for (start = 0; start < max_len; start ++) { for (len = 0; len < max_len - start; len ++) { if (is_properly_hashed (fs, *name + start, len + 1, deh_offset)) { *name = *name + start; return len + 1; } } } return 0; } #endif static void hash_hits_init (reiserfs_filsys_t * fs) { fsck_data (fs)->rebuild.hash_amount = known_hashes (); fsck_data (fs)->rebuild.hash_hits = getmem (sizeof (unsigned long) * fsck_data (fs)->rebuild.hash_amount); return; } static void add_hash_hit (reiserfs_filsys_t * fs, int hash_code) { fsck_data (fs)->rebuild.hash_hits [hash_code] ++; } /* deh_location look reasonable, try to find name length. return 0 if we failed */ static int try_to_get_name_length (struct item_head * ih, struct reiserfs_de_head * deh, int i) { int len; if (i == 0 || !de_bad_location (deh - 1)) { len = name_in_entry_length (ih, deh, i); return (len > 0) ? len : 0; } /* previous entry had bad location so we had no way to find name length */ return 0; } /* define this if you are using -t to debug recovering of corrupted directory item */ #define DEBUG_VERIFY_DENTRY #undef DEBUG_VERIFY_DENTRY /* check directory item and try to recover something */ static int verify_directory_item (reiserfs_filsys_t * fs, struct buffer_head * bh, int item_num) { struct item_head * ih; struct item_head tmp; char * item; struct reiserfs_de_head * deh; char * name; int name_len; int bad, lost_found; int i, j; char buf[4096]; int dirty; int hash_code; int bad_locations; int min_entry_size = 1; #ifdef DEBUG_VERIFY_DENTRY char * direntries; #endif ih = B_N_PITEM_HEAD (bh, item_num); item = B_I_PITEM (bh,ih); deh = (struct reiserfs_de_head *)item; dirty = 0; bad_locations = 0; if ( (get_ih_entry_count (ih) > (get_ih_item_len(ih) / (DEH_SIZE + min_entry_size))) || (get_ih_entry_count (ih) == 0)) set_ih_entry_count (ih, (int)get_ih_item_len(ih) / (DEH_SIZE + min_entry_size)); if (get_ih_entry_count (ih) == 0) { delete_item (fs, bh, item_num); return -1; } /* check deh_location */ for (i = 0; i < get_ih_entry_count (ih); i ++) { /* silently fix deh_state */ if (get_deh_state (deh + i) != (1 << DEH_Visible2)) { set_deh_state (deh + i, (1 << DEH_Visible2)); mark_buffer_dirty (bh); } if (dir_entry_bad_location (deh + i, ih, !i)) mark_de_bad_location (deh + i); } #ifdef DEBUG_VERIFY_DENTRY direntries = getmem (ih_entry_count (ih) * sizeof (int)); printf ("Entries with bad locations within the directory: "); for (i = 0; i < ih_entry_count (ih); i ++) { if (de_bad_location (deh + i)) printf ("%d ", i); } printf ("\n"); #endif /* DEBUG_VERIFY_DENTRY */ /* find entries names in which have mismatching deh_offset */ for (i = get_ih_entry_count (ih) - 1; i >= 0; i --) { if (de_bad (deh + i)) /* bad location */ continue; if (i) { if (get_deh_location (deh + i - 1) < get_deh_location (deh + i)) mark_de_bad_location (deh + i - 1); } name = name_in_entry (deh + i, i); /* Although we found a name, we not always can get its length as it depends on deh_location of previous entry. */ name_len = try_to_get_name_length (ih, deh + i, i); #ifdef DEBUG_VERIFY_DENTRY if (name_len == 0) printf ("Trying to find the name length for %d-th entry\n", i); #endif /* DEBUG_VERIFY_DENTRY */ if (is_dot (name, name_len)) { if (i != 0) fsck_log ("block %lu: item %d: \".\" must be the first entry, but it is the %d-th entry\n", bh->b_blocknr, item_num, i); /* check and fix "." */ if (get_deh_offset (deh + i) != DOT_OFFSET) { set_deh_offset (deh + i, DOT_OFFSET); mark_buffer_dirty (bh); } /* "." must point to the directory it is in */ /* if (not_of_one_file (&(deh[i].deh2_dir_id), &(ih->ih_key))) { fsck_log ("verify_direntry: block %lu, item %H has entry \".\" " "pointing to (%K) instead of (%K)\n", bh->b_blocknr, ih, &(deh[i].deh2_dir_id), &(ih->ih_key)); set_deh_dirid (deh + i, get_key_dirid (&ih->ih_key)); set_deh_objectid (deh + i, get_key_objectid (&ih->ih_key)); mark_buffer_dirty (bh); } */ } else if (is_dot_dot (name, name_len)) { if (i != 1) fsck_log ("block %lu: item %d: \"..\" is %d-th entry\n", bh->b_blocknr, item_num, i); /* check and fix ".." */ if (get_deh_offset (deh + i) != DOT_DOT_OFFSET) { set_deh_offset (deh + i, DOT_DOT_OFFSET); mark_buffer_dirty (bh); } } else { int min_length, max_length; /* check other name */ if (name_len == 0) { /* we do not know the length of name - we will try to find it */ min_length = 1; max_length = item + get_ih_item_len (ih) - name; } else /* we kow name length, so we will try only one name length */ min_length = max_length = name_len; hash_code = 0; for (j = min_length; j <= max_length; j ++) { hash_code = find_hash_in_use (name, j, GET_HASH_VALUE (get_deh_offset (deh + i)), get_sb_hash_code (fs->fs_ondisk_sb)); /* add_hash_hit (fs, hash_code);*/ if (code2func (hash_code) != 0) { /* deh_offset matches to some hash of the name */ if (fsck_hash_defined (fs) && hash_code != func2code (fs->fs_hash_function)) { /* wrong hash selected - so we can skip this leaf */ return 1; } if (!name_len) { fsck_log ("%s: block %lu, item %H: Found a name \"%.*s\" for %d-th entry " "matching to the hash %u.\n", __FUNCTION__, bh->b_blocknr, ih, j, name, i, get_deh_offset (deh + i)); /* FIXME: if next byte is 0 we think that the name is aligned to 8 byte boundary */ if (i) { set_deh_location (&deh[i - 1], get_deh_location (deh + i) + ((name[j] || fs->fs_format == REISERFS_FORMAT_3_5) ? j : ROUND_UP (j))); mark_de_good_location (deh + i - 1); mark_buffer_dirty (bh); } } break; } } add_hash_hit (fs, hash_code); if (j == max_length + 1) { /* deh_offset does not match to anything. it will be deleted for now, but maybe we could just fix a deh_offset if it is in ordeer */ mark_de_bad_offset (deh + i); } } } /* for */ #ifdef DEBUG_VERIFY_DENTRY printf ("Entries with mismatching hash: "); for (i = 0; i < ih_entry_count (ih); i ++) { if (de_bad_offset (deh + i)) printf ("%d ", i); } printf ("\n"); #endif /* DEBUG_VERIFY_DENTRY */ /* correct deh_locations such that code cutting entries will not get screwed up */ { int prev_loc; int loc_fixed; prev_loc = get_ih_item_len (ih); for (i = 0; i < get_ih_entry_count (ih); i ++) { loc_fixed = 0; if (de_bad_location (deh + i)) { set_deh_location (deh + i, prev_loc/* - 1*/); mark_buffer_dirty (bh); loc_fixed = 1; } else { if (get_deh_location (deh + i) >= prev_loc) { set_deh_location (deh + i, prev_loc/* - 1*/); mark_buffer_dirty (bh); loc_fixed = 1; } } prev_loc = get_deh_location (deh + i); if (i == get_ih_entry_count (ih) - 1) { /* last entry starts right after an array of dir entry headers */ if (!de_bad (deh + i) && get_deh_location (deh + i) != (DEH_SIZE * get_ih_entry_count (ih))) { /* free space in the directory item */ fsck_log ("%s: block %lu, item %H: Directory item has a free space - deleting\n", __FUNCTION__, bh->b_blocknr, ih); cut_entry (fs, bh, item_num, get_ih_entry_count (ih), 0); } if (get_deh_location (deh + i) != (DEH_SIZE * get_ih_entry_count (ih))) { set_deh_location (&deh[i], (DEH_SIZE * get_ih_entry_count (ih))); loc_fixed = 1; mark_buffer_dirty (bh); } } #ifdef DEBUG_VERIFY_DENTRY if (loc_fixed) direntries [i] = 1; #endif } /* for */ #ifdef DEBUG_VERIFY_DENTRY printf ("Entries with fixed deh_locations: "); for (i = 0; i < ih_entry_count (ih); i ++) { if (direntries [i]) printf ("%d ", i); } printf ("\n"); #endif /* DEBUG_VERIFY_DENTRY */ } #ifdef DEBUG_VERIFY_DENTRY printf (" N location name\n"); for (i = 0; i < ih_entry_count (ih); i ++) { if (de_bad (deh + i) || (i && de_bad (deh + i - 1)) || /* previous entry marked bad */ (i < ih_entry_count (ih) - 1 && de_bad (deh + i + 1))) { /* next entry is marked bad */ /* print only entries to be deleted and their nearest neighbors */ printf ("%3d: %8d ", i, deh_location (deh + i)); if (de_bad (deh + i)) printf ("will be deleted\n"); else printf ("\"%.*s\"\n", name_in_entry_length (ih, deh + i, i), name_in_entry (deh + i, i)); } } #endif bad = lost_found = 0; tmp = *ih; /* mark enries of /lost+found as bad */ deh = B_I_DEH (bh, ih); for (i = 0; i < get_ih_entry_count (ih); i ++, deh ++) { unsigned int dirid, objectid; if (de_bad (deh)) continue; sprintf (buf, "%.*s", name_in_entry_length (ih, deh, i), name_in_entry (deh, i)); if (sscanf (buf, "%d_%d", &dirid, &objectid) != 2) continue; if (get_deh_dirid (deh) != dirid || get_deh_objectid (deh) != objectid) continue; /* entry in lost+found */ // printf ("%s - will be deleted\n", buf); lost_found++; mark_de_bad_offset (deh); } /* delete entries which are marked bad */ for (i = 0; i < get_ih_entry_count (ih); i ++) { deh = B_I_DEH (bh, ih) + i; if (de_bad (deh)) { bad ++; if (get_ih_entry_count (ih) == 1) { delete_item (fs, bh, item_num); break; } else { cut_entry (fs, bh, item_num, i, 1); } i --; } } if (bad == get_ih_entry_count (&tmp) && lost_found != bad) { fsck_log ("%s: block %lu, item %H: All entries were deleted from the directory\n", __FUNCTION__, bh->b_blocknr, &tmp); return -1; } deh = B_I_DEH (bh, ih); if (get_offset (&ih->ih_key) != get_deh_offset (deh)) { fsck_log ("verify_direntry: block %lu, item %H: Key's offset %k must match the directory's hash (%u) - changed.\n", bh->b_blocknr, ih, &ih->ih_key, get_deh_offset (deh)); set_offset (key_format (&ih->ih_key), &ih->ih_key, get_deh_offset (deh)); mark_buffer_dirty (bh); } if (bad > lost_found) fsck_log ("pass0: block %lu, item %H: %d entries were deleted\n", bh->b_blocknr, &tmp, bad - lost_found); return 0; } static __inline__ int does_it_fit_into_dev (__u64 offset, __u64 fs_size) { /* Count of unformatted pointers - offset / blocksize Count of blocks to store them - UNFM_P_SIZE * offset / blocksize / MAX_ITEM_LEN Size to store it - blocksize * UNFM_P_SIZE * offset / blocksize / MAX_ITEM_LEN */ return ( UNFM_P_SIZE * offset / MAX_ITEM_LEN(fs->fs_blocksize) < fs_size) ? 1 : 0; } static int is_wrong_short_key (struct key * key) { if (get_key_dirid (key) == 0 || get_key_objectid (key) == 0 || get_key_objectid (key) == 1 || get_key_dirid (key) == ~0ul || get_key_objectid (key) == ~0ul || get_key_dirid (key) == get_key_objectid (key) || (get_key_dirid (key) == 1 && get_key_objectid (key) != 2) || (get_key_dirid (key) != 1 && get_key_objectid (key) == 2) ) return 1; return 0; } /* 1 if some of fields in the block head of bh look bad */ int leaf_structure_check (reiserfs_filsys_t * fs, struct buffer_head * bh) { struct block_head * blkh; int free_space, counted; blkh = B_BLK_HEAD (bh); if (!is_leaf_block_head(bh->b_data)) { /* We should not get here on rebuild. */ fsck_log ("block %lu: The block does not look like a leaf.\n", bh->b_blocknr); one_more_corruption (fs, FATAL); return 1; } counted = leaf_count_ih(bh->b_data, bh->b_size); if (counted < get_blkh_nr_items (blkh)) { fsck_log ("block %lu: The number of items (%lu) is incorrect, should be (%lu)", bh->b_blocknr, get_blkh_nr_items(blkh), counted); if (fsck_mode(fs) == FSCK_REBUILD) { set_blkh_nr_items(blkh, counted); fsck_log (" - corrected\n"); mark_buffer_dirty (bh); } else { fsck_log ("\n"); one_more_corruption (fs, FATAL); return 1; } } free_space = leaf_free_space_estimate(bh->b_data, bh->b_size); if (get_blkh_free_space (blkh) != free_space) { fsck_log ("block %lu: The free space (%lu) is incorrect, should be (%lu)", bh->b_blocknr, get_blkh_free_space (blkh), free_space); if (fsck_mode(fs) != FSCK_CHECK && fsck_mode(fs) != FSCK_AUTO) { set_blkh_free_space (blkh, free_space); fsck_log (" - corrected\n"); mark_buffer_dirty (bh); } else { fsck_log ("\n"); one_more_corruption (fs, FIXABLE); return 1; } } return 0; } /* do this on pass 0 with every leaf marked used */ /* FIXME: we can improve fixing of broken keys: we can ssfe direct items which go after stat data and have broken keys */ static void pass0_correct_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh) { int file_format = KEY_FORMAT_UNDEFINED; struct item_head * ih; __u32 * ind_item; __u64 fs_size; __u64 offset; int symlnk = 0; int bad_order; unsigned long unfm_ptr; // unsigned int nr_items; int i, j, nr_items; int dirty = 0; leaf_structure_check(fs, bh); /* Delete all safe links. */ for (i = get_blkh_nr_items (B_BLK_HEAD (bh)) - 1; i >= 0; i--) { if (get_key_dirid (&B_N_PITEM_HEAD (bh, i)->ih_key) == ~0ul) { delete_item (fs, bh, i); } } fs_size = (__u64)fs->fs_blocksize * get_sb_block_count (fs->fs_ondisk_sb); start_again: ih = B_N_PITEM_HEAD (bh, 0); bad_order = 0; for (i = 0; i < (nr_items = get_blkh_nr_items (B_BLK_HEAD (bh))); i ++, ih ++) { if (is_indirect_ih(ih) && (get_ih_item_len (ih) % 4 != 0)) { set_type(get_ih_key_format(ih), &ih->ih_key, TYPE_UNKNOWN); dirty = 1; } if (type_unknown (&ih->ih_key)) { if ((get_ih_item_len (ih) == SD_SIZE) || (get_ih_item_len (ih) == SD_V1_SIZE)) { set_type_and_offset (KEY_FORMAT_1, &ih->ih_key, SD_OFFSET, TYPE_STAT_DATA); dirty = 1; fsck_log("pass0: vpf-10100: block %lu, item (%d): Unknown item type of StatData size," " type set to StatData %k\n", bh->b_blocknr, i, &ih->ih_key); } else { fsck_log("pass0: vpf-10110: block %lu, item (%d): Unknown item type found %k - deleted\n", bh->b_blocknr, i, &ih->ih_key); delete_item (fs, bh, i); goto start_again; } } if (is_wrong_short_key (&ih->ih_key)) { /* sometimes stat datas get k_objectid==0 or k_dir_id==0 */ /* if (i == (nr_items - 1)) { if (i == 0) { fsck_log ("block %lu: item %d: (%H) id equals 0\n", bh->b_blocknr, i, ih); return; } // delete last item fsck_log ("block %lu: item %d: (%H) id equals 0\n", bh->b_blocknr, i, ih); delete_item (fs, bh, i - 1); return; } */ /* FIXME: 18842 19034 0x1 IND (2) 19035 19035 0x0 SD (0) 18842 1 0x1 IND (1) 18842 1 0x1001 DRCT (2) */ /* there is next item: if it is not stat data - take its k_dir_id and k_objectid. if key order will be still wrong - the changed item will be deleted */ if (i && !is_stat_data_ih (ih)) { /* previous item has a wrong short_key */ fsck_log ("pass0: vpf-10120: block %lu: item %d: Wrong key %k, corrected to ", bh->b_blocknr, i, &ih->ih_key); set_key_dirid (&ih->ih_key, get_key_dirid (&(ih - 1)->ih_key)); set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key)); fsck_log ("%k\n", &ih->ih_key); dirty = 1; } else if ((i < nr_items - 1) && !is_stat_data_ih (ih + 1)) { if (!is_wrong_short_key(&(ih + 1)->ih_key)) { fsck_log ("pass0: vpf-10130: block %lu: item %d: Wrong key %k, corrected to ", bh->b_blocknr, i, &ih->ih_key); set_key_dirid (&ih->ih_key, get_key_dirid (&(ih + 1)->ih_key)); set_key_objectid (&ih->ih_key, get_key_objectid (&(ih + 1)->ih_key)); /* set_offset (KEY_FORMAT_1, &ih->ih_key, 0); set_type (KEY_FORMAT_1, &ih->ih_key, TYPE_STAT_DATA);*/ fsck_log ("%k\n", &ih->ih_key); dirty = 1; goto start_again; } else { fsck_log ("pass0: vpf-10140: block %lu: items %d and %d have bad short keys %k, %k, both deleted\n", bh->b_blocknr, i, i+1, &ih->ih_key, &(ih + 1)->ih_key); delete_item (fs, bh, i); delete_item (fs, bh, i); goto start_again; } } else { fsck_log ("pass0: vpf-10150: block %lu: item %d: Wrong key %k, deleted\n", bh->b_blocknr, i, &ih->ih_key); delete_item (fs, bh, i); goto start_again; } } if (i && i + 1 < nr_items) { if (is_stat_data_ih (ih - 1) && !is_stat_data_ih (ih) && !is_direct_ih (ih + 1) && !is_stat_data_ih (ih + 1)) { /* i or i+1 item should be SD or i+1 should be direct item */ if ((get_ih_item_len (ih) == SD_SIZE) || (get_ih_item_len (ih) == SD_V1_SIZE)) { /* make i as SD */ fsck_log("pass0: vpf-10400: block %lu, item %d: Wrong order of items - " "change the type of the key %k to StatData\n", bh->b_blocknr, i, &ih->ih_key); set_type_and_offset (KEY_FORMAT_1, &ih->ih_key, SD_OFFSET, TYPE_STAT_DATA); dirty = 1; } else if ((get_ih_item_len (ih+1) == SD_SIZE) || (get_ih_item_len (ih+1) == SD_V1_SIZE)) { /* make i+1 as SD */ fsck_log("pass0: vpf-10410: block %lu, item %d: Wrong order of items - " "change the type of the key %k to StatData\n", bh->b_blocknr, i + 1, &(ih + 1)->ih_key); set_type_and_offset (KEY_FORMAT_1, &(ih + 1)->ih_key, SD_OFFSET, TYPE_STAT_DATA); dirty = 1; } else if (is_indirect_ih(ih)) { fsck_log("pass0: vpf-10420: block %lu, item %d: Wrong order of items - " "change the type of the key %k to Direct\n", bh->b_blocknr, i+1, &(ih + 1)->ih_key); set_type (get_ih_key_format(ih+1), &(ih + 1)->ih_key, TYPE_DIRECT); dirty = 1; } } } if (i && ((is_stat_data_ih (ih - 1) && !is_stat_data_ih (ih) && (get_key_dirid (&(ih - 1)->ih_key) != get_key_dirid (&ih->ih_key))) || (is_stat_data_ih (ih) && (get_key_dirid (&(ih - 1)->ih_key) > get_key_dirid (&ih->ih_key))))) { /* not the same dir_id of the same file or not increasing dir_id of different files */ if ((i > 1) && get_key_dirid (&(ih - 2)->ih_key) == get_key_dirid (&(ih - 1)->ih_key)) { /* fix i-th */ if (!is_stat_data_ih (ih)) { fsck_log("pass0: vpf-10430: block %lu, item %d: Wrong order of items - " "change the dir_id of the key %k to %lu\n", bh->b_blocknr, i, &ih->ih_key, get_key_dirid (&(ih - 1)->ih_key)); set_key_dirid (&ih->ih_key, get_key_dirid (&(ih - 1)->ih_key)); dirty = 1; } else if (i + 1 < nr_items) { fsck_log("pass0: vpf-10440: block %lu, item %d: Wrong order of items - " "change the dir_id of the key %k to %lu\n", bh->b_blocknr, i, &ih->ih_key, get_key_dirid (&(ih + 1)->ih_key)); set_key_dirid (&ih->ih_key, get_key_dirid (&(ih + 1)->ih_key)); dirty = 1; } } else if ((i + 1 < nr_items) && get_key_dirid (&ih->ih_key) == get_key_dirid (&(ih + 1)->ih_key)) { fsck_log("pass0: vpf-10450: block %lu, item %d: Wrong order of items - " "change the dir_id of the key %k to %lu\n", bh->b_blocknr, i - 1, &(ih - 1)->ih_key, get_key_dirid (&ih->ih_key)); /* fix (i - 1)-th */ set_key_dirid (&(ih - 1)->ih_key, get_key_dirid (&ih->ih_key)); dirty = 1; } } if (i && i + 1 < nr_items) { /* there is a previous and a next items */ if ((get_key_dirid (&(ih - 1)->ih_key) == get_key_dirid (&(ih + 1)->ih_key)) && (get_key_dirid (&(ih - 1)->ih_key) != get_key_dirid (&ih->ih_key))) { fsck_log("pass0: vpf-10460: block %lu, item %d: Wrong order of items - " "change the dir_id of the key %k to %lu\n", bh->b_blocknr, i, &ih->ih_key, get_key_dirid (&(ih - 1)->ih_key)); set_key_dirid (&ih->ih_key, get_key_dirid (&(ih - 1)->ih_key)); dirty = 1; } if (is_stat_data_ih (ih - 1) && is_indirect_ih (ih) && is_direct_ih (ih + 1)) { if ((get_key_objectid (&(ih - 1)->ih_key) == get_key_objectid (&(ih + 1)->ih_key)) && (get_key_objectid (&(ih - 1)->ih_key) != get_key_objectid (&ih->ih_key))) { fsck_log("pass0: vpf-10470: block %lu, item %d: Wrong order of items - " "change the object_id of the key %k to %lu\n", bh->b_blocknr, i, &ih->ih_key, get_key_objectid (&(ih - 1)->ih_key)); set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key)); dirty = 1; } if ((get_key_objectid (&(ih - 1)->ih_key) == get_key_objectid (&ih->ih_key)) && (get_key_objectid (&(ih - 1)->ih_key) != get_key_objectid (&(ih + 1)->ih_key))) { fsck_log("pass0: vpf-10480: block %lu, item %d: Wrong order of items - " "change the object_id of the key %k to %lu\n", bh->b_blocknr, i + 1, &(ih+1)->ih_key, get_key_objectid (&(ih - 1)->ih_key)); set_key_objectid (&(ih + 1)->ih_key, get_key_objectid (&(ih - 1)->ih_key)); dirty = 1; } if ((get_key_objectid (&ih->ih_key) == get_key_objectid (&(ih + 1)->ih_key)) && (get_key_objectid (&(ih - 1)->ih_key) != get_key_objectid (&(ih + 1)->ih_key))) { fsck_log("pass0: vpf-10490: block %lu, item %d: Wrong order of items - " "change the object_id of the key %k to %lu\n", bh->b_blocknr, i - 1, &(ih-1)->ih_key, get_key_objectid (&(ih + 1)->ih_key)); set_key_objectid (&(ih - 1)->ih_key, get_key_objectid (&(ih + 1)->ih_key)); dirty = 1; } if ((get_key_dirid (&(ih - 1)->ih_key) == get_key_dirid (&ih->ih_key)) && (get_key_dirid (&(ih - 1)->ih_key) != get_key_dirid (&(ih + 1)->ih_key))) { fsck_log("pass0: vpf-10500: block %lu, item %d: Wrong order of items - " "change the dir_id of the key %k to %lu\n", bh->b_blocknr, i + 1, &(ih+1)->ih_key, get_key_dirid (&(ih - 1)->ih_key)); set_key_dirid (&(ih + 1)->ih_key, get_key_dirid (&(ih - 1)->ih_key)); dirty = 1; } if ((get_key_dirid (&ih->ih_key) == get_key_dirid (&(ih + 1)->ih_key)) && (get_key_dirid (&(ih - 1)->ih_key) != get_key_dirid (&(ih + 1)->ih_key))) { fsck_log("pass0: vpf-10510: block %lu, item %d: Wrong order of items - " "change the dir_id of the key %k to %lu\n", bh->b_blocknr, i - 1, &(ih-1)->ih_key, get_key_dirid (&(ih + 1)->ih_key)); set_key_dirid (&(ih - 1)->ih_key, get_key_dirid (&(ih + 1)->ih_key)); dirty = 1; } } } if (i && is_stat_data_ih (ih) && get_key_dirid (&(ih - 1)->ih_key) == get_key_dirid (&ih->ih_key) && get_key_objectid (&(ih - 1)->ih_key) >= get_key_objectid (&ih->ih_key)) { if ((i + 1 < nr_items) && !is_stat_data_ih (ih + 1)) { if (get_key_objectid (&(ih - 1)->ih_key) < get_key_objectid (&(ih + 1)->ih_key)) { fsck_log("pass0: vpf-10520: block %lu, item %d: Wrong order of items - " "change the object_id of the key %k to %lu\n", bh->b_blocknr, i - 1, &(ih-1)->ih_key, get_key_objectid (&(ih + 1)->ih_key)); set_key_objectid (&ih->ih_key, get_key_objectid (&(ih + 1)->ih_key)); dirty = 1; } } } if (i && is_stat_data_ih (ih - 1) && !is_stat_data_ih (ih) && (get_key_objectid (&(ih - 1)->ih_key) != get_key_objectid (&ih->ih_key))) { int err = 0; if (i > 1) { if (comp_short_keys (&(ih - 2)->ih_key, &(ih - 1)->ih_key) != -1) misc_set_bit (1, &err); if (comp_short_keys (&(ih - 2)->ih_key, &ih->ih_key) != -1) misc_set_bit (2, &err); } if (i + 1 < nr_items) { if (comp_short_keys (&(ih - 1)->ih_key, &(ih + 1)->ih_key) != -1) misc_set_bit (3, &err); if (comp_short_keys (&ih->ih_key, &(ih + 1)->ih_key) != -1) misc_set_bit (4, &err); } /* if ((test_bit (1, err) || test_bit (3, err)) && (test_bit (2, err) || test_bit (4, err))) { // thera are no problem-free keys, delete them both delete_item (fs, bh, i - 1); delete_item (fs, bh, i - 1); goto start_again; } */ if (!misc_test_bit (1, &err) && !misc_test_bit (3, &err) && !misc_test_bit (2, &err) && !misc_test_bit (4, &err)) { if (i <= 1) { /* take bigger */ if (comp_short_keys (&(ih - 1)->ih_key, &ih->ih_key) == 1) { fsck_log("pass0: vpf-10530: block %lu, item %d: Wrong order of items - " "change the object_id of the key %k to %lu\n", bh->b_blocknr, i, &ih->ih_key, get_key_objectid (&(ih - 1)->ih_key)); set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key)); } else { fsck_log("pass0: vpf-10540: block %lu, item %d: Wrong order of items - " "change the object_id of the key %k to %lu\n", bh->b_blocknr, i - 1, &(ih - 1)->ih_key, get_key_objectid (&ih->ih_key)); set_key_objectid (&(ih - 1)->ih_key, get_key_objectid (&ih->ih_key)); } } else { /* take smaller */ if (comp_short_keys (&(ih - 1)->ih_key, &ih->ih_key) == 1) { fsck_log("pass0: vpf-10550: block %lu, item %d: Wrong order of items - " "change the object_id of the key %k to %lu\n", bh->b_blocknr, i - 1, &(ih - 1)->ih_key, get_key_objectid (&ih->ih_key)); set_key_objectid (&(ih - 1)->ih_key, get_key_objectid (&ih->ih_key)); } else { fsck_log("pass0: vpf-10560: block %lu, item %d: Wrong order of items - " "change the object_id of the key %k to %lu\n", bh->b_blocknr, i, &ih->ih_key, get_key_objectid (&(ih - 1)->ih_key)); set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key)); } } dirty = 1; } else if (!misc_test_bit (1, &err) && !misc_test_bit (3, &err)) { /* take i - 1 */ fsck_log("pass0: vpf-10590: block %lu, item %d: Wrong order of items - " "change the object_id of the key %k to %lu\n", bh->b_blocknr, i, &ih->ih_key, get_key_objectid (&(ih - 1)->ih_key)); set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key)); dirty = 1; } else if (!misc_test_bit (2, &err) && !misc_test_bit (4, &err)) { /* take i */ fsck_log("pass0: vpf-10600: block %lu, item %d: Wrong order of items - " "change the object_id of the key %k to %lu\n", bh->b_blocknr, i - 1, &(ih - 1)->ih_key, get_key_objectid (&ih->ih_key)); set_key_objectid (&(ih - 1)->ih_key, get_key_objectid (&ih->ih_key)); dirty = 1; } } /* this recovers corruptions like the below: 1774 1732 0 0 116262638 1732 1 3 1774 1736 0 0 */ if (i && is_stat_data_ih (ih - 1) && !is_stat_data_ih (ih)) { if (get_key_objectid (&ih->ih_key) != get_key_objectid (&(ih - 1)->ih_key) || get_key_dirid (&ih->ih_key) != get_key_dirid (&(ih - 1)->ih_key) || get_offset (&ih->ih_key) != 1) { if (is_direntry_ih (ih)) { fsck_log ("pass0: vpf-10160: block %lu: item %d: No \".\" entry found in " "the first item of a directory\n", bh->b_blocknr, i); set_key_dirid (&ih->ih_key, get_key_dirid (&(ih - 1)->ih_key)); set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key)); dirty = 1; } else { fsck_log ("pass0: vpf-10170: block %lu: item %d: Wrong order of items - " "the item \n\t%H fixed to ", bh->b_blocknr, i, ih); set_key_dirid (&ih->ih_key, get_key_dirid (&(ih - 1)->ih_key)); set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key)); if (get_ih_item_len (ih - 1) == SD_SIZE) { /* stat data is new, therefore this item is new too */ set_offset (KEY_FORMAT_2, &(ih->ih_key), 1); if ((get_ih_entry_count (ih) != 0xffff) && (get_ih_item_len (ih) % 4 == 0)) set_type (KEY_FORMAT_2, &(ih->ih_key), TYPE_INDIRECT); else set_type (KEY_FORMAT_2, &(ih->ih_key), TYPE_DIRECT); set_ih_key_format (ih, KEY_FORMAT_2); } else { /* stat data is old, therefore this item is old too */ set_offset (KEY_FORMAT_1, &(ih->ih_key), 1); if ((get_ih_entry_count (ih) != 0xffff) && (get_ih_item_len (ih) % 4 == 0)) set_type (KEY_FORMAT_1, &(ih->ih_key), TYPE_INDIRECT); else { set_type (KEY_FORMAT_1, &(ih->ih_key), TYPE_DIRECT); set_ih_free_space (ih, 0xffff); } set_ih_key_format (ih, KEY_FORMAT_1); } fsck_log ("\n\t%H\n", ih); dirty = 1; } } } /* FIXME: corruptions like: 56702 66802 1 2 56702 65536 0 0 56702 66803 1 2 do not get recovered (both last items will be deleted) */ /* delete item if it is not in correct order of object items */ if (i && not_of_one_file (&ih->ih_key, &(ih - 1)->ih_key) && !is_stat_data_ih (ih)) { fsck_log ("pass0: vpf-10180: block %lu: item %d: The item %k, which follows non StatData item %k, is deleted\n", bh->b_blocknr, i, &ih->ih_key, &(ih - 1)->ih_key); delete_item (fs, bh, i); goto start_again; } if (is_stat_data_ih (ih)) { if (get_offset (&ih->ih_key) != 0) { set_offset(KEY_FORMAT_1, &ih->ih_key, 0); dirty = 1; } } else if (!is_direntry_ih (ih)) { /* not SD, not direntry */ if (i && comp_short_keys (&(ih - 1)->ih_key, &ih->ih_key) == 0) { if (is_stat_data_ih (ih - 1)) { if (get_offset (&ih->ih_key) != 1) { set_offset(key_format(&ih->ih_key), &ih->ih_key, 1); dirty = 1; } } else if (is_indirect_ih (ih - 1) && is_direct_ih (ih)) { if (get_offset (&ih->ih_key) != get_offset(&(ih - 1)->ih_key) + I_UNFM_NUM (ih - 1) * fs->fs_blocksize) { set_offset(key_format(&ih->ih_key), &ih->ih_key, get_offset(&(ih - 1)->ih_key) + I_UNFM_NUM (ih - 1) * fs->fs_blocksize); dirty = 1; } } else { /* if indirect item or not the first direct item in the leaf */ fsck_log("pass0: vpf-10250: block %lu, item %d: The item %k with wrong type is deleted\n", bh->b_blocknr, i, &ih->ih_key); delete_item (fs, bh, i); goto start_again; } /* Check the lenght of the direct item; offset should be ok already. */ if (is_direct_ih (ih)) { if (STORE_TAIL_IN_UNFM (get_offset (&ih->ih_key) + get_ih_item_len (ih) - 1, get_ih_item_len (ih), bh->b_size)) { fsck_log("pass0: vpf-10700: block %lu, item %d: The item with wrong offset" " or length found %k, len % lu - deleted\n", bh->b_blocknr, i, &ih->ih_key, get_ih_item_len (ih)); delete_item (fs, bh, i); goto start_again; } } } else { /*first item in the node or first item of the file */ if (i) { /* first item of the file, but not SD - delete */ fsck_log("pass0: vpf-10190: block %lu, item %d: The item %k, which follows non StatData" " item %k, is deleted\n", bh->b_blocknr, i, &ih->ih_key, &(ih - 1)->ih_key ); delete_item (fs, bh, i); goto start_again; } /* indirect or direct is the first in the leaf */ offset = (__u64)get_offset (&ih->ih_key); if (is_indirect_ih (ih)) { if (offset % fs->fs_blocksize != 1) { fsck_log("pass0: vpf-10200: block %lu, item %d: The item %k with wrong offset is deleted\n", bh->b_blocknr, i, &ih->ih_key); delete_item (fs, bh, i); goto start_again; } } else if (is_direct_ih (ih)) { if (!correct_direct_item_offset (get_offset (&ih->ih_key), key_format (&ih->ih_key)) || ((get_offset (&ih->ih_key) % bh->b_size - 1) + get_ih_item_len (ih) > bh->b_size) || STORE_TAIL_IN_UNFM (offset + get_ih_item_len (ih) - 1, get_ih_item_len (ih), bh->b_size)) { fsck_log("pass0: vpf-10210: block %lu, item %d: The item with wrong offset ", bh->b_blocknr, i); fsck_log("or length found %k, len % lu - deleted\n", &ih->ih_key, get_ih_item_len (ih)); delete_item (fs, bh, i); goto start_again; } } offset += get_bytes_number (ih, fs->fs_blocksize); if (!does_it_fit_into_dev (offset, fs_size)) { fsck_log("pass0: vpf-10230: block %lu, item %d: The item offset is is too big %k - deleted\n", bh->b_blocknr, i, &ih->ih_key); delete_item (fs, bh, i); goto start_again; } } } if (i && comp_keys (&(ih - 1)->ih_key, &ih->ih_key) != -1) { /* previous item has key not smaller than the key of currect item */ if (is_stat_data_ih (ih - 1) && !is_stat_data_ih (ih)) { /* fix key of stat data such as if it was stat data of that item */ fsck_log ("pass0: block %lu, items %d, %d: Wrong order of items - make the StatData item %k of the file %k\n", bh->b_blocknr, i - 1, i, &(ih - 1)->ih_key, &ih->ih_key); set_key_dirid (&(ih - 1)->ih_key, get_key_dirid (&ih->ih_key)); set_key_objectid (&(ih - 1)->ih_key, get_key_objectid (&ih->ih_key)); set_offset (KEY_FORMAT_1, &(ih - 1)->ih_key, 0); set_type (KEY_FORMAT_1, &(ih - 1)->ih_key, TYPE_STAT_DATA); dirty = 1; } else { /* ok, we have to delete one of these two - decide which one */ int retval; /* something will be deleted */ dirty = 1; retval = upper_correct (bh, ih - 1, i - 1); switch (retval) { case 0: /* delete upper item */ fsck_log ("pass0: block %lu, item %d (upper): Item %k is out of order - deleted\n", bh->b_blocknr, i - 1, &(ih - 1)->ih_key); delete_item (fs, bh, i - 1); goto start_again; case 1: /* delete lower item */ fsck_log ("pass0: block %lu, item %d (lower): Item %k is out of order - deleted\n", bh->b_blocknr, i, &ih->ih_key); delete_item (fs, bh, i); goto start_again; default: /* upper item was the first item of a node */ /* to make gcc 3.2 do not sware here */; } retval = lower_correct (bh, ih, i); switch (retval) { case 0: /* delete lower item */ fsck_log ("pass0: block %lu, item %d (lower): Item %k is out of order - deleted\n", bh->b_blocknr, i, &ih->ih_key); delete_item (fs, bh, i); goto start_again; case 1: /* delete upper item */ fsck_log ("pass0: block %lu, %d (upper): Item %k is out of order - deleted\n", bh->b_blocknr, i - 1, &(ih - 1)->ih_key); delete_item (fs, bh, i - 1); goto start_again; default: /* only 2 items in the node, how to decide what to delete, go and ask user */ /* to make gcc 3.2 do not sware here */; } fsck_log ("pass0: block %lu, items %d and %d: Which of these items looks better (the other will be deleted.)?\n" "%k\n%k\n", bh->b_blocknr, i-1, i, &(ih - 1)->ih_key, &ih->ih_key); if (fsck_user_confirmed (fs, "1 or 2?", "1\n", 1)) delete_item (fs, bh, i - 1); else delete_item (fs, bh, i); goto start_again; } } if (is_stat_data_ih (ih) && (get_ih_item_len (ih) != SD_SIZE && get_ih_item_len (ih) != SD_V1_SIZE)) { fsck_log ("pass0: block %lu, item %d: StatData item of wrong length found %H - deleted\n", bh->b_blocknr, i, ih); delete_item (fs, bh, i); goto start_again; } dirty += correct_key_format (ih, symlnk); if (is_stat_data_ih (ih)) { __u16 mode; file_format = get_ih_key_format (ih); get_sd_mode (ih, B_N_PITEM(bh,i), &mode); symlnk = ( S_ISLNK(mode) ? 1 : 0); ;/*correct_stat_data (fs, bh, i);*/ } else if ( !is_direntry_ih(ih) && !(symlnk && is_direct_ih(ih)) && (file_format != KEY_FORMAT_UNDEFINED) && (file_format != get_ih_key_format (ih))) { fsck_log("pass0: vpf-10240: block %lu, item (%d): Item %k, which format (%d) is not equal to StatData " "format (%d), is deleted\n", bh->b_blocknr, i, &ih->ih_key, get_ih_key_format(ih), file_format); delete_item (fs, bh, i); goto start_again; } else { file_format = KEY_FORMAT_UNDEFINED; symlnk = 0; } if (i && is_stat_data_ih (ih - 1) && !not_of_one_file (&ih->ih_key, &(ih - 1)->ih_key)) { __u16 mode; get_sd_mode (ih - 1, B_I_PITEM (bh, ih - 1), &mode); if (not_a_directory (B_I_PITEM (bh, ih - 1)) && is_direntry_ih (ih)) { /* make SD mode SD of dir */ fsck_log ("pass0: block %lu, item %d: The directory %K has the wrong mode (%M), corrected to ", bh->b_blocknr, i, &ih->ih_key, mode); mode &= ~S_IFMT; mode |= S_IFDIR; fsck_log ("(%M)\n", mode); set_sd_mode (ih - 1, B_I_PITEM (bh, ih - 1), &mode); dirty = 1; } else if (!not_a_directory (B_I_PITEM (bh, ih - 1)) && !is_direntry_ih (ih)) { /* make SD mode SD of regular file */ fsck_log ("pass0: block %lu, item %d: Not the directory %K has the wrong mode (%M), corrected to ", bh->b_blocknr, i, &ih->ih_key, mode); mode &= ~S_IFMT; mode |= S_IFREG; fsck_log ("(%M)\n", mode); set_sd_mode (ih - 1, B_I_PITEM (bh, ih - 1), &mode); dirty = 1; } if (not_a_regfile (B_I_PITEM (bh, ih - 1)) && is_indirect_ih (ih)) { fsck_log ("pass0: block %lu, item %d: The file %K has the wrong mode (%M), corrected to ", bh->b_blocknr, i, &ih->ih_key, mode); mode &= ~S_IFMT; mode |= S_IFREG; fsck_log ("(%M)\n", mode); set_sd_mode (ih - 1, B_I_PITEM (bh, ih - 1), &mode); dirty = 1; } } if (is_direntry_ih (ih)) { j = verify_directory_item (fs, bh, i); if (j == 1) { /* wrong hash, skip the leaf */ pass_0_stat (fs)->too_old_leaves ++; mark_buffer_clean (bh); return; } else if (j == -1) { /* item was deleted */ goto start_again; } continue; } /*DEBUG*/ if (!is_stat_data_ih (ih) && get_offset (&ih->ih_key) == 0) reiserfs_panic ("block %lu, item %d: Zero offset can have StatData items only, but found %k\n", bh->b_blocknr, i, &ih->ih_key); if (!is_indirect_ih (ih)) continue; /* Darko Palic's filesystem had item: [20079 17328 0xfffb1001 IND, len 4048], format old */ { struct key tmp_key; tmp_key = ih->ih_key; set_offset (key_format (&tmp_key), &tmp_key, get_offset (&tmp_key) + get_bytes_number (ih, bh->b_size) - 1); if (get_offset (&tmp_key) < get_offset (&ih->ih_key)) { fsck_log ("pass0: block %lu, item %d: The item, which has wrong offset %k, is deleted\n", bh->b_blocknr, i, &ih->ih_key); delete_item (fs, bh, i); goto start_again; } } /* temporary ugly fix */ /* if (i && is_stat_data_ih (ih - 1) && !not_of_one_file (&ih->ih_key, &(ih - 1)->ih_key)) { __u16 mode; get_sd_mode (ih - 1, B_I_PITEM (bh, ih - 1), &mode); if (!S_ISREG (mode)) { fsck_log ("pass0: block %lu: mode (%M) of file %K having indirect item is fixed to ", bh->b_blocknr, mode, &ih->ih_key); mode &= ~S_IFMT; mode |= S_IFREG; set_sd_mode (ih - 1, B_I_PITEM (bh, ih - 1), &mode); fsck_log ("(%M)\n", mode); dirty = 1; } } */ ind_item = (__u32 *)B_I_PITEM (bh, ih); for (j = 0; j < (int)I_UNFM_NUM (ih); j ++) { unfm_ptr = le32_to_cpu (ind_item [j]); if (!unfm_ptr) continue; #if 0 if (fsck_mode (fs) == FSCK_ZERO_FILES) { /* FIXME: this is temporary mode of fsck */ ind_item [j] = 0; reiserfs_bitmap_clear_bit (fsck_new_bitmap(fs), unfm_ptr); tmp_zeroed ++; dirty = 1; continue; } #endif if (not_data_block (fs, unfm_ptr) || /* journal area or bitmap or super block */ unfm_ptr >= get_sb_block_count (fs->fs_ondisk_sb) || /* garbage in pointer */ (fs->fs_badblocks_bm && /* bad block */ reiserfs_bitmap_test_bit(fs->fs_badblocks_bm, unfm_ptr))) { pass_0_stat (fs)->wrong_pointers ++; /* fsck_log ("pass0: %d-th pointer (%lu) in item %k (leaf block %lu) is wrong\n", j, unfm_ptr, &ih->ih_key, bh->b_blocknr); */ ind_item [j] = 0; dirty = 1; continue; } /* mark block in bitmaps of unformatted nodes */ register_unfm (unfm_ptr); } } /* mark all objectids in use */ ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) { struct reiserfs_de_head * deh; id_map_mark(proper_id_map (fs), get_key_dirid (&ih->ih_key)); id_map_mark(proper_id_map (fs), get_key_objectid (&ih->ih_key)); if (is_direntry_ih(ih)) { for (j = 0, deh = B_I_DEH (bh, ih); j < get_ih_entry_count (ih); j ++, deh++) id_map_mark(proper_id_map(fs), get_deh_objectid(deh)); } } if (get_blkh_nr_items (B_BLK_HEAD (bh)) < 1) { /* pass 1 will skip this */ pass_0_stat (fs)->all_contents_removed ++; // fsck_log ("pass0: block %lu: All items were deleted.\n", bh->b_blocknr); dirty = 0; mark_buffer_clean (bh); } else { /* pass1 will use this bitmap */ pass0_mark_leaf (bh->b_blocknr); /*fsck_data (fs)->rebuild.leaves ++;*/ } if (dirty) { pass_0_stat (fs)->leaves_corrected ++; mark_buffer_dirty (bh); } } static int is_bad_sd (struct item_head * ih, char * item) { struct stat_data * sd = (struct stat_data *)item; if (get_key_offset_v1 (&ih->ih_key) || get_key_uniqueness (&ih->ih_key)) { fsck_log ("vpf-10610: StatData item %k has non zero offset found.\n", &ih->ih_key); return 1; } if (get_ih_item_len (ih) == SD_V1_SIZE) { /* looks like old stat data */ if (get_ih_key_format (ih) != KEY_FORMAT_1) fsck_log ("vpf-10620: StatData item %k has wrong format.\n", &ih->ih_key); return 0; } if (!S_ISDIR (sd_v2_mode(sd)) && !S_ISREG(sd_v2_mode(sd)) && !S_ISCHR (sd_v2_mode(sd)) && !S_ISBLK(sd_v2_mode(sd)) && !S_ISLNK (sd_v2_mode(sd)) && !S_ISFIFO(sd_v2_mode(sd)) && !S_ISSOCK(sd_v2_mode(sd))) { /*fsck_log ("file %k unexpected mode encountered 0%o\n", &ih->ih_key, sd_v2_mode(sd))*/; } return 0; } int is_bad_directory (struct item_head * ih, char * item, int dev, int blocksize) { int i; char * name; int namelen, entrylen; struct reiserfs_de_head * deh = (struct reiserfs_de_head *)item; __u32 prev_offset = 0; __u16 prev_location = get_ih_item_len (ih); int min_entry_size = 1;/* we have no way to understand whether the filesystem wes created in 3.6 format or converted to it. So, we assume that minimal name length is 1 */ if (get_ih_item_len (ih) / (DEH_SIZE + min_entry_size) < get_ih_entry_count (ih)) /* entry count is too big */ return 1; for (i = 0; i < get_ih_entry_count (ih); i ++, deh ++) { entrylen = entry_length(ih, deh, i); if (entrylen > (int)REISERFS_MAX_NAME_LEN (blocksize)) return 1; if (get_deh_offset (deh) <= prev_offset) return 1; prev_offset = get_deh_offset (deh); if (get_deh_location(deh) + entrylen != prev_location) return 1; prev_location = get_deh_location (deh); namelen = name_in_entry_length (ih, deh, i); name = name_in_entry (deh, i); if (!is_properly_hashed (fs, name, namelen, get_deh_offset (deh))) return 1; } return 0; } /* change incorrect block adresses by 0. Do not consider such item as incorrect */ static int is_bad_indirect (struct item_head * ih, char * item, int dev, int blocksize) { unsigned long blocks; unsigned int i; int bad = 0; if (get_ih_item_len(ih) % UNFM_P_SIZE) { fsck_log ("is_bad_indirect: indirect item of %H of invalid length\n", ih); return 1; } blocks = get_sb_block_count (fs->fs_ondisk_sb); for (i = 0; i < I_UNFM_NUM (ih); i ++) { __u32 * ind = (__u32 *)item; if (le32_to_cpu (ind[i]) >= blocks) { bad ++; fsck_log ("is_bad_indirect: %d-th pointer of item %H looks bad (%lu)\n", i, ih, le32_to_cpu (ind [i])); continue; } } return bad; } /* this is used by pass1.c:save_item and check.c:is_leaf_bad */ int is_bad_item (struct buffer_head * bh, struct item_head * ih, char * item) { int blocksize, dev; blocksize = bh->b_size; dev = bh->b_dev; // FIXME: refuse transparently bad items if (get_key_dirid (&ih->ih_key) == get_key_objectid (&ih->ih_key)) return 1; if (!get_key_dirid (&ih->ih_key) || !get_key_objectid (&ih->ih_key)) return 1; if (is_stat_data_ih(ih)) return is_bad_sd (ih, item); if (is_direntry_ih (ih)) return is_bad_directory (ih, item, dev, blocksize); if (is_indirect_ih (ih)) return is_bad_indirect (ih, item, dev, blocksize); if (is_direct_ih (ih)) return 0; return 1; } int is_leaf_bad (struct buffer_head * bh) { int i; struct item_head * ih; int bad = 0; assert (is_leaf_node (bh)); for (i = 0, ih = B_N_PITEM_HEAD (bh, 0); i < B_NR_ITEMS (bh); i ++, ih ++) { if (is_bad_item (bh, ih, B_I_PITEM (bh, ih))) { fsck_log ("is_leaf_bad: block %lu, item %d: The corrupted item found (%H)\n", bh->b_blocknr, i, ih); bad = 1; continue; } if (i && bad_pair (fs, bh, i)) { fsck_log ("is_leaf_bad: block %lu items %d and %d: Wrong order of items:" "\n\t%H\n\t%H\n", bh->b_blocknr, i - 1, i, ih - 1, ih); bad = 1; } } return bad; } static int is_to_be_read (reiserfs_filsys_t * fs, unsigned long block) { return reiserfs_bitmap_test_bit (fsck_source_bitmap (fs), block); } static void do_pass_0 (reiserfs_filsys_t * fs) { struct buffer_head * bh; unsigned long i; int what_node; unsigned long done = 0, total; if (fsck_mode (fs) == DO_TEST) { /* just to test pass0_correct_leaf */ bh = bread (fs->fs_dev, fsck_data (fs)->rebuild.test, fs->fs_blocksize); if (!bh) { /* we were reading one block at time, and failed, so mark block bad */ fsck_progress ("%s: Reading of the block %lu failed\n", __FUNCTION__, fsck_data (fs)->rebuild.test); reiserfs_free (fs); exit(0); } if (is_leaf_bad (bh)) { fsck_progress ("############### bad #################\n"); } pass0_correct_leaf (fs, bh); print_block (stdout, fs, bh, 3, -1, -1); if (is_leaf_bad (bh)) { fsck_progress ("############### still bad #################\n"); } brelse (bh); reiserfs_free (fs); exit(0); } total = reiserfs_bitmap_ones (fsck_source_bitmap (fs)); for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { if (!is_to_be_read (fs, i)) continue; print_how_far (fsck_progress_file (fs), &done, total, 1, fsck_quiet (fs)); bh = bread (fs->fs_dev, i, fs->fs_blocksize); if (!bh) { /* we were reading one block at time, and failed, so mark block bad */ fsck_progress ("%s: Reading of the block %lu failed\n", __FUNCTION__, i); continue; } if (fs->fs_badblocks_bm && reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i)) reiserfs_panic ("The block (%lu), specified in badblock list, was read.", i); if (not_data_block (fs, i)) { /* block which could not be pointed by indirect item */ if (!(block_of_journal (fs, i) && fsck_data(fs)->rebuild.use_journal_area)) reiserfs_panic ("The block (%lu) from non data area was read.", i); } pass_0_stat (fs)->dealt_with ++; what_node = who_is_this (bh->b_data, bh->b_size); if ( what_node != THE_LEAF && what_node != HAS_IH_ARRAY ) { brelse (bh); continue; } pass_0_stat (fs)->leaves ++; pass0_correct_leaf (fs, bh); brelse (bh); } fsck_progress ("\n"); /* just in case */ id_map_mark(proper_id_map (fs), REISERFS_ROOT_OBJECTID); } int is_used_leaf (unsigned long block) { return pass0_is_leaf (block); } /* int how_many_leaves_were_there (void) { return fsck_data (fs)->rebuild.leaves; } */ /* these are used to correct uformatted node pointers */ int is_bad_unformatted (unsigned long block) { return pass0_is_bad_unfm (block); } /* these are used to correct uformatted node pointers */ int is_good_unformatted (unsigned long block) { return pass0_is_good_unfm (block); } /* this is for check only. With this we make sure that all pointers we put into tree on pass 1 do not point to leaves (FIXME), do not point to journal, bitmap, etc, do not point out of fs boundary (and are marked used in on-disk bitmap - this condition skipped for now). */ int still_bad_unfm_ptr_1 (unsigned long block) { if (!block) return 0; if (pass0_is_leaf (block)) return 1; if (pass0_is_bad_unfm (block) && !is_bad_unfm_in_tree_once (block)) return 2; if (not_data_block (fs, block)) return 3; /* if (!was_block_used (block)) return 4; */ if (block >= get_sb_block_count (fs->fs_ondisk_sb)) return 5; return 0; } /* pointers to data block which get into tree are checked with this */ int still_bad_unfm_ptr_2 (unsigned long block) { if (!block) return 0; if (is_block_used (block)) return 1; if (block >= get_sb_block_count (fs->fs_ondisk_sb)) return 1; return 0; } /* these are used to allocate blocks for tree building */ int are_there_allocable_blocks (unsigned int amout_needed) { if (reiserfs_bitmap_zeros (fsck_allocable_bitmap (fs)) < amout_needed) { unsigned int zeros = 0, i; fsck_progress ("Not enough allocable blocks, checking bitmap..."); for (i = 0; i < fsck_allocable_bitmap (fs)->bm_bit_size; i ++) { if (!reiserfs_bitmap_test_bit (fsck_allocable_bitmap (fs), i)) zeros ++; } fsck_progress ("there are %u allocable blocks, btw\n", zeros); return 0; } return 1; } unsigned long alloc_block (void) { unsigned long block = 0; /* FIXME: start point could be used */ if (reiserfs_bitmap_find_zero_bit (fsck_allocable_bitmap (fs), &block)) { die ("alloc_block: Allocable blocks counter is wrong"); return 0; } reiserfs_bitmap_set_bit (fsck_allocable_bitmap (fs), block); return block; } void make_allocable (unsigned long block) { reiserfs_bitmap_clear_bit (fsck_allocable_bitmap (fs), block); } static void choose_hash_function (reiserfs_filsys_t * fs) { unsigned long max; unsigned int hash_code; int i; if (fsck_hash_defined (fs)) return; max = 0; hash_code = func2code (0); for (i = 0; i < fsck_data (fs)->rebuild.hash_amount; i ++) { /* remember hash whihc got more hits */ if (fsck_data (fs)->rebuild.hash_hits [i] > max) { hash_code = i; max = fsck_data (fs)->rebuild.hash_hits [i]; } if (fsck_data (fs)->rebuild.hash_hits [i]) fsck_log ("%lu directory entries were hashed with %s hash.\n", fsck_data (fs)->rebuild.hash_hits [i], code2name(i)); } if (max == 0 || hash_code == 0) { /* no names were found. take either super block value or default */ hash_code = get_sb_hash_code (fs->fs_ondisk_sb); if (!hash_code) hash_code = DEFAULT_HASH; fsck_log ("Could not find a hash in use. Using %s\n", code2name (hash_code)); } /* compare the most appropriate hash with the hash set in super block */ if (hash_code != get_sb_hash_code (fs->fs_ondisk_sb)) { fsck_progress ("Selected hash (%s) does not match to the hash set in the super block (%s).\n", code2name (hash_code), code2name (get_sb_hash_code (fs->fs_ondisk_sb))); set_sb_hash_code (fs->fs_ondisk_sb, hash_code); } fsck_progress ("\t%s hash is selected\n", code2name (hash_code)); reiserfs_hash (fs) = code2func (hash_code); } /* create bitmap of blocks the tree is to be built off */ /* debugreiserfs and pass0 should share this code -s should show the same as we could recover - test: zero first 32M */ static void init_source_bitmap (reiserfs_filsys_t * fs) { FILE * fp; unsigned long block_count = get_sb_block_count (fs->fs_ondisk_sb); unsigned long i, j; unsigned long tmp; unsigned long block, reserved, bits_amount; switch (fsck_data (fs)->rebuild.scan_area) { case ALL_BLOCKS: fsck_source_bitmap (fs) = reiserfs_create_bitmap (block_count); reiserfs_bitmap_fill (fsck_source_bitmap (fs)); fsck_progress ("The whole partition (%d blocks) is to be scanned\n", reiserfs_bitmap_ones (fsck_source_bitmap (fs))); break; case USED_BLOCKS: fsck_progress ("Loading on-disk bitmap .. "); fsck_source_bitmap (fs) = reiserfs_create_bitmap (block_count); reiserfs_bitmap_copy (fsck_source_bitmap (fs), fs->fs_bitmap2); fsck_progress ("ok, %d blocks marked used\n", reiserfs_bitmap_ones (fsck_source_bitmap (fs))); break; case EXTERN_BITMAP: fp = fopen (fsck_data (fs)->rebuild.bitmap_file_name, "r"); if (!fp) reiserfs_panic ("Could not load bitmap: %s\n", strerror(errno)); fsck_source_bitmap (fs) = reiserfs_bitmap_load (fp); if (!fsck_source_bitmap (fs)) reiserfs_panic ("Could not load fitmap from \"%s\"", fsck_data (fs)->rebuild.bitmap_file_name); fsck_progress ("%d blocks marked used in extern bitmap\n", reiserfs_bitmap_ones (fsck_source_bitmap (fs))); fclose (fp); break; default: reiserfs_panic ("No area to scan specified"); } tmp = 0; /* unmark bitmaps */ block = fs->fs_super_bh->b_blocknr + 1; reserved = fsck_source_bitmap(fs)->bm_bit_size; for (i = 0; i < get_sb_bmap_nr (fs->fs_ondisk_sb); i ++) { if (!reiserfs_bitmap_test_bit (fsck_source_bitmap (fs), block)) { /* bitmap is definitely broken, mark all blocks of this bitmap block as used */ bits_amount = (reserved < fs->fs_blocksize * 8) ? reserved : fs->fs_blocksize * 8; fsck_log("%s: Bitmap %lu (of %lu bits) is wrong - mark all blocks [%lu - %lu] as used\n", __FUNCTION__, i, bits_amount, i * fs->fs_blocksize * 8, fs->fs_blocksize * 8 * i + bits_amount); for (j = i * fs->fs_blocksize * 8; j < i * fs->fs_blocksize * 8 + bits_amount; j++) { if (!reiserfs_bitmap_test_bit (fsck_source_bitmap(fs), j)) reiserfs_bitmap_set_bit (fsck_source_bitmap(fs), j); } } reiserfs_bitmap_clear_bit (fsck_source_bitmap (fs), block); reserved -= fs->fs_blocksize * 8; tmp ++; /* next block fo bitmap */ if (spread_bitmaps (fs)) block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8); else block ++; } /* pass 0 will skip super block and journal areas and bitmap blocks, find how many blocks have to be read */ for (i = 0; i <= fs->fs_super_bh->b_blocknr; i ++) { if (!reiserfs_bitmap_test_bit (fsck_source_bitmap (fs), i)) continue; reiserfs_bitmap_clear_bit (fsck_source_bitmap (fs), i); tmp ++; } /* unmark journal area as used if journal is standard or it is non standard and initialy has been created on a main device */ reserved = get_size_of_journal_or_reserved_area (fs->fs_ondisk_sb); /* where does journal area (or reserved journal area) start from */ if (!is_new_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) && !is_old_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) die ("init_source_bitmap: Wrong super block location, you must run --rebuild-sb."); block = get_journal_start_must (fs); for (i = block; i < reserved + block; i ++) { if (!reiserfs_bitmap_test_bit (fsck_source_bitmap (fs), i)) continue; reiserfs_bitmap_clear_bit (fsck_source_bitmap (fs), i); tmp ++; } if (fs->fs_badblocks_bm) for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { if (reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i)) reiserfs_bitmap_clear_bit (fsck_source_bitmap (fs), i); } fsck_source_bitmap (fs)->bm_set_bits = reiserfs_bitmap_ones (fsck_source_bitmap (fs)); fsck_progress ("Skipping %d blocks (super block, journal, " "bitmaps) %d blocks will be read\n", tmp, fsck_source_bitmap (fs)->bm_set_bits); } static void before_pass_0 (reiserfs_filsys_t * fs) { /* bitmap of blocks to be read */ init_source_bitmap (fs); /* bitmap of leaves, good and bad unformatted */ make_aux_bitmaps (fs); /* on pass0 all objectids will be marked here as used */ proper_id_map (fs) = id_map_init(); /* pass0 gathers statistics about hash hits */ hash_hits_init (fs); } static void save_pass_0_result (reiserfs_filsys_t * fs) { FILE * file; int retval; /* save bitmaps with which we will be able start reiserfs from pass 1 */ file = open_file ("temp_fsck_file.deleteme", "w+"); if (!file) return; reiserfs_begin_stage_info_save (file, PASS_0_DONE); reiserfs_bitmap_save (file, leaves_bitmap); reiserfs_bitmap_save (file, good_unfm_bitmap); reiserfs_bitmap_save (file, bad_unfm_bitmap); reiserfs_end_stage_info_save (file); close_file (file); retval = rename ("temp_fsck_file.deleteme", state_dump_file (fs)); if (retval != 0) fsck_progress ("%s: Could not rename the temporary file temp_fsck_file.deleteme to %s", __FUNCTION__, state_dump_file (fs)); } /* file 'fp' must contain 3 bitmaps saved during last pass 0: bitmap of leaves, bitmaps of good and bad unfms*/ void load_pass_0_result (FILE * fp, reiserfs_filsys_t * fs) { leaves_bitmap = reiserfs_bitmap_load (fp); good_unfm_bitmap = reiserfs_bitmap_load (fp); bad_unfm_bitmap = reiserfs_bitmap_load (fp); if (!leaves_bitmap || !good_unfm_bitmap || !bad_unfm_bitmap) fsck_exit ("State dump file seems corrupted. Run without -d"); fsck_source_bitmap (fs) = leaves_bitmap; /* on pass 1 we do not need proper objectid map */ fsck_progress ("Pass 0 result loaded. %d leaves, %d/%d good/bad data blocks\n", reiserfs_bitmap_ones (leaves_bitmap), reiserfs_bitmap_ones (good_unfm_bitmap), reiserfs_bitmap_ones (bad_unfm_bitmap)); } static void after_pass_0 (reiserfs_filsys_t * fs) { time_t t; /* update super block: hash, objectid map, fsck state */ choose_hash_function (fs); id_map_flush(proper_id_map (fs), fs); set_sb_fs_state (fs->fs_ondisk_sb, PASS_0_DONE); mark_buffer_dirty (fs->fs_super_bh); /* write all dirty blocks */ fsck_progress ("Flushing.."); fs->fs_dirt = 1; reiserfs_flush (fs); fsck_progress ("finished\n"); stage_report (0, fs); /* free what we do not need anymore */ reiserfs_delete_bitmap (fsck_source_bitmap (fs)); fsck_source_bitmap (fs) = 0; if (!fsck_run_one_step (fs)) { if (fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1)) { /* reiserfsck continues */ fsck_source_bitmap (fs) = leaves_bitmap; return; } } else save_pass_0_result (fs); id_map_free(proper_id_map (fs)); proper_id_map (fs) = 0; time (&t); fsck_progress ("###########\n" "reiserfsck finished pass 0 at %s" "###########\n", ctime (&t)); fs->fs_dirt = 1; reiserfs_close (fs); exit(0); } void pass_0 (reiserfs_filsys_t * fs) { if (get_reiserfs_format (fs->fs_ondisk_sb) != fs->fs_format || get_reiserfs_format (fs->fs_ondisk_sb) == REISERFS_FORMAT_UNKNOWN) reiserfs_panic ("pass 0: ReiserFS format version mismatch found, you should run --rebuild-sb"); fsck_progress ("\nPass 0:\n"); if (fsck_log_file (fs) != stderr) /* this is just to separate warnings in the log file */ fsck_log ("####### Pass 0 #######\n"); before_pass_0 (fs); /* scan the partition, find leaves and correct them */ do_pass_0 (fs); after_pass_0 (fs); } reiserfsprogs-3.6.9/fsck/pass1.c0000664000077100007710000005615307705261642012261 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" #include reiserfs_bitmap_t * bad_unfm_in_tree_once_bitmap; //int step = 0; // 0 - find stat_data or any item ; 1 - find item ; 2 - already found /* allocates buffer head and copy buffer content */ struct buffer_head * make_buffer (int dev, unsigned long blocknr, int size, char * data) { struct buffer_head * bh; bh = getblk (dev, blocknr, size); if (buffer_uptodate (bh)) return bh; // die ("make_buffer: uptodate buffer found"); memcpy (bh->b_data, data, size); misc_set_bit (BH_Uptodate, (char *)&bh->b_state); return bh; } int find_not_of_one_file(struct key * to_find, struct key * key) { if ((get_key_objectid (to_find) != ~0ul) && (get_key_objectid (to_find) != get_key_objectid (key))) return 1; if ((get_key_dirid (to_find) != ~0ul) && (get_key_dirid (to_find) != get_key_dirid (key))) return 1; return 0; } int is_item_reachable (struct item_head * ih) { return ih_reachable (ih) ? 1 : 0; } void mark_item_unreachable (struct item_head * ih) { clean_ih_flags (ih); mark_ih_unreachable (ih); if (is_indirect_ih (ih)) set_ih_free_space (ih, 0); } void mark_item_reachable (struct item_head * ih, struct buffer_head * bh) { mark_ih_reachable (ih); mark_buffer_dirty (bh); } static void stat_data_in_tree (struct buffer_head *bh, struct item_head * ih) { #if 0 __u32 objectid; objectid = get_key_objectid (&ih->ih_key); if (mark_objectid_really_used (proper_id_map (fs), objectid)) { stat_shared_objectid_found (fs); mark_objectid_really_used (shared_id_map (fs), objectid); } #endif zero_nlink (ih, B_I_PITEM (bh, ih)); } static char *still_bad_unfm_ptr_to_string (int val) { switch (val) { case 1: return "a leaf"; case 2: return "shared between a few files"; case 3: return "not a data block"; case 4: return "not used in on-disk bitmap"; case 5: return "out of partition boundary"; } return ""; } /* this just marks blocks pointed by an indirect item as used in the new bitmap */ static void indirect_in_tree (struct buffer_head * bh, struct item_head * ih) { unsigned int i; __u32 * unp; __u32 unfm_ptr; int ret; unp = (__u32 *)B_I_PITEM (bh, ih); for (i = 0; i < I_UNFM_NUM (ih); i ++) { unfm_ptr = le32_to_cpu (unp[i]); if (unfm_ptr == 0) continue; if ((ret = still_bad_unfm_ptr_1 (unfm_ptr))) reiserfs_panic ("%s: block %lu: The file %k points to the block (%u) which is %s", __FUNCTION__, bh->b_blocknr, &ih->ih_key, unfm_ptr, still_bad_unfm_ptr_to_string(ret)); mark_block_used (unfm_ptr, 1); } } static void leaf_is_in_tree_now (struct buffer_head * bh) { item_action_t actions[] = {stat_data_in_tree, indirect_in_tree, 0, 0}; mark_block_used ((bh)->b_blocknr, 1); for_every_item (bh, mark_item_unreachable, actions); pass_1_stat (fs)->inserted_leaves ++; mark_buffer_dirty (bh); } static void insert_pointer (struct buffer_head * bh, struct path * path) { struct item_head * ih; char * body; int retval; struct tree_balance tb; init_tb_struct (&tb, fs, path, 0x7fff); /* fix_nodes & do_balance must work for internal nodes only */ ih = 0; retval = fix_nodes (/*tb.transaction_handle,*/ M_INTERNAL, &tb, ih); if (retval != CARRY_ON) die ("insert_pointer: fix_nodes failed with retval == %d", retval); /* child_pos: we insert after position child_pos: this feature of the insert_child */ /* there is special case: we insert pointer after (-1)-st key (before 0-th key) in the parent */ if (PATH_LAST_POSITION (path) == 0 && path->pos_in_item == 0) PATH_H_B_ITEM_ORDER (path, 0) = -1; else { if (PATH_H_PPARENT (path, 0) == 0) PATH_H_B_ITEM_ORDER (path, 0) = 0; /* PATH_H_B_ITEM_ORDER (path, 0) = PATH_H_PPARENT (path, 0) ? PATH_H_B_ITEM_ORDER (path, 0) : 0;*/ } ih = 0; body = (char *)bh; //memmode = 0; do_balance (&tb, ih, body, M_INTERNAL, 0); leaf_is_in_tree_now (bh); } /* return 1 if left and right can be joined. 0 otherwise */ int balance_condition_fails (struct buffer_head * left, struct buffer_head * right) { if (B_FREE_SPACE (left) >= B_CHILD_SIZE (right) - (are_items_mergeable (B_N_PITEM_HEAD (left, B_NR_ITEMS (left) - 1), B_N_PITEM_HEAD (right, 0), left->b_size) ? IH_SIZE : 0)) return 1; return 0; } /* return 1 if new can be joined with last node on the path or with its right neighbor, 0 otherwise */ int balance_condition_2_fails (struct buffer_head * new, struct path * path) { struct buffer_head * bh; struct key * right_dkey; int pos, used_space; bh = PATH_PLAST_BUFFER (path); if (balance_condition_fails (bh, new)) /* new node can be joined with last buffer on the path */ return 1; /* new node can not be joined with its left neighbor */ right_dkey = uget_rkey (path); if (right_dkey == 0) /* there is no right neighbor */ return 0; pos = PATH_H_POSITION (path, 1); if (pos == B_NR_ITEMS (bh = PATH_H_PBUFFER (path, 1))) { /* we have to read parent of right neighbor. For simplicity we call search_by_key, which will read right neighbor as well */ INITIALIZE_PATH(path_to_right_neighbor); if (reiserfs_search_by_key_4 (fs, right_dkey, &path_to_right_neighbor) != ITEM_FOUND) reiserfs_panic ("%s: block %lu, pointer %d: The left delimiting key %k of the block (%lu) is wrong," "the item cannot be found", __FUNCTION__, PATH_H_PBUFFER(path, 1)->b_blocknr, pos, right_dkey, get_dc_child_blocknr(B_N_CHILD (bh, pos + 1))); used_space = B_CHILD_SIZE (PATH_PLAST_BUFFER (&path_to_right_neighbor)); pathrelse (&path_to_right_neighbor); } else used_space = get_dc_child_size (B_N_CHILD (bh, pos + 1)); if (B_FREE_SPACE (new) >= used_space - (are_items_mergeable (B_N_PITEM_HEAD (new, B_NR_ITEMS (new) - 1), (struct item_head *)right_dkey, new->b_size) ? IH_SIZE : 0)) return 1; return 0; } static void get_max_buffer_key (struct buffer_head * bh, struct key * key) { struct item_head * ih; ih = B_N_PITEM_HEAD (bh, B_NR_ITEMS (bh) - 1); copy_key (key, &(ih->ih_key)); if (is_direntry_key (key)) { /* copy deh_offset 3-rd and 4-th key components of the last entry */ set_offset (KEY_FORMAT_1, key, get_deh_offset (B_I_DEH (bh, ih) + get_ih_entry_count (ih) - 1)); } else if (!is_stat_data_key (key)) /* get key of the last byte, which is contained in the item */ set_offset (key_format (key), key, get_offset (key) + get_bytes_number (ih, bh->b_size) - 1); } int tree_is_empty (void) { return (get_sb_root_block (fs->fs_ondisk_sb) == ~0ul || get_sb_root_block (fs->fs_ondisk_sb) == 0) ? 1 : 0; } void make_single_leaf_tree (struct buffer_head * bh) { /* tree is empty, make tree root */ set_sb_root_block (fs->fs_ondisk_sb, bh->b_blocknr); set_sb_tree_height (fs->fs_ondisk_sb, 2); mark_buffer_dirty (fs->fs_super_bh); leaf_is_in_tree_now (bh); } /* inserts pointer to leaf into tree if possible. If not, marks node as uninsertable in special bitmap */ static void try_to_insert_pointer_to_leaf (struct buffer_head * new_bh) { INITIALIZE_PATH (path); struct buffer_head * bh; /* last path buffer */ struct key * first_bh_key, last_bh_key; /* first and last keys of new buffer */ struct key last_path_buffer_last_key, * right_dkey; int ret_value; if (tree_is_empty () == 1) { make_single_leaf_tree (new_bh); return; } first_bh_key = B_N_PKEY (new_bh, 0); /* try to find place in the tree for the first key of the coming node */ ret_value = reiserfs_search_by_key_4 (fs, first_bh_key, &path); if (ret_value == ITEM_FOUND) goto cannot_insert; /* get max key in the new node */ get_max_buffer_key (new_bh, &last_bh_key); bh = PATH_PLAST_BUFFER (&path); if (comp_keys (B_N_PKEY (bh, 0), &last_bh_key) == 1/* first is greater*/) { /* new buffer falls before the leftmost leaf */ if (balance_condition_fails (new_bh, bh)) goto cannot_insert; if (uget_lkey (&path) != 0 || PATH_LAST_POSITION (&path) != 0) die ("try_to_insert_pointer_to_leaf: bad search result"); path.pos_in_item = 0; goto insert; } /* get max key of buffer, that is in tree */ get_max_buffer_key (bh, &last_path_buffer_last_key); if (comp_keys (&last_path_buffer_last_key, first_bh_key) != -1/* second is greater */) /* first key of new buffer falls in the middle of node that is in tree */ goto cannot_insert; right_dkey = uget_rkey (&path); if (right_dkey && comp_keys (right_dkey, &last_bh_key) != 1 /* first is greater */) goto cannot_insert; if (balance_condition_2_fails (new_bh, &path)) goto cannot_insert; insert: insert_pointer (new_bh, &path); goto out; cannot_insert: /* statistic */ mark_block_uninsertable (new_bh->b_blocknr); out: pathrelse (&path); return; } /* everything should be correct already in the leaf but contents of indirect items. So we only 1. zero slots pointing to a leaf 2. zero pointers to blocks which are pointed already 3. what we should do with directory entries hashed by another hash? they are deleted for now */ static void pass1_correct_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh) { unsigned int i, j; struct item_head * ih; __u32 * ind_item; __u32 unfm_ptr; int dirty = 0; ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) { if (is_direntry_ih (ih)) { struct reiserfs_de_head * deh; char * name; int name_len; unsigned int hash_code; deh = B_I_DEH (bh, ih); for (j = 0; j < get_ih_entry_count (ih); j ++) { name = name_in_entry (deh + j, j); name_len = name_in_entry_length (ih, deh + j, j); if ((j == 0 && is_dot (name, name_len)) || (j == 1 && is_dot_dot (name, name_len))) { continue; } hash_code = find_hash_in_use (name, name_len, GET_HASH_VALUE (get_deh_offset (deh + j)), get_sb_hash_code (fs->fs_ondisk_sb)); if (hash_code != get_sb_hash_code (fs->fs_ondisk_sb)) { fsck_log ("pass1: block %lu, item %d, entry %d: The entry \"%.*s\" of the %k is hashed with %s " "whereas proper hash is %s", bh->b_blocknr, i, j, name_len, name, &ih->ih_key, code2name (hash_code), code2name (get_sb_hash_code (fs->fs_ondisk_sb))); if (get_ih_entry_count (ih) == 1) { delete_item (fs, bh, i); fsck_log(" - the only entry - item was deleted\n"); i --; ih --; break; } else { cut_entry (fs, bh, i, j, 1); fsck_log(" - deleted\n"); j --; deh = B_I_DEH (bh, ih); } } } continue; } if (!is_indirect_ih (ih)) continue; /* correct indirect items */ ind_item = (__u32 *)B_I_PITEM (bh, ih); for (j = 0; j < I_UNFM_NUM (ih); j ++, ind_item ++) { unfm_ptr = le32_to_cpu (*ind_item); if (!unfm_ptr) continue; /* this corruption of indirect item had to be fixed in pass0 */ if (not_data_block (fs, unfm_ptr) || unfm_ptr >= get_sb_block_count (fs->fs_ondisk_sb)) /*!was_block_used (unfm_ptr))*/ reiserfs_panic ("%s: block %lu, item %d, pointer %d: The wrong pointer (%u) in the file %K. " "Must be fixed on pass0.", __FUNCTION__, bh->b_blocknr, i, j, unfm_ptr, &ih->ih_key); /* 1. zero slots pointing to a leaf */ if (is_used_leaf (unfm_ptr)) { dirty ++; *ind_item = 0; pass_1_stat (fs)->pointed_leaves ++; continue; } /* 2. zero pointers to blocks which are pointed already */ if (is_bad_unformatted (unfm_ptr)) { /* this unformatted pointed more than once. Did we see it already? */ if (!is_bad_unfm_in_tree_once (unfm_ptr)) /* keep first reference to it and mark about that in special bitmap */ mark_bad_unfm_in_tree_once (unfm_ptr); else { /* Yes, we have seen this pointer already, zero other pointers to it. */ dirty ++; *ind_item = 0; pass_1_stat (fs)->non_unique_pointers ++; continue; } } else pass_1_stat (fs)->correct_pointers ++; } } if (dirty) mark_buffer_dirty (bh); } struct si * remove_saved_item (struct si * si) { struct si * tmp = si->si_next; freemem (si->si_dnm_data); freemem (si); return tmp; } /* fsck starts creating of this bitmap on pass 1. It will then become on-disk bitmap */ static void init_new_bitmap (reiserfs_filsys_t * fs) { unsigned int i; unsigned long block; unsigned long reserved; fsck_new_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); /* mark_block_used skips 0, set the bit explicitly */ reiserfs_bitmap_set_bit (fsck_new_bitmap (fs), 0); /* mark other skipped blocks and super block used */ for (i = 1; i <= fs->fs_super_bh->b_blocknr; i ++) mark_block_used (i, 1); /* mark bitmap blocks as used */ block = fs->fs_super_bh->b_blocknr + 1; for (i = 0; i < get_sb_bmap_nr (fs->fs_ondisk_sb); i ++) { mark_block_used (block, 1); if (spread_bitmaps (fs)) block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8); else block ++; } reserved = get_size_of_journal_or_reserved_area (fs->fs_ondisk_sb); /* where does journal area (or reserved journal area) start from */ if (!is_new_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) && !is_old_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) die ("init_new_bitmap: Wrong super block location, you must run --rebuild-sb."); block = get_journal_start_must (fs); for (i = block; i < reserved + block; i ++) mark_block_used (i, 1); if (fs->fs_badblocks_bm) for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { if (reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i)) { if (reiserfs_bitmap_test_bit (fsck_new_bitmap (fs), i)) reiserfs_panic ("%s: The block pointer to not data area, must be fixed on the pass0.\n", __FUNCTION__); reiserfs_bitmap_set_bit (fsck_new_bitmap (fs), i); } } #if 0 /* mark journal area as used if journal is standard or it is non standard and initialy has been created on a main device */ reserved = 0; if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb)) reserved = get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)); if (get_sb_reserved_for_journal (fs->fs_ondisk_sb)) reserved = get_sb_reserved_for_journal (fs->fs_ondisk_sb); if (reserved) { for (i = 0; i <= reserved; i ++) mark_block_used (i + get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb))); } #endif } /* this makes a map of blocks which can be allocated when fsck will continue */ static void find_allocable_blocks (reiserfs_filsys_t * fs) { unsigned long i; fsck_progress ("Looking for allocable blocks .. "); fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_fill (fsck_allocable_bitmap (fs)); /* find how many leaves are not pointed by any indirect items */ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { if (not_data_block (fs, i)) /* journal (or reserved for it area), bitmaps, super block and blocks before it */ continue; if (is_good_unformatted (i) && is_bad_unformatted (i)) die ("find_allocable_blocks: The block (%lu) is masr as good and as bad at once.", i); if (is_good_unformatted (i) || is_bad_unformatted (i)) { /* blocks which were pointed once or more thn onec from indirect items - they will not be allocated */ continue; } /* make allocable not leaves, not bad blocks */ if (!is_used_leaf (i) && (!fs->fs_badblocks_bm || !reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i))) { /* this is not leaf and it is not pointed by found indirect items, so it does not contains anything valuable */ make_allocable (i); pass_1_stat (fs)->allocable_blocks ++; } } fsck_progress ("finished\n"); fs->block_allocator = reiserfsck_reiserfs_new_blocknrs; fs->block_deallocator = reiserfsck_reiserfs_free_block; } static void before_pass_1 (reiserfs_filsys_t * fs) { /* this will become an on-disk bitmap */ init_new_bitmap (fs); /* bitmap of leaves which could not be inserted on pass 1. FIXME: no need to have 1 bit per block */ fsck_uninsertables (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_fill (fsck_uninsertables (fs)); /* find blocks which can be allocated */ find_allocable_blocks (fs); /* bitmap of bad unformatted nodes which are in the tree already */ bad_unfm_in_tree_once_bitmap = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); /* pass 1 does not deal with objectid */ } static void save_pass_1_result (reiserfs_filsys_t * fs) { FILE * file; int retval; file = open_file("temp_fsck_file.deleteme", "w+"); if (!file) return; /* to be able to get a new bitmap on pass2 we should flush it on disk new_bitmap should not be flushed on disk if run without -d option, as if fsck fails on pass1 we get wrong bitmap on the next fsck start */ reiserfs_flush_to_ondisk_bitmap (fsck_new_bitmap (fs), fs); /* to be able to restart with pass 2 we need bitmap of uninsertable blocks and bitmap of alocable blocks */ reiserfs_begin_stage_info_save(file, PASS_1_DONE); reiserfs_bitmap_save (file, fsck_uninsertables (fs)); reiserfs_bitmap_save (file, fsck_allocable_bitmap(fs)); reiserfs_end_stage_info_save (file); close_file (file); retval = rename ("temp_fsck_file.deleteme", state_dump_file (fs)); if (retval != 0) fsck_progress ("pass 1: Could not rename the temporary file temp_fsck_file.deleteme to %s", state_dump_file (fs)); } void load_pass_1_result (FILE * fp, reiserfs_filsys_t * fs) { fsck_new_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_copy (fsck_new_bitmap (fs), fs->fs_bitmap2); fsck_uninsertables (fs) = reiserfs_bitmap_load (fp); fsck_allocable_bitmap (fs) = reiserfs_bitmap_load (fp); fs->block_allocator = reiserfsck_reiserfs_new_blocknrs; fs->block_deallocator = reiserfsck_reiserfs_free_block; if (!fsck_new_bitmap (fs) || !fsck_allocable_bitmap (fs) || !fsck_allocable_bitmap (fs)) fsck_exit ("State dump file seems corrupted. Run without -d"); /* we need objectid map on pass 2 to be able to relocate files */ proper_id_map (fs) = id_map_init(); /* Not implemented yet. fetch_objectid_map (proper_id_map (fs), fs); */ fsck_progress ("Pass 1 result loaded. %d blocks used, %d allocable, " "still to be inserted %d\n", reiserfs_bitmap_ones (fsck_new_bitmap (fs)), reiserfs_bitmap_zeros (fsck_allocable_bitmap (fs)), reiserfs_bitmap_zeros (fsck_uninsertables (fs))); } extern reiserfs_bitmap_t * leaves_bitmap; /* reads blocks marked in leaves_bitmap and tries to insert them into tree */ static void do_pass_1 (reiserfs_filsys_t * fs) { struct buffer_head * bh; unsigned long i; int what_node; unsigned long done = 0, total; /* on pass0 we have found that amount of leaves */ total = reiserfs_bitmap_ones (leaves_bitmap); /* read all leaves found on the pass 0 */ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { if (!is_used_leaf (i)) continue; print_how_far (fsck_progress_file (fs), &done, total, 1, fsck_quiet (fs)); /* at least one of nr_to_read blocks is to be checked */ bh = bread (fs->fs_dev, i, fs->fs_blocksize); if (!bh) { /* we were reading one block at time, and failed, so mark block bad */ fsck_progress ("pass1: Reading of the block %lu failed\n", i); continue; } what_node = who_is_this (bh->b_data, bh->b_size); if ( what_node != THE_LEAF ) { check_memory_msg(); die ("build_the_tree: Nothing but leaves are expected. Block %lu - %s\n", i, which_block(what_node)); } if (is_block_used (i) && !(block_of_journal (fs, i) && fsck_data(fs)->rebuild.use_journal_area)) /* block is in new tree already */ die ("build_the_tree: The leaf (%lu) is in the tree already\n", i); /* fprintf (block_list, "leaf %d\n", i + j);*/ pass_1_stat (fs)->leaves ++; /* the leaf may still contain indirect items with wrong slots. Fix that */ pass1_correct_leaf (fs, bh); if (get_blkh_nr_items (B_BLK_HEAD (bh)) == 0) { /* all items were deleted on pass 0 or pass 1 */ mark_buffer_clean (bh); brelse (bh); continue; } if (is_leaf_bad (bh)) { /* FIXME: will die */ fsck_log ("is_leaf_bad: WARNING: The leaf (%lu) is formatted badly. Will be handled on the the pass2.\n", bh->b_blocknr); mark_block_uninsertable (bh->b_blocknr); brelse (bh); continue; } if (block_of_journal (fs, i) && fsck_data(fs)->rebuild.use_journal_area) { /* FIXME: temporary thing */ if (tree_is_empty ()) { /* we insert inot tree only first leaf of journal */ unsigned long block; struct buffer_head * new_bh; block = alloc_block (); if (!block) die ("could not allocate block"); new_bh = getblk (bh->b_dev, block, bh->b_size); memcpy (new_bh->b_data, bh->b_data, bh->b_size); mark_buffer_uptodate (new_bh, 1); mark_buffer_dirty (new_bh); make_single_leaf_tree (new_bh); brelse (new_bh); brelse (bh); continue; } /* other blocks of journal will be inserted in pass 2 */ mark_block_uninsertable (bh->b_blocknr); brelse (bh); continue; } try_to_insert_pointer_to_leaf (bh); brelse (bh); } fsck_progress ("\n"); } static void after_pass_1 (reiserfs_filsys_t * fs) { time_t t; /* update fsck_state */ /* we should not flush bitmaps on disk after pass1, because new_bitmap contains only those blocks which are good leaves or just allocated internal blocks. */ set_sb_fs_state (fs->fs_ondisk_sb, PASS_1_DONE); mark_buffer_dirty (fs->fs_super_bh); /* write all dirty blocks */ fsck_progress ("Flushing.."); fs->fs_dirt = 1; reiserfs_flush (fs); fsck_progress ("finished\n"); stage_report (1, fs); /* we do not need this anymore */ delete_aux_bitmaps (); reiserfs_delete_bitmap (bad_unfm_in_tree_once_bitmap); if (!fsck_run_one_step (fs)) { if (fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1)) /* reiserfsck continues */ return; } else save_pass_1_result (fs); if (proper_id_map (fs)) { /* when we run pass 1 only - we do not have proper_id_map */ id_map_free(proper_id_map (fs)); proper_id_map (fs) = 0; } time (&t); fsck_progress ("###########\n" "reiserfsck finished pass 1 at %s" "###########\n", ctime (&t)); fs->fs_dirt = 1; reiserfs_close (fs); exit(0); } void pass_1 (reiserfs_filsys_t * fs) { fsck_progress ("\nPass 1 (will try to insert %lu leaves):\n", reiserfs_bitmap_ones (fsck_source_bitmap (fs))); if (fsck_log_file (fs) != stderr) fsck_log ("####### Pass 1 #######\n"); before_pass_1 (fs); /* try to insert leaves found during pass 0 */ do_pass_1 (fs); after_pass_1 (fs); } reiserfsprogs-3.6.9/fsck/pass2.c0000664000077100007710000004651707665645672012303 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" /* on pass2 we take leaves which could not be inserted into tree during pass1 and insert each item separately. It is possible that items of different objects with the same key can be found. We treat that in the following way: we put it into tree with new key and link it into /lost+found directory with name made of dir,oid. When coming item is a directory - we delete object from the tree, put it back with different key, link it to /lost+found directory and insert directory as it is */ /* relocation rules: we have an item (it is taken from "non-insertable" leaf). It has original key yet. We check to see if object with this key is remapped. Object can be only remapped if it is not a piece of directory */ /* in list of this structures we store what has been relocated. */ struct relocated { unsigned long old_dir_id; unsigned long old_objectid; unsigned long new_objectid; struct relocated * next; }; /* all relocated files will be linked into lost+found directory at the beginning of semantic pass */ static struct relocated * relocated_list = NULL; static __u32 get_relocated_objectid_from_list (struct key * key) { struct relocated *cur = relocated_list; while (cur) { if (cur->old_dir_id == get_key_dirid (key) && cur->old_objectid == get_key_objectid (key)) /* object is relocated already */ return cur->new_objectid; cur = cur->next; } return 0; } /* return objectid the object has to be remapped with */ __u32 objectid_for_relocation (struct key * key) { struct relocated * cur; __u32 cur_id; if ((cur_id = get_relocated_objectid_from_list (key)) != 0) return cur_id; cur = getmem (sizeof (struct relocated)); cur->old_dir_id = get_key_dirid (key); cur->old_objectid = get_key_objectid (key); cur->new_objectid = id_map_alloc(proper_id_map(fs)); cur->next = relocated_list; relocated_list = cur; /* fsck_log ("relocation: (%K) is relocated to (%lu, %lu)\n", key, get_key_dirid (key), cur->new_objectid);*/ return cur->new_objectid; } /* relocated files get added into lost+found with slightly different names */ static __u64 link_one (struct relocated * file) { char * name; struct key obj_key; __u64 len = 0; asprintf (&name, "%lu,%lu", file->old_dir_id, file->new_objectid); set_key_dirid (&obj_key, file->old_dir_id); set_key_objectid (&obj_key, file->new_objectid); /* 0 for fsck_need does not mean too much - it would make effect if there * were no this directory yet. But /lost_found is there already */ len = reiserfs_add_entry (fs, &lost_found_dir_key, name, name_length(name, lost_found_dir_format), &obj_key, 0/*fsck_need*/); pass_2_stat (fs)->relocated ++; free (name); return len; } void linked_already(struct key *new_key /*, link_func_t link_func*/) { struct relocated *cur = relocated_list; struct relocated *prev = NULL; while (cur) { if (cur->old_dir_id == get_key_dirid(new_key) && cur->new_objectid == get_key_objectid(new_key)) break; prev = cur; cur = cur->next; } if (cur) { /* len = link_func(cur); */ if (prev) prev->next = cur->next; else relocated_list = cur->next; freemem (cur); } } void link_relocated_files (void) { struct relocated * tmp; int count; count = 0; while (relocated_list) { link_one (relocated_list); tmp = relocated_list; relocated_list = relocated_list->next; freemem (tmp); count ++; } } /* this item is in tree. All unformatted pointer are correct. Do not check them */ void save_item (struct si ** head, struct item_head * ih, char * item, __u32 blocknr) { struct si * si, * cur; si = getmem (sizeof (*si)); si->si_dnm_data = getmem (get_ih_item_len(ih)); /*si->si_blocknr = blocknr;*/ memcpy (&(si->si_ih), ih, IH_SIZE); memcpy (si->si_dnm_data, item, get_ih_item_len(ih)); if (*head == 0) *head = si; else { cur = *head; while (cur->si_next) cur = cur->si_next; cur->si_next = si; } return; } struct si * save_and_delete_file_item (struct si * si, struct path * path) { struct buffer_head * bh = PATH_PLAST_BUFFER (path); struct item_head * ih = PATH_PITEM_HEAD (path); save_item (&si, ih, B_I_PITEM (bh, ih), bh->b_blocknr); /* delete item temporary - do not free unformatted nodes */ reiserfsck_delete_item (path, 1/*temporary*/); return si; } /* check whether there are any directory items with this key */ int should_relocate (struct item_head * ih) { struct key key; struct key * rkey; struct path path; struct item_head * path_ih; /* starting with the leftmost item with this key */ key = ih->ih_key; set_type_and_offset (KEY_FORMAT_1, &key, SD_OFFSET, TYPE_STAT_DATA); while (1) { reiserfs_search_by_key_4 (fs, &key, &path); if (get_item_pos (&path) == B_NR_ITEMS (get_bh (&path))) { rkey = uget_rkey (&path); if (rkey && !not_of_one_file (&key, rkey)) { /* file continues in the right neighbor */ key = *rkey; pathrelse (&path); continue; } /* there is no more items with this key */ pathrelse (&path); break; } path_ih = get_ih (&path); if (not_of_one_file (&key, &(path_ih->ih_key))) { /* there are no more item with this key */ pathrelse (&path); break; } if (is_stat_data_ih (path_ih)) { fix_obviously_wrong_sd_mode (&path); if (ih_checked (path_ih)) { /* we have checked it already */ pathrelse (&path); if (get_relocated_objectid_from_list (&path_ih->ih_key)) return 1; /* it was relocated */ break; } else { mark_ih_checked (path_ih); mark_buffer_dirty (get_bh(&path)); } } /* ok, item found, but make sure that it is not a directory one */ if ((is_stat_data_ih (path_ih) && !not_a_directory (get_item (&path))) || (is_direntry_ih (path_ih))) { /* item of directory found. so, we have to relocate the file */ pathrelse (&path); return 1; } key = path_ih->ih_key; set_offset (KEY_FORMAT_1, &key, get_offset (&key) + 1); pathrelse (&path); } return 0; } /* this works for both new and old stat data */ #define st_mode(sd) le16_to_cpu(((struct stat_data *)(sd))->sd_mode) #define st_mtime_v1(sd) le32_to_cpu(((struct stat_data_v1 *)(sd))->sd_mtime) #define st_mtime_v2(sd) le32_to_cpu(((struct stat_data *)(sd))->sd_mtime) /* either both sd-s are new of both are old */ static void overwrite_stat_data (struct item_head * new_ih, void * new_item, struct path * path) { __u16 new_mode, old_mode; get_sd_mode (new_ih, new_item, &new_mode); get_sd_mode (get_ih (path), get_item (path), &old_mode); if (S_ISREG (new_mode) && !S_ISREG (old_mode)) { /* in tree we have not regular file - overwrite its stat data with stat data of regular file */ memcpy (get_item (path), new_item, get_ih_item_len (get_ih (path))); mark_buffer_dirty (get_bh (path)); return; } if (S_ISREG (old_mode) && !S_ISREG (new_mode)) { /* new stat data is not a stat data of regular file, keep regular file stat data in tree */ return; } /* if coming stat data has newer mtime - use that */ if (stat_data_v1 (new_ih)) { if (st_mtime_v1 (new_item) > st_mtime_v1 (get_item (path))) { memcpy (get_item (path), new_item, SD_V1_SIZE); mark_buffer_dirty (get_bh (path)); } } else { if (st_mtime_v2 (new_item) > st_mtime_v2 (get_item (path))) { memcpy (get_item (path), new_item, SD_SIZE); mark_buffer_dirty (get_bh (path)); } } return; } /* insert sd item if it does not exist, overwrite it otherwise */ static void put_sd_into_tree (struct item_head * new_ih, char * new_item) { struct path path; if (!not_a_directory (new_item)) { /* new item is a stat data of a directory. So we have to relocate all items which have the same short key and are of not a directory */ rewrite_file (new_ih, 1, 0/*do not change new_ih*/); } else { /* new item is a stat data of something else but directory. If there are items of directory - we have to relocate the file */ if (should_relocate (new_ih)) rewrite_file (new_ih, 1, 1/*change new_ih*/); } /* if we will have to insert item into tree - it is ready */ zero_nlink (new_ih, new_item); mark_item_unreachable (new_ih); /* we are sure now that if we are inserting stat data of a directory - there are no items with the same key which are not items of a directory, and that if we are inserting stat data is of not a directory - it either has new key already or there are no items with this key which are items of a directory */ if (reiserfs_search_by_key_4 (fs, &(new_ih->ih_key), &path) == ITEM_FOUND) { /* this stat data is found */ if (get_ih_key_format (get_ih(&path)) != get_ih_key_format (new_ih)) { /* in tree stat data and a new one are of different formats */ fsck_log ("put_sd_into_tree: Inserting the StatData %K, mode (%M)...", &(new_ih->ih_key), st_mode (new_item)); if (stat_data_v1 (new_ih)) { /* sd to be inserted is of V1, where as sd in the tree is of V2 */ fsck_log ("found newer in the tree, mode (%M), insersion was skipped.\n", st_mode (get_item (&path))); pathrelse (&path); } else { /* the stat data in the tree is sd_v1 */ fsck_log ("older sd, mode (%M), is replaced with it.\n", st_mode (get_item (&path))); reiserfsck_delete_item (&path, 0/*not temporary*/); reiserfs_search_by_key_4 (fs, &new_ih->ih_key, &path); reiserfsck_insert_item (&path, new_ih, new_item); } } else { /* both stat data are of the same version */ overwrite_stat_data (new_ih, new_item, &path); pathrelse (&path); } return; } /* item not found, insert a new one */ reiserfsck_insert_item (&path, new_ih, new_item); } /* this tries to put each item entry to the tree, if there is no items of the directory, insert item containing 1 entry */ static void put_directory_item_into_tree (struct item_head * comingih, char * item) { struct reiserfs_de_head * deh; int i; char * buf; char * name; int namelen; /* if there are anything with this key but a directory - move it somewhere else */ rewrite_file (comingih, 1, 0/* do not change ih */); deh = (struct reiserfs_de_head *)item; for (i = 0; i < get_ih_entry_count (comingih); i ++, deh ++) { name = name_in_entry (deh, i); namelen = name_in_entry_length (comingih, deh, i); if (!is_properly_hashed (fs, name, namelen, get_deh_offset (deh))) reiserfs_panic ("put_directory_item_into_tree: The entry (%d) \"%.*s\" of the directory %k has" " badly hashed entry", i, namelen, name, &comingih->ih_key); asprintf (&buf, "%.*s", namelen, name); /* 1 for fsck is important: if there is no any items of this directory in the tree yet - new item will be inserted marked not reached */ reiserfs_add_entry (fs, &(comingih->ih_key), buf, entry_length (comingih, deh, i), (struct key *)&(deh->deh2_dir_id), 1 << IH_Unreachable); free (buf); } } void insert_item_separately (struct item_head * ih, char * item, int was_in_tree) { if (get_key_dirid (&ih->ih_key) == get_key_objectid (&ih->ih_key)) reiserfs_panic ("insert_item_separately: The item being inserted has the bad key %H", ih); if (is_stat_data_ih (ih)) { put_sd_into_tree (ih, item); } else if (is_direntry_ih (ih)) { put_directory_item_into_tree (ih, item); } else { reiserfsck_file_write (ih, item, was_in_tree); } } static void put_stat_data_items (struct buffer_head * bh) { int i; struct item_head * ih; ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) { /* this check instead of saved_items */ if (!is_stat_data_ih (ih) || is_bad_item (bh, ih, B_I_PITEM (bh, ih))) { continue; } insert_item_separately (ih, B_I_PITEM (bh, ih), 0/*was in tree*/); } } static void put_not_stat_data_items (struct buffer_head * bh) { int i; struct item_head * ih; ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) { if (is_stat_data_ih (ih) || is_bad_item (bh, ih, B_I_PITEM (bh, ih))) { continue; } insert_item_separately (ih, B_I_PITEM (bh, ih), 0/*was in tree*/); } } static void before_pass_2 (reiserfs_filsys_t * fs) { /* anything specific for pass 2 ? */ } static void save_pass_2_result (reiserfs_filsys_t * fs) { FILE * file; int retval; file = open_file("temp_fsck_file.deleteme", "w+"); if (!file) return; /* to be able to restart from semantic we do not need to save anything here, but two magic values */ reiserfs_begin_stage_info_save(file, TREE_IS_BUILT); reiserfs_end_stage_info_save (file); close_file (file); retval = rename ("temp_fsck_file.deleteme", state_dump_file (fs)); if (retval != 0) fsck_progress ("%s: Could not rename the temporary file temp_fsck_file.deleteme to %s", __FUNCTION__, state_dump_file (fs)); } /* we have nothing to load from a state file, but we have to fetch on-disk bitmap, copy it to allocable bitmap, and fetch objectid map */ void load_pass_2_result (reiserfs_filsys_t * fs) { fsck_new_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_copy (fsck_new_bitmap (fs), fs->fs_bitmap2); fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_copy (fsck_allocable_bitmap (fs), fs->fs_bitmap2); fs->block_allocator = reiserfsck_reiserfs_new_blocknrs; fs->block_deallocator = reiserfsck_reiserfs_free_block; /* we need objectid map on semantic pass to be able to relocate files */ proper_id_map (fs) = id_map_init(); /* Not implemented yet. fetch_objectid_map (proper_id_map (fs), fs); */ } /* uninsertable blocks are marked by 0s in uninsertable_leaf_bitmap during the pass 1. They must be not in the tree */ static void do_pass_2 (reiserfs_filsys_t * fs) { struct buffer_head * bh; unsigned long j; int i, what_node; unsigned long done = 0, total; total = reiserfs_bitmap_zeros (fsck_uninsertables (fs)) * 2; if (!total) return; fsck_progress ("\nPass 2:\n"); for (i = 0; i < 2; i++) { j = 0; while (reiserfs_bitmap_find_zero_bit (fsck_uninsertables (fs), &j) == 0) { bh = bread (fs->fs_dev, j, fs->fs_blocksize); if (bh == 0) { fsck_log ("pass_2: Reading of the block (%lu) failed on the device 0x%x\n", j, fs->fs_dev); goto cont; } if (is_block_used (bh->b_blocknr) && !(block_of_journal (fs, bh->b_blocknr) && fsck_data(fs)->rebuild.use_journal_area)) { fsck_log("%s: The block (%lu) is in the tree already. Should not happen.\n", __FUNCTION__, bh->b_blocknr); goto cont; } /* this must be leaf */ what_node = who_is_this (bh->b_data, bh->b_size); if (what_node != THE_LEAF) { // || B_IS_KEYS_LEVEL(bh)) { fsck_log ("%s: The block (%b), marked as a leaf on the first two passes, is not a leaf! Will be skipped.\n", __FUNCTION__, bh); goto cont; } /* fsck_log ("block %lu is being inserted\n", bh->b_blocknr); check_buffers_mem(fsck_log_file (fs)); fflush(fsck_log_file (fs)); */ if (i) { /* insert all not SD items */ put_not_stat_data_items (bh); pass_2_stat (fs)->leaves ++; make_allocable (j); } else /* insert SD items only */ put_stat_data_items (bh); print_how_far (fsck_progress_file (fs), &done, total, 1, fsck_quiet (fs)); cont: brelse (bh); j ++; } } fsck_progress ("\n"); } static void after_pass_2 (reiserfs_filsys_t * fs) { time_t t; /* we can now flush new_bitmap on disk as tree is built and contains all data, which were found on dik at start in used bitmaps */ reiserfs_bitmap_copy (fs->fs_bitmap2, fsck_new_bitmap (fs)); /* we should copy new_bitmap to allocable bitmap, becuase evth what is used for now (marked as used in new_bitmap) should not be allocablel; and what is not in tree for now should be allocable. these bitmaps differ because on pass2 we skip those blocks, whose SD's are not in the tree, and therefore indirect items of such bad leaves points to not used and not allocable blocks. */ /* DEBUG only */ /* if (reiserfs_bitmap_compare (fsck_allocable_bitmap (fs), fsck_new_bitmap(fs))) { fsck_log ("Allocable bitmap differs from the new bitmap after pass2\n"); reiserfs_bitmap_copy (fsck_allocable_bitmap(fs), fsck_new_bitmap (fs)); } */ /* update super block: objectid map, fsck state */ set_sb_fs_state (fs->fs_ondisk_sb, TREE_IS_BUILT); mark_buffer_dirty (fs->fs_super_bh); /* write all dirty blocks */ fsck_progress ("Flushing.."); id_map_flush(proper_id_map (fs), fs); fs->fs_dirt = 1; reiserfs_flush_to_ondisk_bitmap (fs->fs_bitmap2, fs); reiserfs_flush (fs); fsck_progress ("finished\n"); /* fixme: should be optional */ /* fsck_progress ("Tree is built. Checking it - "); reiserfsck_check_pass1 (); fsck_progress ("finished\n");*/ stage_report (2, fs); /* free what we do not need anymore */ reiserfs_delete_bitmap (fsck_uninsertables (fs)); if (!fsck_run_one_step (fs)) { if (fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1)) /* reiserfsck continues */ return; } else save_pass_2_result (fs); id_map_free(proper_id_map (fs)); proper_id_map (fs) = 0; reiserfs_delete_bitmap (fsck_new_bitmap (fs)); reiserfs_delete_bitmap (fsck_allocable_bitmap (fs)); time (&t); fsck_progress ("###########\n" "reiserfsck finished pass 2 at %s" "###########\n", ctime (&t)); fs->fs_dirt = 1; reiserfs_close (fs); exit(0); } void pass_2 (reiserfs_filsys_t * fs) { if (fsck_log_file (fs) != stderr) fsck_log ("####### Pass 2 #######\n"); before_pass_2 (fs); /* take blocks which were not inserted into tree yet and put each item separately */ do_pass_2 (fs); after_pass_2 (fs); if (get_sb_root_block (fs->fs_ondisk_sb) == ~0ul || get_sb_root_block (fs->fs_ondisk_sb) == 0) die ( "\nNo reiserfs metadata found. If you are sure that you had the reiserfs\n" "on this partition, then the start of the partition might be changed\n" "or all data were wiped out. The start of the partition may get changed\n" "by a partitioner if you have used one. Then you probably rebuilt the\n" "superblock as there was no one. Zero the block at 64K offset from the\n" "start of the partition (a new super block you have just built) and try\n" "to move the start of the partition a few cylinders aside and check if\n" "debugreiserfs /dev/xxx detects a reiserfs super block. If it does this\n" "is likely to be the right super block version. \n" "If this makes you nervous, try www.namesys.com/support.html, and for\n" "$25 the author of fsck, or a colleague if he is out, will step you\n" "through it all.\n"); } reiserfsprogs-3.6.9/fsck/pass4.c0000664000077100007710000000373307665645672012276 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" void pass_4_check_unaccessed_items (void) { struct key key; struct path path; int i; struct buffer_head * bh; struct item_head * ih; unsigned long items; struct key * rdkey; path.path_length = ILLEGAL_PATH_ELEMENT_OFFSET; key = root_dir_key; fsck_progress ("Pass 4 - "); items = 0; while (reiserfs_search_by_key_4 (fs, &key, &path) == ITEM_FOUND) { bh = PATH_PLAST_BUFFER (&path); /* print ~ how many leaves were scanned and how fast it was */ if (!fsck_quiet (fs)) print_how_fast (items++, 0, 50, 0); for (i = get_item_pos (&path), ih = get_ih (&path); i < B_NR_ITEMS (bh); i ++, ih ++) { if (!is_item_reachable (ih)) { PATH_LAST_POSITION (&path) = i; rdkey = get_next_key_2 (&path); if (rdkey) key = *rdkey; else memset (&key, 0xff, KEY_SIZE); pass_4_stat (fs)->deleted_items ++; reiserfsck_delete_item (&path, 0); goto cont; } if (get_ih_flags(ih) != 0) { clean_ih_flags(ih); mark_buffer_dirty(bh); } } PATH_LAST_POSITION(&path) = i - 1; rdkey = reiserfs_next_key (&path); if (rdkey) key = *rdkey; else memset (&key, 0xff, KEY_SIZE); pathrelse (&path); cont: /* to make gcc 3.2 do not sware here */; } pathrelse (&path); fsck_progress ("finished\n"); stage_report (4, fs); /* after pass 4 */ /* put bitmap on place */ reiserfs_bitmap_copy (fs->fs_bitmap2, fsck_new_bitmap (fs)); /* update super block */ set_sb_free_blocks (fs->fs_ondisk_sb, reiserfs_bitmap_zeros (fsck_new_bitmap (fs))); mark_buffer_dirty (fs->fs_super_bh); /* write all dirty blocks */ fsck_progress ("Flushing.."); fs->fs_dirt = 1; id_map_flush(proper_id_map (fs), fs); reiserfs_flush_to_ondisk_bitmap (fs->fs_bitmap2, fs); reiserfs_flush (fs); fsck_progress ("finished\n"); return; } reiserfsprogs-3.6.9/tune/0000777000077100007710000000000007705315454011164 5reiserfsprogs-3.6.9/tune/reiserfstune.80000664000077100007710000001506507705261642013717 .\" -*- nroff -*- .\" Copyright 1996-2003 Hans Reiser. .\" .TH REISERFSTUNE 8 "April 2003" "Reiserfsprogs-3.6.9" .SH NAME reiserfstune .SH SYNOPSIS .B reiserfstune [ \fB-f\fR ] [ \fB-j\fR | \fB--journal-device\fR \fIFILE\fR ] [ \fB--no-journal-available\fR ] [ \fB--journal-new-device\fR \fIFILE\fR ] [ \fB--make-journal-standard\fR ] [ \fB-s\fR | \fB--journal-new-size\fR \fIN\fR ] [ \fB-o\fR | \fB--journal-new-offset\fR \fIN\fR ] [ \fB-t\fR | \fB--max-transaction-size\fR \fIN\fR ] [ \fB-u\fR | \fB--uuid \fIUUID\fR ] [ \fB-l\fR | \fB--label \fILABEL\fR ] .I device .SH DESCRIPTION \fBreiserfstune\fR is used for tuning the ReiserFS journal. It can change two parameters (journal size and maximum transaction size), and it can move the journal's location to a new specified block device. (The old ReiserFS's journal may be kept unused, or discarded at the user's option.) Note: At the time of writing this feature was implemented for a special release of ReiserFS, and was not expected to be put into the mainstream kernel until approximately Linux 2.5. This means that if you have the stock kernel you must apply a special patch. Without this patch the kernel will refuse to mount the newly modified file system. We will charge $25 to explain this to you if you ask us why it doesn't work. .PP Perhaps the most interesting application of this code is to put the journal on a solid state disk. .TP \fIdevice is the special file corresponding to the newly specified block device (e.g /dev/hdXX for IDE disk partition or /dev/sdXX for the SCSI disk partition). .SH OPTIONS .TP \fB-j\fR | \fB--journal-device\fR \fIFILE \fIFILE\fR is the file name of the block device the file system has the current journal (the one prior to running reiserfstune) on. This option is required when the journal is already on a separate device from the main data device (although it can be avoided with \fB--no-journal-available\fR). If you don't specify journal device by this option, reiserfstune suppose that journal is on main device. .TP \fB--no-journal-available allows \fBreiserfstune\fR to continue when the current journal's block device is no longer available. This might happen if a disk goes bad and you remove it (and run fsck). .TP \fB--journal-new-device \fIFILE \fIFILE\fR is the file name of the block device which will contain the new journal for the file system. If you don't specify this, reiserfstune supposes that journal device remains the same. .TP \fB \-s\fR | \fB\--journal-new-size \fIN \fIN\fR is the size parameter for the new journal. When journal is to be on a separate device - its size defaults to number of blocks that device has. When journal is to be on the same device as the filesytem - its size defaults to amount of blocks allocated for journal by \fImkreiserfs\fR when it created the filesystem. Minimum is 513 for both cases. .TP \fB \-o\fR | \fB\--journal-new-offset \fIN \fIN\fR is an offset in blocks where journal will starts from when journal is to be on a separate device. Default is 0. Has no effect when journal is to be on the same device as the filesystem. Most users have no need to use this feature. It can be used when you want the journals from multiple filesystems to reside on the same device, and you don't want to or cannot partition that device. .TP \fB \-t\fR | \fB\--maximal-transaction-size \fIN \fI\fR is the maximum transaction size parameter for the new journal. The default, and max possible, value is 1024 blocks. It should be less than half the size of the journal. If specifed incorrectly, it will be adjusted. .TP \fB\-f\fR | \fB--force\fR Normally \fBreiserfstune\fR will refuse to change a journal of a file system that was created before this journal relocation code. This is because if you change the journal, you cannot go back (without special option \fB--make-journal-standard\fR) to an old kernel that lacks this feature and be able to use your filesytem. This option forces it to do that. Specified more than once it allows to avoid asking for confirmation. .TP \fB--make-journal-standard\fR As it was mentioned above, if your file system has non-standard journal, it can not be mounted on the kernel without journal relocation code. The thing can be changed, the only condition is that there is reserved area on main device of the standard journal size 8193 blocks (it will be so for instance if you convert standard journal to non-standard). Just specify this option when you relocate journal back, or without relocation if you already have it on main device. .TP \fB-u\fR | \fB--uuid \fIUUID\fR Set the universally unique identifier (\fB UUID \fR) of the filesystem to \fIUUID\fR (see also \fBuuidgen(8)\fR). The format of the UUID is a series of hex digits separated by hypthens, like this: "c1b9d5a2-f162-11cf-9ece-0020afc76f16". .TP \fB-l\fR | \fB--label \fILABEL\fR Set the volume label of the filesystem. \fILABEL\fR can be at most 16 characters long; if it is longer than 16 characters, reiserfstune will truncate it. .SH POSSIBLE SCENARIOS OF USING REISERFSTUNE: 1. You have ReiserFS on /dev/hda1, and you wish to have it working with its journal on the device /dev/journal .nf .IP boot kernel patched with special "relocatable journal support" patch reiserfstune /dev/hda1 --journal-new-device /dev/journal -f mount /dev/hda1 and use. You would like to change max transaction size to 512 blocks reiserfstune -t 512 /dev/hda1 You would like to use your file system on another kernel that doesn't contain relocatable journal support. umount /dev/hda1 reiserfstune /dev/hda1 -j /dev/journal --journal-new-device /dev/hda1 --make-journal-standard mount /dev/hda1 and use. .LP 2. You would like to have ReiserFS on /dev/hda1 and to be able to switch between different journals including journal located on the device containing the filesystem. .nf .IP boot kernel patched with special "relocatable journal support" patch mkreiserfs /dev/hda1 you got solid state disk (perhaps /dev/sda, they typically look like scsi disks) reiserfstune --journal-new-device /dev/sda1 -f /dev/hda1 Your scsi device dies, it is three in the morning, you have an extra IDE device lying around reiserfsck --no-journal-available /dev/hda1 or reiserfsck --rebuild-tree --no-journal-available /dev/hda1 reiserfstune --no-journal-available --journal-new-device /dev/hda1 /dev/hda1 using /dev/hda1 under patched kernel .SH AUTHOR This version of \fBreiserfstune\fR has been written by Vladimir Demidov and Edward Shishkin . .SH BUGS Please repoort bugs to the ReiserFS mail list .SH SEE ALSO .BR reiserfsck (8), .BR debugreiserfs (8), .BR mkreiserfs (8) reiserfsprogs-3.6.9/tune/Makefile.am0000664000077100007710000000030207665645673013147 sbin_PROGRAMS = reiserfstune reiserfstune_SOURCES = tune.c tune.h man_MANS = reiserfstune.8 EXTRA_DIST = $(man_MANS) LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a reiserfsprogs-3.6.9/tune/Makefile.in0000644000077100007710000003226507705315226013152 # Makefile.in generated by automake 1.7.2 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__quote = @am__quote@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ sbin_PROGRAMS = reiserfstune reiserfstune_SOURCES = tune.c tune.h man_MANS = reiserfstune.8 EXTRA_DIST = $(man_MANS) LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a subdir = tune mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = sbin_PROGRAMS = reiserfstune$(EXEEXT) PROGRAMS = $(sbin_PROGRAMS) am_reiserfstune_OBJECTS = tune.$(OBJEXT) reiserfstune_OBJECTS = $(am_reiserfstune_OBJECTS) reiserfstune_LDADD = $(LDADD) reiserfstune_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \ $(top_srcdir)/reiserfscore/libcore.a reiserfstune_LDFLAGS = DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/tune.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(reiserfstune_SOURCES) NROFF = nroff MANS = $(man_MANS) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(reiserfstune_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu tune/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(sbindir) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f || exit 1; \ else :; fi; \ done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ rm -f $(DESTDIR)$(sbindir)/$$f; \ done clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) reiserfstune$(EXEEXT): $(reiserfstune_OBJECTS) $(reiserfstune_DEPENDENCIES) @rm -f reiserfstune$(EXEEXT) $(LINK) $(reiserfstune_LDFLAGS) $(reiserfstune_OBJECTS) $(reiserfstune_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tune.Po@am__quote@ distclean-depend: -rm -rf ./$(DEPDIR) .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: man8dir = $(mandir)/man8 install-man8: $(man8_MANS) $(man_MANS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(man8dir) @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.8*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ *) ext='8' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ done uninstall-man8: @$(NORMAL_UNINSTALL) @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.8*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ *) ext='8' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ rm -f $(DESTDIR)$(man8dir)/$$inst; \ done ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) installdirs: $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(man8dir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-man install-exec-am: install-sbinPROGRAMS install-info: install-info-am install-man: install-man8 installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am uninstall-man uninstall-sbinPROGRAMS uninstall-man: uninstall-man8 .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-sbinPROGRAMS ctags distclean distclean-compile \ distclean-depend distclean-generic distclean-tags distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-man8 install-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-info-am uninstall-man \ uninstall-man8 uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: reiserfsprogs-3.6.9/tune/tune.c0000444000077100007710000004507307705265616012232 /* * Copyright 2002-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "tune.h" char *program_name; static void message( const char * fmt, ... ) __attribute__ ((format (printf, 1, 2))); static void message( const char * fmt, ... ) { char *buf; va_list args; buf = NULL; va_start( args, fmt ); vasprintf( &buf, fmt, args ); va_end( args ); if( buf ) { fprintf( stderr, "%s: %s\n", program_name, buf ); free( buf ); } } reiserfs_filsys_t * fs; static void print_usage_and_exit(void) { message ("Usage: %s [options] " " device [block-count]\n" "\n" "Options:\n\n" " -j | --journal-device file\n" " --journal-new-device file\n" " -o | --journal-new-offset N\n" " -s | --journal-new-size N\n" " -t | --transaction-max-size N\n" " --no-journal-available\n" " --make-journal-standard\n" /*"\t-p | --keep-old-journal-param (keep parametrs from old journal to new one)\n"*/ " -u | --uuid UUID|random\n" " -l | --label LABEL\n" " -f | --force \n", program_name); exit (1); } /* Undocumented options: -B badblock_file */ unsigned long Journal_size = 0; int Max_trans_size = JOURNAL_TRANS_MAX; int Offset = 0; __u16 Options = 0; int Force = 0; char * LABEL; unsigned char UUID[16]; char * badblocks_file; /* If specified paramenters defines the standard journal, make it standard. */ static int should_make_journal_standard (reiserfs_filsys_t * fs, char * j_new_dev_name) { if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb)) return 0; /* if (!user_confirmed (stderr, "ATTENTION! Filesystem with non-standard journal " "found. Continue? (y/n):", "y\n")) { exit(1); } */ /* make sure journal is on main device, it has default size and the file system has non-standard magic */ if (j_new_dev_name) { /* new journal was specified - check if it is available */ if (strcmp (j_new_dev_name, fs->fs_file_name)) return 0; if (Journal_size && Journal_size != journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1) return 0; if (Max_trans_size && (Max_trans_size != JOURNAL_TRANS_MAX)) return 0; } else { /* new journal was not specified - check ondisk journal params */ if (get_sb_reserved_for_journal(fs->fs_ondisk_sb) < journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1) { message ("Can not create standard journal of the size %llu", journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1); return 0; } } return 1; } static int set_standard_journal_params (reiserfs_filsys_t * fs) { struct buffer_head * bh; /* ondisk superblock update */ if (get_sb_version(fs->fs_ondisk_sb) == 0) memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_5_SUPER_MAGIC_STRING, strlen (REISERFS_3_5_SUPER_MAGIC_STRING)); else if (get_sb_version(fs->fs_ondisk_sb) == 2) memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_6_SUPER_MAGIC_STRING, strlen (REISERFS_3_6_SUPER_MAGIC_STRING)); else { message ("Can not set standard reiserfs magic: unknown format found %u," " try reiserfsck first", get_sb_version(fs->fs_ondisk_sb)); return 0; } set_jp_journal_1st_block (sb_jp(fs->fs_ondisk_sb), get_journal_start_must (fs)); set_jp_journal_dev (sb_jp(fs->fs_ondisk_sb), 0); set_jp_journal_size (sb_jp(fs->fs_ondisk_sb), journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)); if (get_jp_journal_max_trans_len(sb_jp(fs->fs_ondisk_sb)) != JOURNAL_TRANS_MAX) set_jp_journal_max_trans_len(sb_jp(fs->fs_ondisk_sb), JOURNAL_TRANS_MAX); if (get_jp_journal_max_batch(sb_jp(fs->fs_ondisk_sb)) != JOURNAL_MAX_BATCH) set_jp_journal_max_batch(sb_jp(fs->fs_ondisk_sb), JOURNAL_MAX_BATCH); if (get_jp_journal_max_commit_age(sb_jp(fs->fs_ondisk_sb)) != JOURNAL_MAX_COMMIT_AGE) set_jp_journal_max_commit_age(sb_jp(fs->fs_ondisk_sb), JOURNAL_MAX_COMMIT_AGE); if (get_jp_journal_max_trans_age(sb_jp(fs->fs_ondisk_sb)) != JOURNAL_MAX_TRANS_AGE) set_jp_journal_max_trans_age(sb_jp(fs->fs_ondisk_sb), JOURNAL_MAX_TRANS_AGE); set_sb_reserved_for_journal (fs->fs_ondisk_sb, 0); /* journal_header update */ bh = getblk(fs->fs_journal_dev, get_jp_journal_1st_block(sb_jp(fs->fs_ondisk_sb)) + get_jp_journal_size(sb_jp(fs->fs_ondisk_sb)), fs->fs_blocksize); if (!bh) { message ("Cannot get the journal header block. getblk failed.\n"); return 0; } ((struct reiserfs_journal_header *)(bh->b_data))->jh_journal = *(sb_jp(fs->fs_ondisk_sb)); mark_buffer_uptodate (bh, 1); mark_buffer_dirty (bh); bwrite(bh); brelse(bh); return 1; } void zero_journal (reiserfs_filsys_t * fs) { unsigned int i; struct buffer_head * bh; unsigned long done; unsigned long start, len; fprintf (stderr, "Initializing journal - "); start = get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb)); len = get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)); done = 0; for (i = 0; i < len; i ++) { print_how_far (stderr, &done, len, 1, 1/*be quiet*/); bh = getblk (fs->fs_journal_dev, start + i, fs->fs_blocksize); if (!bh) die ("zero_journal: getblk failed"); memset (bh->b_data, 0, bh->b_size); mark_buffer_dirty (bh); mark_buffer_uptodate (bh, 1); bwrite (bh); brelse (bh); } fprintf (stderr, "\n"); fflush (stderr); } static int str2int (char * str) { int val; char * tmp; val = (int) strtol (str, &tmp, 0); if (*tmp) die ("%s: strtol is unable to make an integer of %s\n", program_name, str); return val; } static void set_transaction_max_size (char * str) { Max_trans_size = str2int( str ); } /* journal must fit into number of blocks pointed by first bitmap */ static void set_journal_device_size (char * str) { Journal_size = str2int (str) ; } static void set_offset_in_journal_device (char * str) { Offset = str2int( str ); } int main (int argc, char **argv) { reiserfs_filsys_t * fs; char * device_name; char * jdevice_name; char * j_new_device_name; int c; static int flag; struct reiserfs_journal_header * j_head; reiserfs_trans_t old, new; int Is_journal_or_maxtrans_size_specified = 0; program_name = strrchr( argv[ 0 ], '/' ); if (program_name) program_name++; else program_name = argv[ 0 ]; print_banner (program_name); if (argc < 2) print_usage_and_exit (); device_name = 0; jdevice_name = 0; j_new_device_name = 0; while (1) { static struct option options[] = { {"journal-device", required_argument, 0, 'j'}, {"journal-new-device", required_argument, &flag, OPT_NEW_J}, {"journal-new-size", required_argument, 0, 's'}, {"transaction-max-size", required_argument, 0, 't'}, {"journal-new-offset", required_argument, 0, 'o'}, {"no-journal-available", no_argument, &flag, OPT_SKIP_J}, /*{"keep-old-journal-param", no_argument, 0, 'p'},*/ {"uuid", required_argument, 0, 'u'}, {"label", required_argument, 0, 'l'}, {"force", no_argument, 0, 'f'}, {"really-force", no_argument, &flag, OPT_SUPER_FORCE}, {"make-journal-standard", no_argument, &flag, OPT_STANDARD}, {0, 0, 0, 0} }; int option_index; c = getopt_long (argc, argv, "j:s:t:o:fu:l:B:", options, &option_index); if (c == -1) break; switch (c) { case 0: /* long-only optins */ if (flag == OPT_NEW_J) { Options |= OPT_NEW_J; j_new_device_name = optarg; } if (flag == OPT_SKIP_J) { Options |= OPT_SKIP_J; } if (flag == OPT_SUPER_FORCE) { Options |=OPT_SUPER_FORCE; } if (flag == OPT_STANDARD) { Options |=OPT_STANDARD; } break; case 'j': /* --journal-device */ jdevice_name = optarg; break; case 's': /* --journal-new-size */ set_journal_device_size (optarg); Is_journal_or_maxtrans_size_specified = 1; break; case 't': /* --transaction-max-size */ set_transaction_max_size (optarg); Is_journal_or_maxtrans_size_specified = 1; break; case 'o': /* --offset */ set_offset_in_journal_device (optarg); break; case 'f': /* forces replacing standard journal with non-standard one. Specified more than once - allows to avoid asking for confirmation */ Force ++; break; case 'B': /* --badblock-list */ asprintf (&badblocks_file, "%s", optarg); break; case 'u': /* UUID */ if (!strcmp(optarg, "random")) { if (generate_random_uuid (UUID)) message ("failed to genetate UUID\n"); } else { if (set_uuid (optarg, UUID)) { message ("wrong UUID specified\n"); return 1; } } break; case 'l': /* LABEL */ LABEL = optarg; break; #if 0 case 'J': /* --journal-new-device */ Options |= OPT_NEW_J; j_new_device_name = optarg; break; case 'u': /* --no-journal-available */ Options |= OPT_SKIPJ; break; case 'p': /* --keep-old-journal-param */ Options |= OPT_KEEPO; break; #endif default: print_usage_and_exit(); } } if (optind != argc - 1) print_usage_and_exit (); /* device to be formatted */ device_name = argv [optind]; fs = reiserfs_open (device_name, O_RDONLY, 0, NULL, 1); if (no_reiserfs_found(fs)) { message ("Cannot open reiserfs on %s", device_name); return 1; } /* journal was opened or it wasn't opened but the option --no-journal-available has been specified by user */ /* make sure filesystem is not mounted */ if (is_mounted (fs->fs_file_name)) { /* fixme: it can not be mounted, btw */ message ("Reiserfstune is not allowed to be run on mounted filesystem."); reiserfs_close (fs); return 1; } if (!reiserfs_is_fs_consistent (fs)) { message ("Filesystem looks not cleanly umounted, check the consistency first.\n"); reiserfs_close (fs); return 1; } reiserfs_reopen (fs, O_RDWR); if (badblocks_file) { unsigned long i, marked = 0; if (reiserfs_open_ondisk_bitmap (fs) < 0) { message("Failed to open reiserfs ondisk bitmap.\n"); reiserfs_close(fs); exit(1); } if (create_badblock_bitmap (fs, badblocks_file)) { message("Failed to initialize the bad block bitmap.\n"); reiserfs_close(fs); exit(1); } for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { if (reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i)) { if (!reiserfs_bitmap_test_bit (fs->fs_bitmap2, i)) { reiserfs_bitmap_set_bit (fs->fs_bitmap2, i); marked++; } else { /* Check that this is a block */ if (not_data_block(fs, i)) { message("Block %lu belongs to the internal reiserfs area " "and cannot be reloacted.\n", i); exit(1); } else { message("Block %lu is used already in reiserfs tree.\n", i); } } } } message("%lu bad blocks were marked as used.\n", marked); reiserfs_close(fs); exit(0); } if (!jdevice_name && !(Options & OPT_SKIP_J)) { message ("Journal device has not been specified. Assuming journal is on the main " "device (%s).\n", device_name); jdevice_name = device_name; } if (jdevice_name && (Options & OPT_SKIP_J)) { message ("Either specify journal device, " "or choose the option --no-journal-available"); return 1; } if (j_new_device_name && (Options & OPT_STANDARD)) { /* New device was specified and --make-journal-standard was also. */ message ("Either specify new journal device, " "or choose the option --make-journal-standard"); return 1; } /* now we try to open journal, it makes sence if there is no the flag NEED_TUNE in ondisk superblock and --no-journal available is not specified. */ if (get_jp_journal_magic(sb_jp(fs->fs_ondisk_sb)) != NEED_TUNE && !(Options & OPT_SKIP_J)) { if (reiserfs_open_journal (fs, jdevice_name, O_RDWR | O_LARGEFILE)) { message ("Failed to open the journal device (%s).", jdevice_name); return 1; } if (reiserfs_journal_params_check(fs)) { message ("Unable to open old journal. Wrong journal parameters."); reiserfs_close (fs); return 1; } } /* in spite of journal was opened, the file system can be non-consistent or there are non-replayed transaction in journal, make sure it isn't (if there is no the flag NEED_TUNE in ondisk superblock */ if (get_jp_journal_magic(sb_jp(fs->fs_ondisk_sb)) != NEED_TUNE && reiserfs_journal_opened (fs)) { j_head = (struct reiserfs_journal_header *)(fs->fs_jh_bh->b_data); if (get_boundary_transactions(fs, &old, &new)) { if (new.trans_id != get_jh_last_flushed(j_head)) { if (!(Options & OPT_SUPER_FORCE)) { message ("There are non-replayed transaction in old journal," " check filesystem consistency first"); reiserfs_close (fs); return 1; } } } if (!reiserfs_is_fs_consistent (fs)) { message ("Check filesystem consistency first"); reiserfs_close (fs); return 1; } } /* set UUID and LABEL if specified */ if (fs->fs_format == REISERFS_FORMAT_3_6) { if (uuid_is_correct (UUID)) { memcpy (fs->fs_ondisk_sb->s_uuid, UUID, 16); mark_buffer_dirty (fs->fs_super_bh); fs->fs_dirt = 1; } if (LABEL != NULL) { if (strlen (LABEL) > 16) message ("Specified LABEL is longer then 16 characters, will be truncated\n"); strncpy (fs->fs_ondisk_sb->s_label, LABEL, 16); mark_buffer_dirty (fs->fs_super_bh); fs->fs_dirt = 1; } } else { if (uuid_is_correct (UUID)) reiserfs_panic ("UUID cannot be specified for 3.5 format\n"); if (LABEL) reiserfs_panic ("LABEL cannot be specified for 3.5 format\n"); } if (!j_new_device_name) { /* new journal device hasn't been specified */ printf ("Current parameters:\n"); print_filesystem_state (stdout, fs); print_block (stdout, fs, fs->fs_super_bh); if ((Options & OPT_STANDARD) && should_make_journal_standard(fs, j_new_device_name)) { if (!user_confirmed (stderr, "ATTENTION! Filesystem with " "non-standard journal found. Continue? (y/n):", "y\n")) { exit(1); } fs->fs_journal_dev = fs->fs_dev; if (set_standard_journal_params (fs)) { printf ("\nNew parameters:\n"); print_filesystem_state (stdout, fs); print_block (stdout, fs, fs->fs_super_bh); printf ("New journal parameters:\n"); print_journal_params (stdout, sb_jp (fs->fs_ondisk_sb)); mark_buffer_dirty (fs->fs_super_bh); mark_buffer_uptodate (fs->fs_super_bh, 1); reiserfs_close (fs); printf ("Syncing.."); fflush (stdout); sync (); printf ("ok\n"); return 0; } } if (Is_journal_or_maxtrans_size_specified) { /* new journal device hasn't been specified, but journal size or max transaction size have been, so we suppose that journal device remains the same */ if (!reiserfs_journal_opened (fs)) { message("Cannot set up new paramenters for not specified journal."); return 1; } j_new_device_name = jdevice_name; } else { /* the only parameter has been specified is device_name, so there is nothing to do */ reiserfs_close (fs); return 0; } } /* new journal device has been specified */ /* make sure new journal device is block device file */ if (!can_we_format_it (j_new_device_name, Force)) { reiserfs_close (fs); return 1; } if (!strcmp (device_name, j_new_device_name)) { unsigned long reserved, journal_size; /* we have to put journal on main device. It is only possible if there is enough space reserved by mkreiserfs */ if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb)) /* standard journal */ reserved = get_jp_journal_size(sb_jp(fs->fs_ondisk_sb)) + 1; else /* non-standard journal */ reserved = get_sb_reserved_for_journal (fs->fs_ondisk_sb); journal_size = Journal_size; if (!journal_size) { journal_size = journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1; message("Journal size has not been specified. Assuming it is the default size (%lu)", journal_size); } /* journal_size = (Journal_size ? Journal_size : // specified (fs->fs_blocksize == 1024 ? (fs->fs_blocksize) * 8 - 3 - REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize : JOURNAL_DEFAULT_SIZE + 1)); // default */ if (journal_size + Offset > get_journal_start_must (fs) + reserved) { message ("There is no enough space reserved for journal on main " "device (journal_size=%lu, reserved=%lu)\n", journal_size, reserved); reiserfs_close (fs); return 1; } } message ("Current journal parameters:"); print_journal_params (stdout, sb_jp (fs->fs_ondisk_sb)); if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb)) { /* we have standard journal, so check if we can convert it to non-standard one */ /* if (!should_make_journal_non_standard (Force)) { reiserfs_close (fs); return 1; } */ if (is_reiserfs_3_6_magic_string (fs->fs_ondisk_sb)) set_sb_version (fs->fs_ondisk_sb, REISERFS_FORMAT_3_6); else if (is_reiserfs_3_5_magic_string (fs->fs_ondisk_sb)) set_sb_version (fs->fs_ondisk_sb, REISERFS_FORMAT_3_5); else { message ("Could not convert from unknown version, try reiserfsck first"); reiserfs_close (fs); return 1; } memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_JR_SUPER_MAGIC_STRING, strlen (REISERFS_JR_SUPER_MAGIC_STRING)); set_sb_reserved_for_journal (fs->fs_ondisk_sb, get_jp_journal_size (sb_jp(fs->fs_ondisk_sb)) + 1); } /* now we are going to close old journal and to create a new one */ reiserfs_close_journal (fs); if (!reiserfs_create_journal (fs, j_new_device_name, Offset, Journal_size, Max_trans_size)) { message ("Could not create new journal"); reiserfs_close (fs); return 1; } if (should_make_journal_standard (fs, j_new_device_name)) set_standard_journal_params (fs); message ("New journal parameters:"); print_journal_params (stdout, sb_jp (fs->fs_ondisk_sb)); print_block (stdout, fs, fs->fs_super_bh); if (Force < 2) { message ("ATTENTION: YOU ARE ABOUT TO SETUP THE NEW JOURNAL FOR THE \"%s\"!\n" "AREA OF \"%s\" DEDICATED FOR JOURNAL WILL BE ZEROED!", device_name, j_new_device_name); if (!user_confirmed (stderr, "Continue (y/n):", "y\n")) { return 1; } } zero_journal (fs); reiserfs_close (fs); printf ("Syncing.."); fflush (stdout); sync (); printf ("ok\n"); return 0; } reiserfsprogs-3.6.9/tune/tune.h0000664000077100007710000000167407665645673012254 /* * Copyright 2002-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "io.h" #include "misc.h" #include "reiserfs_lib.h" #include "../include/config.h" #include "../version.h" /* main.c */ extern reiserfs_filsys_t * fs; /* * options */ #define OPT_SUPER_FORCE 0x0010 #define OPT_OLD_J 0x0100 #define OPT_NEW_J 0x0200 #define OPT_SIZEJ 0x0400 #define OPT_TMAXS 0x0800 #define OPT_OFSET 0x1000 #define OPT_SKIP_J 0x2000 #define OPT_KEEPO 0x4000 #define OPT_FORCE 0x8000 #define OPT_STANDARD 0x0020 extern char *program_name; reiserfsprogs-3.6.9/depcomp0000755000077100007710000002753307634203260011504 #! /bin/sh # depcomp - compile a program generating dependencies as side-effects # Copyright 1999, 2000 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # `libtool' can also be set to `yes' or `no'. if test -z "$depfile"; then base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` dir=`echo "$object" | sed 's,/.*$,/,'` if test "$dir" = "$object"; then dir= fi # FIXME: should be _deps on DOS. depfile="$dir.deps/$base" fi tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. This file always lives in the current directory. # Also, the AIX compiler puts `$object:' at the start of each line; # $object doesn't have directory information. stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" outname="$stripped.o" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1="$dir.libs/$base.lo.d" tmpdepfile2="$dir.libs/$base.d" "$@" -Wc,-MD else tmpdepfile1="$dir$base.o.d" tmpdepfile2="$dir$base.d" "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi if test -f "$tmpdepfile1"; then tmpdepfile="$tmpdepfile1" else tmpdepfile="$tmpdepfile2" fi if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a space and a tab in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. We will use -o /dev/null later, # however we can't do the remplacement now because # `-o $object' might simply not be used IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M "$@" -o /dev/null $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # X makedepend shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes ;; esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; -*) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " for arg do case "$arg" in "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 reiserfsprogs-3.6.9/aclocal.m40000644000077100007710000007236207705315222011770 # generated automatically by aclocal 1.7.2 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # Do all the work for Automake. -*- Autoconf -*- # This macro actually does too much some checks are only needed if # your package does certain things. But this isn't really a big deal. # Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 8 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... AC_PREREQ([2.54]) # Autoconf 2.50 wants to disallow AM_ names. We explicitly allow # the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl AC_SUBST([PACKAGE], [AC_PACKAGE_TARNAME])dnl AC_SUBST([VERSION], [AC_PACKAGE_VERSION])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AM_MISSING_PROG(AMTAR, tar) AM_PROG_INSTALL_SH AM_PROG_INSTALL_STRIP # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl ]) ]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [_am_stamp_count=`expr ${_am_stamp_count-0} + 1` echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) # Copyright 2002 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.7"]) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION so it can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.7.2])]) # Helper functions for option handling. -*- Autoconf -*- # Copyright 2001, 2002 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 2 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # # Check to make sure that the build environment is sane. # # Copyright 1996, 1997, 2000, 2001 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 3 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # -*- Autoconf -*- # Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 3 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # AM_AUX_DIR_EXPAND # Copyright 2001 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. # Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50]) AC_DEFUN([AM_AUX_DIR_EXPAND], [ # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. # Copyright 2001 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl install_sh=${install_sh-"$am_aux_dir/install-sh"} AC_SUBST(install_sh)]) # AM_PROG_INSTALL_STRIP # Copyright 2001 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # serial 4 -*- Autoconf -*- # Copyright 1999, 2000, 2001 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi for depmode in $am_compiler_list; do # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. echo '#include "conftest.h"' > conftest.c echo 'int i;' > conftest.h echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=conftest.c object=conftest.o \ depfile=conftest.Po tmpdepfile=conftest.TPo \ $SHELL ./depcomp $depcc -c -o conftest.o conftest.c >/dev/null 2>&1 && grep conftest.h conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then am_cv_$1_dependencies_compiler_type=$depmode break fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [rm -f .deps 2>/dev/null mkdir .deps 2>/dev/null if test -d .deps; then DEPDIR=.deps else # MS-DOS does not allow filenames that begin with a dot. DEPDIR=_deps fi rmdir .deps 2>/dev/null AC_SUBST([DEPDIR]) ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking Speeds up one-time builds --enable-dependency-tracking Do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH]) ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. #serial 2 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi grep '^DEP_FILES *= *[[^ @%:@]]' < "$mf" > /dev/null || continue # Extract the definition of DEP_FILES from the Makefile without # running `make'. DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` test -z "$DEPDIR" && continue # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n -e '/^U = / s///p' < "$mf"` test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" # We invoke sed twice because it is the simplest approach to # changing $(DEPDIR) to its actual value in the expansion. for file in `sed -n -e ' /^DEP_FILES = .*\\\\$/ { s/^DEP_FILES = // :loop s/\\\\$// p n /\\\\$/ b loop p } /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 2 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' doit: @echo done END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi AC_SUBST(am__include) AC_SUBST(am__quote) AC_MSG_RESULT($_am_result) rm -f confinc confmf ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright 1997, 2000, 2001 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 5 AC_PREREQ(2.52) # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE]) AC_SUBST([$1_FALSE]) if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]) fi])]) # Like AC_CONFIG_HEADER, but automatically create stamp file. -*- Autoconf -*- # Copyright 1996, 1997, 2000, 2001 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. AC_PREREQ([2.52]) # serial 6 # AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) reiserfsprogs-3.6.9/tests/0000777000077100007710000000000007705315454011353 5reiserfsprogs-3.6.9/tests/PROGS/0000777000077100007710000000000007705315454012245 5reiserfsprogs-3.6.9/tests/PROGS/Makefile.am0000664000077100007710000000020507665645673014232 sbin_PROGRAMS = reiserfs_corrupter SOURCES = corrupter.c LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a reiserfsprogs-3.6.9/tests/PROGS/Makefile.in0000644000077100007710000002721107705315226014226 # Makefile.in generated by automake 1.7.2 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__quote = @am__quote@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ sbin_PROGRAMS = reiserfs_corrupter SOURCES = corrupter.c LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a subdir = tests/PROGS mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = sbin_PROGRAMS = reiserfs_corrupter$(EXEEXT) PROGRAMS = $(sbin_PROGRAMS) reiserfs_corrupter_SOURCES = reiserfs_corrupter.c reiserfs_corrupter_OBJECTS = reiserfs_corrupter.$(OBJEXT) reiserfs_corrupter_LDADD = $(LDADD) reiserfs_corrupter_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \ $(top_srcdir)/reiserfscore/libcore.a reiserfs_corrupter_LDFLAGS = DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/reiserfs_corrupter.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = reiserfs_corrupter.c DIST_COMMON = Makefile.am Makefile.in SOURCES = corrupter.c all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu tests/PROGS/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(sbindir) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f || exit 1; \ else :; fi; \ done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ rm -f $(DESTDIR)$(sbindir)/$$f; \ done clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) reiserfs_corrupter$(EXEEXT): $(reiserfs_corrupter_OBJECTS) $(reiserfs_corrupter_DEPENDENCIES) @rm -f reiserfs_corrupter$(EXEEXT) $(LINK) $(reiserfs_corrupter_LDFLAGS) $(reiserfs_corrupter_OBJECTS) $(reiserfs_corrupter_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reiserfs_corrupter.Po@am__quote@ distclean-depend: -rm -rf ./$(DEPDIR) .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: $(mkinstalldirs) $(DESTDIR)$(sbindir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-sbinPROGRAMS install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-sbinPROGRAMS ctags distclean distclean-compile \ distclean-depend distclean-generic distclean-tags distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-sbinPROGRAMS install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-info-am uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: reiserfsprogs-3.6.9/tests/PROGS/reiserfs_corrupter.c0000664000077100007710000001200607705261642016254 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "io.h" #include "misc.h" #include "reiserfs_lib.h" enum { USED_BLOCKS, ALL_BLOCKS, EXTERN_BITMAP }; typedef struct corrupter_options { int bitmap_kind; char * bm_name; reiserfs_bitmap_t * bm; int block_size; int offset; } corrupter_options_t; #define print_usage_and_exit() {\ printf ("\nUsage: %s [options] device\n"\ "Options:\n"\ " -b bitmap\t\tscan blocks marked in bitmap\n"\ " -S\t\t\tscan-whole-partition\n"\ " -s blocksize\t\tfs blocksize\n"\ " -o bitmap\t\tskip offset blocks\n\n"\ , argv[0]);\ exit (16);\ } static char * parse_options (corrupter_options_t * options, int argc, char * argv []) { int c; options->bitmap_kind = USED_BLOCKS; options->block_size = 4096; options->offset = 0; options->bm_name = NULL; options->bm = NULL; while (1) { int option_index; c = getopt_long (argc, argv, "Sb:s:o:", NULL, &option_index); if (c == -1) break; switch (c) { case 0: /* long-only options */ break; case 'b': /* --scan-marked-in-bitmap */ options->bitmap_kind = EXTERN_BITMAP; options->bm_name = optarg; break; case 'S': /* --scan-whole-partition */ options->bitmap_kind = ALL_BLOCKS; break; case 'o': /* --scan-marked-in-bitmap */ options->offset = atoi (optarg); break; case 's': /* --scan-marked-in-bitmap */ options->block_size = atoi (optarg); break; default: print_usage_and_exit(); } } if (optind != argc - 1) print_usage_and_exit(); return argv[optind]; } void load_bitmap_from_file (corrupter_options_t * options) { FILE * fd; fd = fopen (options->bm_name, "r"); if (!fd) reiserfs_panic ("%s: could not load bitmap: %s\n", __FUNCTION__, strerror(errno)); options->bm = reiserfs_bitmap_load (fd); if (!options->bm) reiserfs_panic ("could not load fitmap from \"%s\"", options->bm_name); fclose (fd); } void warn_what_will_be_done (corrupter_options_t * options, char * file_name, int bl_count) { printf ("====================\n"); printf ("\tprogram will corrupt %s\n", file_name); printf ("\tblock size is %d\n", options->block_size); printf ("\toffset is %d blocks\n", options->offset); if (options->bitmap_kind == ALL_BLOCKS) { printf ("\tall formatted blocks, bitmap and journal blocks will be corrupted\n"); } else if (options->bitmap_kind == USED_BLOCKS) { printf ("\tall formatted blocks, bitmap and journal blocks which are used in fs bitmap will be corrupted\n"); } else if (options->bitmap_kind == EXTERN_BITMAP) { printf ("\tall formatted blocks, bitmap and journal blocks from bitmap %s will be corrupted\n", options->bm_name); } printf ("\tblocks count %d\n", bl_count); printf ("====================\n"); } int main (int argc, char * argv []) { corrupter_options_t options; char * file_name; unsigned int block_count, i; reiserfs_filsys_t * fs; file_name = parse_options (&options, argc, argv); fs = reiserfs_open (file_name, O_RDONLY, 0, &options, 1); if (no_reiserfs_found (fs)) die ("could not open filesystem on \"%s\"", file_name); /* keep SB to separate memory */ fs->fs_ondisk_sb = getmem(fs->fs_blocksize); memcpy (fs->fs_ondisk_sb, fs->fs_super_bh->b_data, fs->fs_blocksize); block_count = get_sb_block_count (fs->fs_ondisk_sb); if (options.bm_name) { load_bitmap_from_file (&options); } else { if (reiserfs_open_ondisk_bitmap (fs)) die ("could not open bitmap\n"); options.bm = reiserfs_create_bitmap (fs->fs_bitmap2->bm_bit_size); reiserfs_bitmap_copy (options.bm, fs->fs_bitmap2); } if (options.bm && block_count > options.bm->bm_bit_size) { printf ("fs is larger (%d blocks) then bitmap (%ld blocks), work with %ld blocks only\n", block_count, options.bm->bm_bit_size, options.bm->bm_bit_size); block_count = options.bm->bm_bit_size; } warn_what_will_be_done (&options, file_name, block_count); for (i = options.offset; i < block_count; i++) { int who; struct buffer_head * bh; /* read every block and corrupt all formatted blocks */ if (!reiserfs_bitmap_test_bit (options.bm, i)) continue; bh = bread (fs->fs_dev, i, fs->fs_blocksize); who = who_is_this (bh->b_data, bh->b_size); /* if (block of bitmap || block of journal || leaf || internal) take N random bytes and write them into N random place within the block */ if (who != THE_SUPER && who != THE_LEAF && who != THE_INTERNAL && who != THE_JDESC && !block_of_bitmap (fs, i) && !block_of_journal (fs, i)) continue; printf ("\ncorrupt %d ", i); } freemem(fs->fs_ondisk_sb); reiserfs_close (fs); printf ("\nDone\n"); return 0; } reiserfsprogs-3.6.9/tests/Makefile.am0000664000077100007710000000004307665645673013340 SUBDIRS = PROGS sbin_PROGRAMS = reiserfsprogs-3.6.9/tests/Makefile.in0000644000077100007710000003060607705315226013336 # Makefile.in generated by automake 1.7.2 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__quote = @am__quote@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ SUBDIRS = PROGS sbin_PROGRAMS = subdir = tests mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = sbin_PROGRAMS = PROGRAMS = $(sbin_PROGRAMS) DIST_SOURCES = RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ ps-recursive install-info-recursive uninstall-info-recursive \ all-recursive install-data-recursive install-exec-recursive \ installdirs-recursive install-recursive uninstall-recursive \ check-recursive installcheck-recursive DIST_COMMON = Makefile.am Makefile.in DIST_SUBDIRS = $(SUBDIRS) all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu tests/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(sbindir) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f || exit 1; \ else :; fi; \ done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ rm -f $(DESTDIR)$(sbindir)/$$f; \ done clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @set fnord $$MAKEFLAGS; amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $$MAKEFLAGS; amf=$$2; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" \ distdir=../$(distdir)/$$subdir \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(PROGRAMS) installdirs: installdirs-recursive installdirs-am: $(mkinstalldirs) $(DESTDIR)$(sbindir) install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-recursive distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: info: info-recursive info-am: install-data-am: install-exec-am: install-sbinPROGRAMS install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \ clean-generic clean-recursive clean-sbinPROGRAMS ctags \ ctags-recursive distclean distclean-generic distclean-recursive \ distclean-tags distdir dvi dvi-am dvi-recursive info info-am \ info-recursive install install-am install-data install-data-am \ install-data-recursive install-exec install-exec-am \ install-exec-recursive install-info install-info-am \ install-info-recursive install-man install-recursive \ install-sbinPROGRAMS install-strip installcheck installcheck-am \ installdirs installdirs-am installdirs-recursive \ maintainer-clean maintainer-clean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-generic \ mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \ ps-recursive tags tags-recursive uninstall uninstall-am \ uninstall-info-am uninstall-info-recursive uninstall-recursive \ uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: reiserfsprogs-3.6.9/README0000664000077100007710000000545107705261642011013 Reiserfs is a file system based on balanced tree algorithms, which is described at www.namesys.com. [LICENSING] ReiserFSprogs is hereby licensed under the GNU General Public License version 2 but with the following "Anti-Plagiarism" modification: You may not remove any credits or brand marks, or cause them to not display, unless you are an end user (that is, you are not redistributing to others). Yes, there really are people with the nerve to remove credits from software they did not write, or only wrote a small part of, and they are even frequently occurring sad to say. Credits are not ads, credits describe someone's contribution to the project (e.g. labor or money) whereas an ad says something else. Source code files that contain the phrase "licensing governed by reiserfsprogs/README" are "governed files" throughout that file. Governed files are licensed under this license. The portions of them owned by Hans Reiser, or authorized to be licensed by him, have been in the past, and likely will be in the future, licensed to other parties under other licenses. If you add your code to governed files, and don't want it to be owned by Hans Reiser, put your copyright label on that code so we can keep things straight. It will be a kindness if you identify whether Hans Reiser is allowed to license code labeled as owned by you on your behalf other than under this license, because he wants to know if it is okay to do so and put a check in the mail to you (for non-trivial improvements) when he makes his next sale. He makes no guarantees as to the amount if any, though he feels motivated to motivate contributors, and you can surely discuss this with him before or after contributing. You have the right to decline to allow him to license your code contribution other than under this license or the GPL. Further licensing options are available for commercial and/or other interests directly from reiser@namesys.com

[END LICENSING] Send bug reports to reiserfs-dev@namesys.com. Hideous Commercial Pitch: Spread your development costs across other OS vendors. Select from the best in the world, not the best in your building, by buying from third party OS component suppliers. Leverage the software component development power of the internet. Be the most aggressive in taking advantage of the commercial possibilities of decentralized internet development, and add value through your branded integration that you sell as an operating system. Let your competitors be the ones to compete against the entire internet by themselves. Be hip, get with the new economic trend, before your competitors do. Send email to reiser@namesys.com. To understand the code, after reading the website, start reading the code by reading reiserfs_fs.h first. reiserfsprogs-3.6.9/configure0000755000077100007710000050640207705315224012036 #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.57. # # Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi # Support unset when possible. if (FOO=FOO; unset FOO) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" # Sed expression to map a string onto a valid variable name. as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="version.h" # Factoring default headers for most tests. ac_includes_default="\ #include #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if STDC_HEADERS # include # include #else # if HAVE_STDLIB_H # include # endif #endif #if HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include # endif # include #endif #if HAVE_STRINGS_H # include #endif #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #if HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM AWK SET_MAKE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE RANLIB ac_ct_RANLIB CPP EGREP LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/-/_/g'` eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias ac_env_CC_set=${CC+set} ac_env_CC_value=$CC ac_cv_env_CC_set=${CC+set} ac_cv_env_CC_value=$CC ac_env_CFLAGS_set=${CFLAGS+set} ac_env_CFLAGS_value=$CFLAGS ac_cv_env_CFLAGS_set=${CFLAGS+set} ac_cv_env_CFLAGS_value=$CFLAGS ac_env_LDFLAGS_set=${LDFLAGS+set} ac_env_LDFLAGS_value=$LDFLAGS ac_cv_env_LDFLAGS_set=${LDFLAGS+set} ac_cv_env_LDFLAGS_value=$LDFLAGS ac_env_CPPFLAGS_set=${CPPFLAGS+set} ac_env_CPPFLAGS_value=$CPPFLAGS ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} ac_cv_env_CPPFLAGS_value=$CPPFLAGS ac_env_CPP_set=${CPP+set} ac_env_CPP_value=$CPP ac_cv_env_CPP_set=${CPP+set} ac_cv_env_CPP_value=$CPP # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-dependency-tracking Speeds up one-time builds --enable-dependency-tracking Do not reject slow dependency extractors --enable-io-failure-emulation Never use that. It is for debugging only Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be # absolute. ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd $ac_popdir done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.57. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core core.* *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo >confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . $cache_file;; *) . ./$cache_file;; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version="1.7" ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f $ac_dir/shtool; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} { (exit 1); exit 1; }; } fi ac_config_guess="$SHELL $ac_aux_dir/config.guess" ac_config_sub="$SHELL $ac_aux_dir/config.sub" ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL=$ac_install_sh fi fi echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo "$as_me:$LINENO: checking whether build environment is sane" >&5 echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&5 echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&2;} { (exit 1); exit 1; }; } fi test "$2" = conftest.file ) then # Ok. : else { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! Check your system clock" >&5 echo "$as_me: error: newly created file is older than distributed files! Check your system clock" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 test "$program_prefix" != NONE && program_transform_name="s,^,$program_prefix,;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s,\$,$program_suffix,;$program_transform_name" # Double any \ or $. echo might interpret backslashes. # By default was `s,x,x', remove it if useless. cat <<\_ACEOF >conftest.sed s/[\\$]/&&/g;s/;s,x,x,$// _ACEOF program_transform_name=`echo $program_transform_name | sed -f conftest.sed` rm conftest.sed # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_AWK+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then echo "$as_me:$LINENO: result: $AWK" >&5 echo "${ECHO_T}$AWK" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$AWK" && break done echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF all: @echo 'ac_maketemp="$(MAKE)"' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftest.make fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 SET_MAKE= else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 SET_MAKE="MAKE=${MAKE-make}" fi # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} { (exit 1); exit 1; }; } fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE=reiserfsprogs VERSION=3.6.9 cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} AMTAR=${AMTAR-"${am_missing_run}tar"} install_sh=${install_sh-"$am_aux_dir/install-sh"} # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then echo "$as_me:$LINENO: result: $STRIP" >&5 echo "${ECHO_T}$STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 echo "${ECHO_T}$ac_ct_STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi STRIP=$ac_ct_STRIP else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" # We need awk for the "check" target. The system "awk" is bad on # some platforms. ac_config_headers="$ac_config_headers include/config.h" PRESET_CFLAGS=$CFLAGS ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CC" && break done CC=$ac_ct_CC fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. echo "$as_me:$LINENO: checking for C compiler default output" >&5 echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Find the output, starting from the most likely. This scheme is # not robust to junk in `.', hence go to wildcards (a.*) only as a last # resort. # Be careful to initialize this variable, since it used to be cached. # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. ac_cv_exeext= # b.out is created by i960 compilers. for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; conftest.$ac_ext ) # This is the source file. ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` # FIXME: I believe we export ac_cv_exeext for Libtool, # but it would be cool to find out if it's true. Does anybody # maintain Libtool? --akim. export ac_cv_exeext break;; * ) break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6 # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6 echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` export ac_cv_exeext break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6 rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6 OBJEXT=$ac_cv_objext ac_objext=$OBJEXT echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS CFLAGS="-g" echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 if test "${ac_cv_prog_cc_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_stdc=$ac_arg break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC fi case "x$ac_cv_prog_cc_stdc" in x|xno) echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6 ;; *) echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 CC="$CC $ac_cv_prog_cc_stdc" ;; esac # Some people use a C++ compiler to compile C. Since we use `exit', # in C++ we need to declare it. In case someone uses the same compiler # for both compiling C and C++ we need to have the C++ compiler decide # the declaration of exit, since it's the most demanding environment. cat >conftest.$ac_ext <<_ACEOF #ifndef __cplusplus choke me #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ ''\ '#include ' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu rm -f .deps 2>/dev/null mkdir .deps 2>/dev/null if test -d .deps; then DEPDIR=.deps else # MS-DOS does not allow filenames that begin with a dot. DEPDIR=_deps fi rmdir .deps 2>/dev/null ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' doit: @echo done END # If we don't find an include directive, just comment out the code. echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi echo "$as_me:$LINENO: result: $_am_result" >&5 echo "${ECHO_T}$_am_result" >&6 rm -f confinc confmf # Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then enableval="$enable_dependency_tracking" fi; if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. echo '#include "conftest.h"' > conftest.c echo 'int i;' > conftest.h echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=conftest.c object=conftest.o \ depfile=conftest.Po tmpdepfile=conftest.TPo \ $SHELL ./depcomp $depcc -c -o conftest.o conftest.c >/dev/null 2>&1 && grep conftest.h conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then am_cv_CC_dependencies_compiler_type=$depmode break fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi if test "x" = "x$PRESET_CFLAGS"; then CFLAGS="${RPM_OPT_FLAGS} $CFLAGS -Wall" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 echo "${ECHO_T}$ac_ct_RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi RANLIB=$ac_ct_RANLIB else RANLIB="$ac_cv_prog_RANLIB" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6 ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6 if test "${ac_cv_prog_egrep+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | (grep -E '(a|b)') >/dev/null 2>&1 then ac_cv_prog_egrep='grep -E' else ac_cv_prog_egrep='egrep' fi fi echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 echo "${ECHO_T}$ac_cv_prog_egrep" >&6 EGREP=$ac_cv_prog_egrep echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6 if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in fcntl.h limits.h malloc.h sys/ioctl.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc in yes:no ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; no:yes ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to bug-autoconf@gnu.org. ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 if test "${ac_cv_c_const+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { /* FIXME: Include the comments suggested by Paul. */ #ifndef __cplusplus /* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset x; /* SunOS 4.1.1 cc rejects this. */ char const *const *ccp; char **p; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; ccp = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++ccp; p = (char**) ccp; ccp = (char const *const *) p; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; } #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_const=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_const=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 echo "${ECHO_T}$ac_cv_c_const" >&6 if test $ac_cv_c_const = no; then cat >>confdefs.h <<\_ACEOF #define const _ACEOF fi echo "$as_me:$LINENO: checking for inline" >&5 echo $ECHO_N "checking for inline... $ECHO_C" >&6 if test "${ac_cv_c_inline+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_inline=$ac_kw; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.$ac_objext conftest.$ac_ext done fi echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 echo "${ECHO_T}$ac_cv_c_inline" >&6 case $ac_cv_c_inline in inline | yes) ;; no) cat >>confdefs.h <<\_ACEOF #define inline _ACEOF ;; *) cat >>confdefs.h <<_ACEOF #define inline $ac_cv_c_inline _ACEOF ;; esac echo "$as_me:$LINENO: checking for size_t" >&5 echo $ECHO_N "checking for size_t... $ECHO_C" >&6 if test "${ac_cv_type_size_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((size_t *) 0) return 0; if (sizeof (size_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_size_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_size_t=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 echo "${ECHO_T}$ac_cv_type_size_t" >&6 if test $ac_cv_type_size_t = yes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned _ACEOF fi echo "$as_me:$LINENO: checking for struct stat.st_rdev" >&5 echo $ECHO_N "checking for struct stat.st_rdev... $ECHO_C" >&6 if test "${ac_cv_member_struct_stat_st_rdev+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static struct stat ac_aggr; if (ac_aggr.st_rdev) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_member_struct_stat_st_rdev=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static struct stat ac_aggr; if (sizeof ac_aggr.st_rdev) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_member_struct_stat_st_rdev=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_member_struct_stat_st_rdev=no fi rm -f conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_rdev" >&5 echo "${ECHO_T}$ac_cv_member_struct_stat_st_rdev" >&6 if test $ac_cv_member_struct_stat_st_rdev = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_STAT_ST_RDEV 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define HAVE_ST_RDEV 1 _ACEOF fi if test $ac_cv_c_compiler_gnu = yes; then echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5 echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6 if test "${ac_cv_prog_gcc_traditional+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_pattern="Autoconf.*'x'" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include Autoconf TIOCGETP _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "$ac_pattern" >/dev/null 2>&1; then ac_cv_prog_gcc_traditional=yes else ac_cv_prog_gcc_traditional=no fi rm -f conftest* if test $ac_cv_prog_gcc_traditional = no; then cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include Autoconf TCGETA _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "$ac_pattern" >/dev/null 2>&1; then ac_cv_prog_gcc_traditional=yes fi rm -f conftest* fi fi echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5 echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6 if test $ac_cv_prog_gcc_traditional = yes; then CC="$CC -traditional" fi fi echo "$as_me:$LINENO: checking for working memcmp" >&5 echo $ECHO_N "checking for working memcmp... $ECHO_C" >&6 if test "${ac_cv_func_memcmp_working+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_memcmp_working=no else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { /* Some versions of memcmp are not 8-bit clean. */ char c0 = 0x40, c1 = 0x80, c2 = 0x81; if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) exit (1); /* The Next x86 OpenStep bug shows up only when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary. William Lewis provided this test program. */ { char foo[21]; char bar[21]; int i; for (i = 0; i < 4; i++) { char *a = foo + i; char *b = bar + i; strcpy (a, "--------01111111"); strcpy (b, "--------10000000"); if (memcmp (a, b, 16) >= 0) exit (1); } exit (0); } ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_memcmp_working=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_memcmp_working=no fi rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $ac_cv_func_memcmp_working" >&5 echo "${ECHO_T}$ac_cv_func_memcmp_working" >&6 test $ac_cv_func_memcmp_working = no && LIBOBJS="$LIBOBJS memcmp.$ac_objext" for ac_func in strftime do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else # strftime is in -lintl on SCO UNIX. echo "$as_me:$LINENO: checking for strftime in -lintl" >&5 echo $ECHO_N "checking for strftime in -lintl... $ECHO_C" >&6 if test "${ac_cv_lib_intl_strftime+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char strftime (); int main () { strftime (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_intl_strftime=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_intl_strftime=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_intl_strftime" >&5 echo "${ECHO_T}$ac_cv_lib_intl_strftime" >&6 if test $ac_cv_lib_intl_strftime = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_STRFTIME 1 _ACEOF LIBS="-lintl $LIBS" fi fi done for ac_func in vprintf do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF echo "$as_me:$LINENO: checking for _doprnt" >&5 echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6 if test "${ac_cv_func__doprnt+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* System header to define __stub macros and hopefully few prototypes, which can conflict with char _doprnt (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char _doprnt (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub__doprnt) || defined (__stub____doprnt) choke me #else char (*f) () = _doprnt; #endif #ifdef __cplusplus } #endif int main () { return f != _doprnt; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func__doprnt=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func__doprnt=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5 echo "${ECHO_T}$ac_cv_func__doprnt" >&6 if test $ac_cv_func__doprnt = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_DOPRNT 1 _ACEOF fi fi done for ac_func in strerror strstr strtol do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # Check whether --enable-io-failure-emulation or --disable-io-failure-emulation was given. if test "${enable_io_failure_emulation+set}" = set; then enableval="$enable_io_failure_emulation" if test "$enableval" = "yes" ; then echo -e "\nCarefull! IO failure emulation is ON\n" cat >>confdefs.h <<\_ACEOF #define IO_FAILURE_EMULATION 1 _ACEOF fi fi; echo "$as_me:$LINENO: checking for CREDITS" >&5 echo $ECHO_N "checking for CREDITS... $ECHO_C" >&6 if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _GNU_SOURSE #include #include #include int main (void) { FILE *fin, *fout; char *line = NULL; unsigned int len = 0; int start, count; if ((fin = fopen("CREDITS", "r")) == NULL) { fprintf(stderr, "Error occured while openning the file 'CREDITS': " "%s.\n", strerror(errno)); return 1; } if ((fout = fopen("include/credits.h", "w")) == NULL) { fprintf(stderr, "Error occured while openning the file 'credits.h': " "%s.\n", strerror(errno)); return 1; } /* Replicate the header. */ while (getline(&line, &len, fin) != -1) { fprintf(fout, line); if (!strcmp(line, "\n")) break; } fprintf(fout, "char *credits[] = {\n"); start = 2; count = 0; while (getline(&line, &len, fin) != -1) { if (!strcmp(line, "\n") || strlen(line) < 1) { start = 1; count++; } else { if (!start) fprintf(fout, "\t\\\" "\n"); else if (start == 1) fprintf(fout, ",\n\n"); line[strlen(line) - 1] = 0; fprintf(fout, "\t\"%s\\\n\"", line); start = 0; } } fprintf(fout, "\n};\n"); fprintf(fout, "#define CREDITS_COUNT %d\n", count); free(line); fclose(fin); fclose(fout); return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 ; exit fi rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi ac_config_files="$ac_config_files include/Makefile mkreiserfs/Makefile resize_reiserfs/Makefile fsck/Makefile lib/Makefile Makefile reiserfscore/Makefile debugreiserfs/Makefile tune/Makefile tests/Makefile tests/PROGS/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi # Support unset when possible. if (FOO=FOO; unset FOO) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" # Sed expression to map a string onto a valid variable name. as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by $as_me, which was generated by GNU Autoconf 2.57. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.57, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir INSTALL="$INSTALL" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # INIT-COMMANDS section. # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; "mkreiserfs/Makefile" ) CONFIG_FILES="$CONFIG_FILES mkreiserfs/Makefile" ;; "resize_reiserfs/Makefile" ) CONFIG_FILES="$CONFIG_FILES resize_reiserfs/Makefile" ;; "fsck/Makefile" ) CONFIG_FILES="$CONFIG_FILES fsck/Makefile" ;; "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "reiserfscore/Makefile" ) CONFIG_FILES="$CONFIG_FILES reiserfscore/Makefile" ;; "debugreiserfs/Makefile" ) CONFIG_FILES="$CONFIG_FILES debugreiserfs/Makefile" ;; "tune/Makefile" ) CONFIG_FILES="$CONFIG_FILES tune/Makefile" ;; "tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; "tests/PROGS/Makefile" ) CONFIG_FILES="$CONFIG_FILES tests/PROGS/Makefile" ;; "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "include/config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS include/config.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t s,@CYGPATH_W@,$CYGPATH_W,;t t s,@PACKAGE@,$PACKAGE,;t t s,@VERSION@,$VERSION,;t t s,@ACLOCAL@,$ACLOCAL,;t t s,@AUTOCONF@,$AUTOCONF,;t t s,@AUTOMAKE@,$AUTOMAKE,;t t s,@AUTOHEADER@,$AUTOHEADER,;t t s,@MAKEINFO@,$MAKEINFO,;t t s,@AMTAR@,$AMTAR,;t t s,@install_sh@,$install_sh,;t t s,@STRIP@,$STRIP,;t t s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t s,@AWK@,$AWK,;t t s,@SET_MAKE@,$SET_MAKE,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t s,@ac_ct_CC@,$ac_ct_CC,;t t s,@EXEEXT@,$EXEEXT,;t t s,@OBJEXT@,$OBJEXT,;t t s,@DEPDIR@,$DEPDIR,;t t s,@am__include@,$am__include,;t t s,@am__quote@,$am__quote,;t t s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t s,@CCDEPMODE@,$CCDEPMODE,;t t s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t s,@RANLIB@,$RANLIB,;t t s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@CPP@,$CPP,;t t s,@EGREP@,$EGREP,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # Line after last line for current file. ac_more_lines=: ac_sed_cmds= while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be # absolute. ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo $f;; *) # Relative if test -f "$f"; then # Build tree echo $f elif test -f "$srcdir/$f"; then # Source tree echo $srcdir/$f else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t s,@INSTALL@,$ac_INSTALL,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_HEADER section. # # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='[ ].*$,\1#\2' ac_dC=' ' ac_dD=',;t' # ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='$,\1#\2define\3' ac_uC=' ' ac_uD=',;t' for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo $f;; *) # Relative if test -f "$f"; then # Build tree echo $f elif test -f "$srcdir/$f"; then # Source tree echo $srcdir/$f else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } # Remove the trailing spaces. sed 's/[ ]*$//' $ac_file_inputs >$tmp/in _ACEOF # Transform confdefs.h into two sed scripts, `conftest.defines' and # `conftest.undefs', that substitutes the proper values into # config.h.in to produce config.h. The first handles `#define' # templates, and the second `#undef' templates. # And first: Protect against being on the right side of a sed subst in # config.status. Protect against being in an unquoted here document # in config.status. rm -f conftest.defines conftest.undefs # Using a here document instead of a string reduces the quoting nightmare. # Putting comments in sed scripts is not portable. # # `end' is used to avoid that the second main sed command (meant for # 0-ary CPP macros) applies to n-ary macro definitions. # See the Autoconf documentation for `clear'. cat >confdef2sed.sed <<\_ACEOF s/[\\&,]/\\&/g s,[\\$`],\\&,g t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp t end s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp : end _ACEOF # If some macros were called several times there might be several times # the same #defines, which is useless. Nevertheless, we may not want to # sort them, since we want the *last* AC-DEFINE to be honored. uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs rm -f confdef2sed.sed # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >>conftest.undefs <<\_ACEOF s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, _ACEOF # Break up conftest.defines because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS echo ' :' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.defines >/dev/null do # Write a limited-size here document to $tmp/defines.sed. echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#define' lines. echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/defines.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail rm -f conftest.defines mv conftest.tail conftest.defines done rm -f conftest.defines echo ' fi # grep' >>$CONFIG_STATUS echo >>$CONFIG_STATUS # Break up conftest.undefs because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #undef templates' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.undefs >/dev/null do # Write a limited-size here document to $tmp/undefs.sed. echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#undef' echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/undefs.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail rm -f conftest.undefs mv conftest.tail conftest.undefs done rm -f conftest.undefs cat >>$CONFIG_STATUS <<\_ACEOF # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then echo "/* Generated by configure. */" >$tmp/config.h else echo "/* $ac_file. Generated by configure. */" >$tmp/config.h fi cat $tmp/in >>$tmp/config.h rm -f $tmp/in if test x"$ac_file" != x-; then if diff $ac_file $tmp/config.h >/dev/null 2>&1; then { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 echo "$as_me: $ac_file is unchanged" >&6;} else ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } rm -f $ac_file mv $tmp/config.h $ac_file fi else cat $tmp/config.h rm -f $tmp/config.h fi _am_stamp_count=`expr ${_am_stamp_count-0} + 1` echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null || $as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X$ac_file : 'X\(//\)[^/]' \| \ X$ac_file : 'X\(//\)$' \| \ X$ac_file : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X$ac_file | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'`/stamp-h$_am_stamp_count done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_COMMANDS section. # for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue ac_dest=`echo "$ac_file" | sed 's,:.*,,'` ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_dir=`(dirname "$ac_dest") 2>/dev/null || $as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_dest" : 'X\(//\)[^/]' \| \ X"$ac_dest" : 'X\(//\)$' \| \ X"$ac_dest" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_dest" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be # absolute. ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 echo "$as_me: executing $ac_dest commands" >&6;} case $ac_dest in depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`(dirname "$mf") 2>/dev/null || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` else continue fi grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue # Extract the definition of DEP_FILES from the Makefile without # running `make'. DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` test -z "$DEPDIR" && continue # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n -e '/^U = / s///p' < "$mf"` test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" # We invoke sed twice because it is the simplest approach to # changing $(DEPDIR) to its actual value in the expansion. for file in `sed -n -e ' /^DEP_FILES = .*\\\\$/ { s/^DEP_FILES = // :loop s/\\\\$// p n /\\\\$/ b loop p } /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`(dirname "$file") 2>/dev/null || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p $dirpart/$fdir else as_dir=$dirpart/$fdir as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} { (exit 1); exit 1; }; }; } # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ;; esac done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi reiserfsprogs-3.6.9/configure.in0000664000077100007710000000560107705261642012441 dnl Process this file with autoconf to produce a configure script. AC_INIT(version.h) AM_INIT_AUTOMAKE(reiserfsprogs, 3.6.9) dnl We install in /sbin, the utils are to be available on boot dnl AC_PREFIX(/) AM_CONFIG_HEADER(include/config.h) AC_SUBST(sbindir) PRESET_CFLAGS=$CFLAGS AC_PROG_CC if test "x" = "x$PRESET_CFLAGS"; then CFLAGS="${RPM_OPT_FLAGS} $CFLAGS -Wall" fi dnl Checks for programs. AC_PROG_RANLIB dnl AC_PROG_AWK dnl AC_PROG_INSTALL dnl AC_PROG_LN_S dnl Checks for libraries. dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(fcntl.h limits.h malloc.h sys/ioctl.h unistd.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T AC_STRUCT_ST_RDEV dnl Checks for library functions. AC_PROG_GCC_TRADITIONAL AC_FUNC_MEMCMP AC_FUNC_STRFTIME AC_FUNC_VPRINTF AC_CHECK_FUNCS(strerror strstr strtol) dnl Never enable this. It is for debugging only AC_ARG_ENABLE(io-failure-emulation, [ --enable-io-failure-emulation Never use that. It is for debugging only], [ if test "$enableval" = "yes" ; then echo -e "\nCarefull! IO failure emulation is ON\n" AC_DEFINE(IO_FAILURE_EMULATION, 1, [gets set when configure --enable-io-failure-emulation]) fi ]) AC_DEFUN(AC_PREPARE_CREDITS, [ AC_MSG_CHECKING(for CREDITS) AC_TRY_RUN([ #define _GNU_SOURSE #include #include #include int main (void) { FILE *fin, *fout; char *line = NULL; unsigned int len = 0; int start, count; if ((fin = fopen("CREDITS", "r")) == NULL) { fprintf(stderr, "Error occured while openning the file 'CREDITS': " "%s.\n", strerror(errno)); return 1; } if ((fout = fopen("include/credits.h", "w")) == NULL) { fprintf(stderr, "Error occured while openning the file 'credits.h': " "%s.\n", strerror(errno)); return 1; } /* Replicate the header. */ while (getline(&line, &len, fin) != -1) { fprintf(fout, line); if (!strcmp(line, "\n")) break; } fprintf(fout, "char *credits[] = {\n"); start = 2; count = 0; while (getline(&line, &len, fin) != -1) { if (!strcmp(line, "\n") || strlen(line) < 1) { start = 1; count++; } else { if (!start) fprintf(fout, "\t\\\" "\n"); else if (start == 1) fprintf(fout, ",\n\n"); line[strlen(line) - 1] = 0; fprintf(fout, "\t\"%s\\\n\"", line); start = 0; } } fprintf(fout, "\n};\n"); fprintf(fout, "#define CREDITS_COUNT %d\n", count); free(line); fclose(fin); fclose(fout); return 0; } ], AC_MSG_RESULT(yes), AC_MSG_RESULT(no) ; exit) ]) AC_PREPARE_CREDITS() AC_OUTPUT( include/Makefile mkreiserfs/Makefile resize_reiserfs/Makefile fsck/Makefile lib/Makefile Makefile reiserfscore/Makefile debugreiserfs/Makefile tune/Makefile tests/Makefile tests/PROGS/Makefile) reiserfsprogs-3.6.9/reiserfscore/0000777000077100007710000000000007705315452012702 5reiserfsprogs-3.6.9/reiserfscore/bitmap.c0000664000077100007710000004171007705261642014244 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ /* * 2000/10/26 - Initial version. */ #include "includes.h" #include /* create clean bitmap */ reiserfs_bitmap_t * reiserfs_create_bitmap (unsigned int bit_count) { reiserfs_bitmap_t * bm; bm = getmem (sizeof (*bm)); if (!bm) return 0; bm->bm_bit_size = bit_count; bm->bm_byte_size = ((unsigned long long)bit_count + 7) / 8; bm->bm_set_bits = 0; bm->bm_map = getmem (bm->bm_byte_size); if (!bm->bm_map) { freemem (bm); return 0; } return bm; } /* Expand existing bitmap. Return non-zero if can't. FIXME: it is assumed that bit_count is new number of blocks to be addressed */ int reiserfs_expand_bitmap (reiserfs_bitmap_t * bm, unsigned int bit_count) { unsigned int byte_count = ((bit_count + 7) / 8); char * new_map; new_map = expandmem (bm->bm_map, bm->bm_byte_size, byte_count - bm->bm_byte_size); if (!new_map) { return 1; } bm->bm_map = new_map; bm->bm_byte_size = byte_count; bm->bm_bit_size = bit_count; bm->bm_dirty = 1; return 0; } void reiserfs_shrink_bitmap (reiserfs_bitmap_t * bm, unsigned int bit_count) { assert (bm->bm_bit_size >= bit_count); bm->bm_byte_size = (bit_count + 7) / 8; bm->bm_bit_size = bit_count; bm->bm_dirty = 1; } /* bitmap destructor */ void reiserfs_delete_bitmap (reiserfs_bitmap_t * bm) { freemem(bm->bm_map); bm->bm_map = NULL; /* to not reuse bitmap handle */ bm->bm_bit_size = 0; bm->bm_byte_size = 0; freemem(bm); } void reiserfs_bitmap_copy (reiserfs_bitmap_t * to, reiserfs_bitmap_t * from) { assert (to->bm_byte_size == from->bm_byte_size); memcpy (to->bm_map, from->bm_map, from->bm_byte_size); to->bm_bit_size = from->bm_bit_size; to->bm_set_bits = from->bm_set_bits; to->bm_dirty = 1; } int reiserfs_bitmap_compare (reiserfs_bitmap_t * bm1, reiserfs_bitmap_t * bm2) { unsigned long i, diff; unsigned long int bytes, bits; assert (bm1->bm_byte_size == bm2->bm_byte_size && bm1->bm_bit_size == bm2->bm_bit_size); diff = 0; /* compare full bytes */ bytes = bm1->bm_bit_size / 8; bits = bytes * 8; if (memcmp (bm1->bm_map, bm2->bm_map, bytes)) { for (i = 0; i < bits; i ++) if (reiserfs_bitmap_test_bit(bm1, i) != reiserfs_bitmap_test_bit(bm2, i)) diff ++; } /* compare last byte of bitmap which can be used partially */ bits = bm1->bm_bit_size % 8; for (i = bm1->bm_bit_size / 8 * 8; i < bm1->bm_bit_size / 8 * 8 + bits; i ++) if (reiserfs_bitmap_test_bit(bm1, i) != reiserfs_bitmap_test_bit(bm2, i)) diff ++; /* int mask; mask = 255 >> (8 - bits); if ((bm1->bm_map [bytes] & mask) != (bm2->bm_map [bytes] & mask)) { diff ++; } }*/ return diff; } /* Does X | Y for every bit of the bitmap `to`, where X - bit of the `to` bitmap, Y - `from` bitmap. Save result in the `to` bitmap. */ void reiserfs_bitmap_disjunction (reiserfs_bitmap_t * to, reiserfs_bitmap_t * from) { unsigned int i; assert (to->bm_byte_size == from->bm_byte_size && to->bm_bit_size == from->bm_bit_size); for (i = 0; i < to->bm_bit_size; i++) { if (misc_test_bit(i, from->bm_map) && !misc_test_bit(i, to->bm_map)) { misc_set_bit(i, to->bm_map); to->bm_set_bits ++; to->bm_dirty = 1; } } } /* Does X & !Y for every bit of the bitmap `base`, where X - bit of the `base` bitmap, Y - `exclude` bitmap. Save result in the `base` bitmap. */ void reiserfs_bitmap_delta (reiserfs_bitmap_t * base, reiserfs_bitmap_t * exclude) { unsigned int i; assert (base->bm_byte_size == exclude->bm_byte_size && base->bm_bit_size == exclude->bm_bit_size); for (i = 0; i < base->bm_bit_size; i++) { if (misc_test_bit(i, exclude->bm_map) && misc_test_bit(i, base->bm_map)) { misc_clear_bit(i, base->bm_map); base->bm_set_bits --; base->bm_dirty = 1; } } } void reiserfs_bitmap_set_bit (reiserfs_bitmap_t * bm, unsigned int bit_number) { assert(bit_number < bm->bm_bit_size); if (misc_test_bit (bit_number, bm->bm_map)) return; misc_set_bit(bit_number, bm->bm_map); bm->bm_set_bits ++; bm->bm_dirty = 1; } void reiserfs_bitmap_clear_bit (reiserfs_bitmap_t * bm, unsigned int bit_number) { assert(bit_number < bm->bm_bit_size); if (!misc_test_bit (bit_number, bm->bm_map)) return; misc_clear_bit (bit_number, bm->bm_map); bm->bm_set_bits --; bm->bm_dirty = 1; } int reiserfs_bitmap_test_bit (reiserfs_bitmap_t * bm, unsigned int bit_number) { if (bit_number >= bm->bm_bit_size) printf ("bit %u, bitsize %lu\n", bit_number, bm->bm_bit_size); assert(bit_number < bm->bm_bit_size); return misc_test_bit(bit_number, bm->bm_map); } unsigned int reiserfs_bitmap_zeros (reiserfs_bitmap_t * bm) { return bm->bm_bit_size - bm->bm_set_bits; } unsigned int reiserfs_bitmap_ones (reiserfs_bitmap_t * bm) { return bm->bm_set_bits; } int reiserfs_bitmap_find_zero_bit (reiserfs_bitmap_t * bm, unsigned long * first) { unsigned long bit_nr = *first; assert(*first < bm->bm_bit_size); bit_nr = misc_find_next_zero_bit(bm->bm_map, bm->bm_bit_size, *first); if (bit_nr >= bm->bm_bit_size) { /* search failed */ return 1; } *first = bit_nr; return 0; } /* read every bitmap block and copy their content into bitmap 'bm' */ static int reiserfs_fetch_ondisk_bitmap (reiserfs_bitmap_t * bm, reiserfs_filsys_t * fs) { unsigned int last_byte_unused_bits; unsigned long block, to_copy; struct buffer_head * bh; unsigned int i; int copied; int ret = 0; char * p; to_copy = (get_sb_block_count (fs->fs_ondisk_sb) + 7) / 8; /*reiserfs_warning (stderr, "Fetching on-disk bitmap..");*/ assert (bm->bm_byte_size == to_copy); copied = fs->fs_blocksize; p = bm->bm_map; block = fs->fs_super_bh->b_blocknr + 1; while (to_copy) { bh = bread (fs->fs_dev, block, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "reiserfs_fetch_ondisk_bitmap: " "bread failed reading bitmap (%lu)\n", block); bh = getblk (fs->fs_dev, block, fs->fs_blocksize); if (!bh) reiserfs_panic ("reiserfs_fetch_ondisk_bitmap: getblk failed"); memset (bh->b_data, 0xff, bh->b_size); mark_buffer_uptodate (bh, 1); } if (to_copy < fs->fs_blocksize) { for (i = to_copy; i < fs->fs_blocksize; i++) { if (bh->b_data[i] != (char)0xff) { ret = 1; break; } } copied = to_copy; } memcpy (p, bh->b_data, copied); brelse (bh); p += copied; to_copy -= copied; /* next bitmap block */ if (spread_bitmaps (fs)) block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8); else block ++; } /* on disk bitmap has bits out of SB_BLOCK_COUNT set to 1, where as reiserfs_bitmap_t has those bits set to 0 */ last_byte_unused_bits = bm->bm_byte_size * 8 - bm->bm_bit_size; for (i = 0; i < last_byte_unused_bits; i ++) { if (misc_test_bit (bm->bm_bit_size + i, bm->bm_map) == 0) ret = 1; else misc_clear_bit (bm->bm_bit_size + i, bm->bm_map); } bm->bm_set_bits = 0; /* FIXME: optimize that */ for (i = 0; i < bm->bm_bit_size; i ++) if (reiserfs_bitmap_test_bit (bm, i)) bm->bm_set_bits ++; bm->bm_dirty = 0; return ret; } /* copy bitmap 'bm' to buffers which hold on-disk bitmap if bitmap was ever changed and return 1. Otherwise - return 0 */ int reiserfs_flush_to_ondisk_bitmap (reiserfs_bitmap_t * bm, reiserfs_filsys_t * fs) { unsigned int last_byte_unused_bits, i; unsigned long to_copy, copied, block; struct buffer_head * bh; char * p; /* make sure that the device is big enough */ bh = bread (fs->fs_dev, bm->bm_bit_size - 1, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "reiserfs_flush_to_ondisk_bitmap: bread failed for block %lu\n", bm->bm_bit_size - 1); /* bh = getblk (fs->fs_dev, bm->bm_bit_size - 1, fs->fs_blocksize); if (!bh) reiserfs_panic ("reiserfs_flush_to_ondisk_bitmap: getblk failed"); mark_buffer_uptodate (bh, 1); mark_buffer_dirty (bh); bwrite (bh);*/ } brelse (bh); if (!bm->bm_dirty) return 0; to_copy = bm->bm_byte_size; copied = fs->fs_blocksize; p = bm->bm_map; block = fs->fs_super_bh->b_blocknr + 1; while (to_copy) { /* we bread to make sure that filesystem contains enough blocks */ bh = getblk (fs->fs_dev, block, fs->fs_blocksize); if (!bh) reiserfs_panic ("reiserfs_flush_to_ondisk_bitmap: " "getblk failed for (%lu)\n", block); memset (bh->b_data, 0xff, bh->b_size); mark_buffer_uptodate (bh, 1); if (to_copy < fs->fs_blocksize) copied = to_copy; memcpy (bh->b_data, p, copied); if (copied == to_copy) { /* set unused bits of last byte of a bitmap to 1 */ last_byte_unused_bits = bm->bm_byte_size * 8 - bm->bm_bit_size; for (i = 0; i < last_byte_unused_bits; i ++) misc_set_bit ((bm->bm_bit_size % (fs->fs_blocksize * 8)) + i, bh->b_data); } mark_buffer_dirty (bh); brelse (bh); p += copied; to_copy -= copied; /* next bitmap block */ if (spread_bitmaps (fs)) block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8); else block ++; } return 1; } void reiserfs_bitmap_zero (reiserfs_bitmap_t * bm) { memset (bm->bm_map, 0, bm->bm_byte_size); bm->bm_set_bits = 0; bm->bm_dirty = 1; } void reiserfs_bitmap_fill (reiserfs_bitmap_t * bm) { memset (bm->bm_map, 0xff, bm->bm_byte_size); bm->bm_set_bits = bm->bm_bit_size; bm->bm_dirty = 1; } /* format of bitmap saved in a file: magic number (32 bits) bm_bit_size (32 bits) number of ranges of used and free blocks (32 bits) number of contiguously used block, .. of free blocks, used, free, etc magic number (32 bits) */ #define BITMAP_START_MAGIC 374031 #define BITMAP_END_MAGIC 7786472 FILE * open_file (char * filename, char * option) { FILE * fp = fopen (filename, option); if (!fp) { reiserfs_warning (stderr, "open_file: could not open file %s\n", filename); return 0; } reiserfs_warning (stderr, "Temp file opened by fsck: \"%s\" .. \n", filename); return fp; } void close_file (FILE * fp) { fclose (fp); /*reiserfs_warning (stderr, "done\n"); fflush (stderr);*/ } void reiserfs_bitmap_save (FILE * fp, reiserfs_bitmap_t * bm) { // FILE * fp; __u32 v; int zeros; int count; unsigned int i; int extents; long position; /* fp = fopen (filename, "w+"); if (!fp) { reiserfs_warning (stderr, "reiserfs_bitmap_save: could not save bitmap in %s: %s", filename, strerror(errno)); return; }*/ // reiserfs_warning (stderr, "Saving bitmap in \"%s\" .. ", filename); fflush (stderr); v = BITMAP_START_MAGIC; fwrite (&v, 4, 1, fp); v = bm->bm_bit_size; fwrite (&v, 4, 1, fp); /*printf ("SAVE: bit_size - %d\n", v);*/ position = ftell(fp); if (fseek (fp, 4, SEEK_CUR)) { reiserfs_warning (stderr, "reiserfs_bitmap_save: fseek failed: %s\n", strerror(errno)); // fclose (fp); return; } zeros = 0; count = 0; extents = 0; for (i = 0; i < v; i ++) { if (reiserfs_bitmap_test_bit (bm, i)) { if (zeros) { /* previous bit was not set, write amount of not set bits, switch to count set bits */ fwrite (&count, 4, 1, fp); /*printf ("SAVE: Free %d\n", count);*/ extents ++; count = 1; zeros = 0; } else { /* one more zero bit appeared */ count ++; } } else { /* zero bit found */ if (zeros) { count ++; } else { /* previous bit was set, write amount of set bits, switch to count not set bits */ fwrite (&count, 4, 1, fp); /*printf ("SAVE: Used %d\n", count);*/ extents ++; count = 1; zeros = 1; } } } fwrite (&count, 4, 1, fp); extents ++; /* if (zeros) printf ("SAVE: Free %d\n", count); else printf ("SAVE: Used %d\n", count); */ v = BITMAP_END_MAGIC; fwrite (&v, 4, 1, fp); if (fseek (fp, position, SEEK_SET)) { reiserfs_warning (stderr, "reiserfs_bitmap_save: fseek failed: %s", strerror(errno)); return; } fwrite (&extents, 4, 1, fp); if (fseek (fp, 0, SEEK_END)) { reiserfs_warning (stderr, "reiserfs_bitmap_save: fseek failed: %s", strerror(errno)); return; } } /* format of fsck dump file: after pass0 magic number (32 bits) passed stage number bitmap of leaves bitmap of good_unfm bitmap of bad_unfm magic number (32 bits) */ #define FSCK_DUMP_START_MAGIC 374033 #define FSCK_DUMP_END_MAGIC 7786470 void reiserfs_begin_stage_info_save(FILE * file, unsigned long stage) { __u32 v = FSCK_DUMP_START_MAGIC; fwrite (&v, 4, 1, file); fwrite (&stage, 4, 1, file); } void reiserfs_end_stage_info_save(FILE * file) { __u32 v = FSCK_DUMP_END_MAGIC; fwrite (&v, 4, 1, file); } /*return last passed stage*/ int is_stage_magic_correct (FILE * fp) { __u32 v; if (fseek (fp, -4, SEEK_END)) { reiserfs_warning (stderr, "is_stage_magic_correct: fseek failed: %s\n", strerror(errno)); return -1; } fread (&v, 4, 1, fp); if (v != FSCK_DUMP_END_MAGIC) { reiserfs_warning (stderr, "is_stage_magic_correct: no magic found\n"); return -1; } if (fseek (fp, 0, SEEK_SET)) { reiserfs_warning (stderr, "is_stage_magic_correct: fseek failed: %s\n", strerror(errno)); return -1; } fread (&v, 4, 1, fp); if (v != FSCK_DUMP_START_MAGIC) { reiserfs_warning (stderr, "is_stage_magic_correct: no magic found\n"); return -1; } fread (&v, 4, 1, fp); if (v != PASS_0_DONE && v != PASS_1_DONE && v != TREE_IS_BUILT && v != SEMANTIC_DONE && v != LOST_FOUND_DONE) { reiserfs_warning (stderr, "is_stage_magic_correct: wrong pass found"); return -1; } return (__u16)v; } reiserfs_bitmap_t * reiserfs_bitmap_load (FILE * fp) { // FILE * fp; __u32 v; int count; int i, j; int extents; int bit; reiserfs_bitmap_t * bm; /* fp = fopen (filename, "r"); if (!fp) { reiserfs_warning (stderr, "reiserfs_bitmap_load: fopen failed: %s\n", strerror(errno)); return 0; }*/ fread (&v, 4, 1, fp); if (v != BITMAP_START_MAGIC) { reiserfs_warning (stderr, "reiserfs_bitmap_load: " "no bitmap start magic found"); // fclose (fp); return 0; } /* read bit size of bitmap */ fread (&v, 4, 1, fp); bm = reiserfs_create_bitmap (v); if (!bm) { reiserfs_warning (stderr, "reiserfs_bitmap_load: creation failed"); // fclose (fp); return 0; } /*printf ("LOAD: bit_size - %d\n", v);*/ fread (&extents, 4, 1, fp); /*printf ("LOAD: extents - %d\n", extents);*/ bit = 0; for (i = 0; i < extents; i ++) { fread (&count, 4, 1, fp); /* if (i % 2) printf ("LOAD: Free %d\n", count); else printf ("LOAD: Used %d\n", count); */ for (j = 0; j < count; j ++, bit ++) if (i % 2 == 0) { reiserfs_bitmap_set_bit (bm, bit); } } fread (&v, 4, 1, fp); /*printf ("LOAD: Endmagic %d\n", v);*/ // fclose (fp); if (v != BITMAP_END_MAGIC) { reiserfs_warning (stderr, "reiserfs_bitmap_load: " "no bitmap end magic found"); return 0; } /* reiserfs_warning (stderr, "%d bits set - done\n", reiserfs_bitmap_ones (bm));*/ fflush (stderr); return bm; } void reiserfs_bitmap_invert (reiserfs_bitmap_t * bm) { unsigned int i; /*reiserfs_warning (stderr, "Bitmap inverting..");fflush (stderr);*/ for (i = 0; i < bm->bm_bit_size; i ++) { if (reiserfs_bitmap_test_bit (bm, i)) reiserfs_bitmap_clear_bit (bm, i); else reiserfs_bitmap_set_bit (bm, i); } /*reiserfs_warning (stderr, "done\n");*/ } void reiserfs_free_ondisk_bitmap (reiserfs_filsys_t * fs) { if (fs->fs_bitmap2) { reiserfs_delete_bitmap (fs->fs_bitmap2); fs->fs_bitmap2 = 0; } } /* read bitmap blocks */ int reiserfs_open_ondisk_bitmap (reiserfs_filsys_t * fs) { if (fs->fs_bitmap2) reiserfs_panic ("%s: bitmap is initiaized already", __FUNCTION__); fs->fs_bitmap2 = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); if (!fs->fs_bitmap2) return -1; if ((get_sb_block_count (fs->fs_ondisk_sb) + fs->fs_blocksize * 8 - 1) / (fs->fs_blocksize * 8) != get_sb_bmap_nr (fs->fs_ondisk_sb)) { reiserfs_warning (stderr, "%s: wrong either bitmaps number,\n", __FUNCTION__); reiserfs_warning (stderr, "count of blocks or blocksize, run with --rebuild-sb " "to fix it\n"); return -1; } return reiserfs_fetch_ondisk_bitmap (fs->fs_bitmap2, fs); } int reiserfs_create_ondisk_bitmap (reiserfs_filsys_t * fs) { if (fs->fs_bitmap2) reiserfs_panic ("create: bitmap is initiaized already"); fs->fs_bitmap2 = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); if (!fs->fs_bitmap2) return 0; return 1; } void reiserfs_close_ondisk_bitmap (reiserfs_filsys_t * fs) { if (!fs->fs_bitmap2) return; reiserfs_flush_to_ondisk_bitmap (fs->fs_bitmap2, fs); reiserfs_free_ondisk_bitmap (fs); } reiserfsprogs-3.6.9/reiserfscore/lbalance.c0000664000077100007710000011323307665645673014550 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "includes.h" /* these are used in do_balance.c */ /* leaf_move_items leaf_shift_left leaf_shift_right leaf_delete_items leaf_insert_into_buf leaf_paste_in_buffer leaf_cut_from_buffer leaf_paste_entries */ extern struct tree_balance init_tb; extern int init_item_pos; extern int init_pos_in_item; extern int init_mode; /* copy copy_count entries from source directory item to dest buffer (creating new item if needed) */ static void leaf_copy_dir_entries (reiserfs_filsys_t * fs, struct buffer_info * dest_bi, struct buffer_head * source, int last_first, int item_num, int from, int copy_count) { struct buffer_head * dest = dest_bi->bi_bh; int item_num_in_dest; /* either the number of target item, or if we must create a new item, the number of the item we will create it next to */ struct item_head * ih; struct reiserfs_de_head * deh; int copy_records_len; /* length of all records in item to be copied */ char * records; ih = B_N_PITEM_HEAD (source, item_num); /* length of all record to be copied and first byte of the last of them */ deh = B_I_DEH (source, ih); if (copy_count) { copy_records_len = (from ? get_deh_location (&deh[from - 1]) : get_ih_item_len (ih)) - get_deh_location (&deh[from + copy_count - 1]); records = source->b_data + get_ih_location (ih) + get_deh_location (&deh[from + copy_count - 1]); } else { copy_records_len = 0; records = 0; } /* when copy last to first, dest buffer can contain 0 items */ item_num_in_dest = (last_first == LAST_TO_FIRST) ? (( B_NR_ITEMS(dest) ) ? 0 : -1) : (B_NR_ITEMS(dest) - 1); /* if there are no items in dest or the first/last item in dest is not item of the same directory */ if ( (item_num_in_dest == - 1) || (last_first == FIRST_TO_LAST && are_items_mergeable (B_N_PITEM_HEAD (dest, item_num_in_dest), ih, dest->b_size) == 0) || (last_first == LAST_TO_FIRST && are_items_mergeable (ih, B_N_PITEM_HEAD (dest, item_num_in_dest), dest->b_size) == 0)) { /* create new item in dest */ struct item_head new_ih; /* form item header */ memcpy (&new_ih.ih_key, &ih->ih_key, KEY_SIZE); /* calculate item len */ set_ih_item_len (&new_ih, DEH_SIZE * copy_count + copy_records_len); set_ih_entry_count (&new_ih, 0); if (last_first == LAST_TO_FIRST) { /* form key by the following way */ if (from < get_ih_entry_count (ih)) { set_key_offset_v1 (&new_ih.ih_key, get_deh_offset (&deh[from])); } else { /* no entries will be copied to this item in this function */ set_key_offset_v1 (&new_ih.ih_key, MAX_KEY1_OFFSET); } set_key_uniqueness (&new_ih.ih_key, DIRENTRY_UNIQUENESS); } set_ih_key_format (&new_ih, get_ih_key_format (ih)); set_ih_flags (&new_ih, get_ih_flags (ih)); /* insert item into dest buffer */ leaf_insert_into_buf (fs, dest_bi, (last_first == LAST_TO_FIRST) ? 0 : B_NR_ITEMS(dest), &new_ih, NULL, 0); } else { /* prepare space for entries */ leaf_paste_in_buffer (fs, dest_bi, (last_first == FIRST_TO_LAST) ? (B_NR_ITEMS(dest) - 1) : 0, 0xffff /*MAX_US_INT */, DEH_SIZE * copy_count + copy_records_len, records, 0); } item_num_in_dest = (last_first == FIRST_TO_LAST) ? (B_NR_ITEMS(dest)-1) : 0; leaf_paste_entries (dest_bi->bi_bh, item_num_in_dest, (last_first == FIRST_TO_LAST) ? get_ih_entry_count (B_N_PITEM_HEAD (dest, item_num_in_dest)) : 0, copy_count, deh + from, records, DEH_SIZE * copy_count + copy_records_len ); } /* Copy the first (if last_first == FIRST_TO_LAST) or last (last_first == LAST_TO_FIRST) item or part of it or nothing (see the return 0 below) from SOURCE to the end (if last_first) or beginning (!last_first) of the DEST */ /* returns 1 if anything was copied, else 0 */ static int leaf_copy_boundary_item (reiserfs_filsys_t * fs, struct buffer_info * dest_bi, struct buffer_head * src, int last_first, int bytes_or_entries) { struct buffer_head * dest = dest_bi->bi_bh; int dest_nr_item, src_nr_item; /* number of items in the source and destination buffers */ struct item_head * ih; struct item_head * dih; dest_nr_item = B_NR_ITEMS(dest); if ( last_first == FIRST_TO_LAST ) { /* if ( DEST is empty or first item of SOURCE and last item of DEST are the items of different objects or of different types ) then there is no need to treat this item differently from the other items that we copy, so we return */ ih = B_N_PITEM_HEAD (src, 0); dih = B_N_PITEM_HEAD (dest, dest_nr_item - 1); if (!dest_nr_item || (are_items_mergeable (dih, ih, src->b_size) == 0)) /* there is nothing to merge */ return 0; if ( I_IS_DIRECTORY_ITEM(ih) ) { if ( bytes_or_entries == -1 ) /* copy all entries to dest */ bytes_or_entries = get_ih_entry_count(ih); leaf_copy_dir_entries (fs, dest_bi, src, FIRST_TO_LAST, 0, 0, bytes_or_entries); return 1; } /* copy part of the body of the first item of SOURCE to the end of the body of the last item of the DEST part defined by 'bytes_or_entries'; if bytes_or_entries == -1 copy whole body; don't create new item header */ if ( bytes_or_entries == -1 ) bytes_or_entries = get_ih_item_len (ih); /* merge first item (or its part) of src buffer with the last item of dest buffer. Both are of the same file */ leaf_paste_in_buffer (fs, dest_bi, dest_nr_item - 1, get_ih_item_len (dih), bytes_or_entries, B_I_PITEM(src,ih), 0); if (I_IS_INDIRECT_ITEM(dih)) { if (bytes_or_entries == get_ih_item_len (ih)) //dih->u.ih_free_space = ih->u.ih_free_space; set_ih_free_space (dih, get_ih_free_space (ih)); } return 1; } /* copy boundary item to right (last_first == LAST_TO_FIRST) */ /* ( DEST is empty or last item of SOURCE and first item of DEST are the items of different object or of different types ) */ src_nr_item = B_NR_ITEMS (src); ih = B_N_PITEM_HEAD (src, src_nr_item - 1); dih = B_N_PITEM_HEAD (dest, 0); if (!dest_nr_item || are_items_mergeable (ih, dih, src->b_size) == 0) return 0; if ( I_IS_DIRECTORY_ITEM(ih)) { if ( bytes_or_entries == -1 ) /* bytes_or_entries = entries number in last item body of SOURCE */ bytes_or_entries = get_ih_entry_count(ih); leaf_copy_dir_entries (fs, dest_bi, src, LAST_TO_FIRST, src_nr_item - 1, get_ih_entry_count(ih) - bytes_or_entries, bytes_or_entries); return 1; } /* copy part of the body of the last item of SOURCE to the begin of the body of the first item of the DEST; part defined by 'bytes_or_entries'; if byte_or_entriess == -1 copy whole body; change first item key of the DEST; don't create new item header */ if ( bytes_or_entries == -1 ) { /* bytes_or_entries = length of last item body of SOURCE */ bytes_or_entries = get_ih_item_len (ih); /* change first item key of the DEST */ //dih->ih_key.k_offset = ih->ih_key.k_offset; set_offset (key_format (&dih->ih_key), &dih->ih_key, get_offset (&ih->ih_key)); /* item becomes non-mergeable */ /* or mergeable if left item was */ //dih->ih_key.k_uniqueness = ih->ih_key.k_uniqueness; set_type (key_format (&dih->ih_key), &dih->ih_key, get_type (&ih->ih_key)); } else { /* merge to right only part of item */ /* change first item key of the DEST */ if ( I_IS_DIRECT_ITEM(dih) ) { //dih->ih_key.k_offset -= bytes_or_entries; set_offset (key_format (&dih->ih_key), &dih->ih_key, get_offset (&dih->ih_key) - bytes_or_entries); } else { //dih->ih_key.k_offset -= ((bytes_or_entries/UNFM_P_SIZE)*dest->b_size); set_offset (key_format (&dih->ih_key), &dih->ih_key, get_offset (&dih->ih_key) - ((bytes_or_entries/UNFM_P_SIZE)*dest->b_size)); } } leaf_paste_in_buffer (fs, dest_bi, 0, 0, bytes_or_entries, B_I_PITEM(src,ih) + get_ih_item_len (ih) - bytes_or_entries, 0); return 1; } /* copy cpy_mun items from buffer src to buffer dest * last_first == FIRST_TO_LAST means, that we copy cpy_num items beginning from first-th item in src to tail of dest * last_first == LAST_TO_FIRST means, that we copy cpy_num items beginning from first-th item in src to head of dest */ static void leaf_copy_items_entirely (reiserfs_filsys_t * fs, struct buffer_info * dest_bi, struct buffer_head * src, int last_first, int first, int cpy_num) { struct buffer_head * dest; int nr; int dest_before; int last_loc, last_inserted_loc, location; int i, j; struct block_head * blkh; struct item_head * ih; dest = dest_bi->bi_bh; if (cpy_num == 0) return; blkh = B_BLK_HEAD(dest); nr = get_blkh_nr_items (blkh); /* we will insert items before 0-th or nr-th item in dest buffer. It depends of last_first parameter */ dest_before = (last_first == LAST_TO_FIRST) ? 0 : nr; /* location of head of first new item */ ih = B_N_PITEM_HEAD (dest, dest_before); /* prepare space for headers */ memmove (ih + cpy_num, ih, (nr-dest_before) * IH_SIZE); /* copy item headers */ memcpy (ih, B_N_PITEM_HEAD (src, first), cpy_num * IH_SIZE); set_blkh_free_space (blkh, get_blkh_free_space (blkh) - IH_SIZE * cpy_num); /* location of unmovable item */ j = location = (dest_before == 0) ? dest->b_size : get_ih_location (ih-1); for (i = dest_before; i < nr + cpy_num; i ++) { location -= get_ih_item_len (&ih[i-dest_before]); set_ih_location (&ih[i-dest_before], location); } /* prepare space for items */ last_loc = get_ih_location (&ih[nr+cpy_num-1-dest_before]); last_inserted_loc = get_ih_location (&ih[cpy_num-1]); /* check free space */ memmove (dest->b_data + last_loc, dest->b_data + last_loc + j - last_inserted_loc, last_inserted_loc - last_loc); /* copy items */ memcpy (dest->b_data + last_inserted_loc, B_N_PITEM(src,(first + cpy_num - 1)), j - last_inserted_loc); /* sizes, item number */ set_blkh_nr_items (blkh, get_blkh_nr_items (blkh) + cpy_num); set_blkh_free_space (blkh, get_blkh_free_space (blkh) - (j - last_inserted_loc)); mark_buffer_dirty (dest); if (dest_bi->bi_parent) { struct disk_child * dc; dc = B_N_CHILD (dest_bi->bi_parent, dest_bi->bi_position); set_dc_child_size (dc, get_dc_child_size (dc) + j - last_inserted_loc + IH_SIZE * cpy_num); mark_buffer_dirty(dest_bi->bi_parent); } } /* This function splits the (liquid) item into two items (useful when shifting part of an item into another node.) */ static void leaf_item_bottle (reiserfs_filsys_t * fs, struct buffer_info * dest_bi, struct buffer_head * src, int last_first, int item_num, int cpy_bytes) { struct buffer_head * dest = dest_bi->bi_bh; struct item_head * ih; if ( last_first == FIRST_TO_LAST ) { /* if ( if item in position item_num in buffer SOURCE is directory item ) */ if (I_IS_DIRECTORY_ITEM(ih = B_N_PITEM_HEAD(src,item_num))) leaf_copy_dir_entries (fs, dest_bi, src, FIRST_TO_LAST, item_num, 0, cpy_bytes); else { struct item_head n_ih; /* copy part of the body of the item number 'item_num' of SOURCE to the end of the DEST part defined by 'cpy_bytes'; create new item header; change old item_header (????); n_ih = new item_header; */ memcpy (&n_ih, ih, IH_SIZE); set_ih_item_len (&n_ih, cpy_bytes); if (I_IS_INDIRECT_ITEM(ih)) { //n_ih.u.ih_free_space = 0; set_ih_free_space (&n_ih, 0);; } //n_ih.ih_version = ih->ih_version; set_ih_key_format (&n_ih, get_ih_key_format (ih)); set_ih_flags (&n_ih, get_ih_flags (ih)); leaf_insert_into_buf (fs, dest_bi, B_NR_ITEMS(dest), &n_ih, B_N_PITEM (src, item_num), 0); } } else { /* if ( if item in position item_num in buffer SOURCE is directory item ) */ if (I_IS_DIRECTORY_ITEM(ih = B_N_PITEM_HEAD (src, item_num))) leaf_copy_dir_entries (fs, dest_bi, src, LAST_TO_FIRST, item_num, get_ih_entry_count(ih) - cpy_bytes, cpy_bytes); else { struct item_head n_ih; /* copy part of the body of the item number 'item_num' of SOURCE to the begin of the DEST part defined by 'cpy_bytes'; create new item header; n_ih = new item_header; */ memcpy (&n_ih, ih, SHORT_KEY_SIZE); if (I_IS_DIRECT_ITEM(ih)) { //n_ih.ih_key.k_offset = ih->ih_key.k_offset + ih->ih_item_len - cpy_bytes; set_offset (key_format (&ih->ih_key), &n_ih.ih_key, get_offset (&ih->ih_key) + get_ih_item_len (ih) - cpy_bytes); //n_ih.ih_key.k_uniqueness = TYPE_DIRECT; set_type (key_format (&ih->ih_key), &n_ih.ih_key, TYPE_DIRECT); //n_ih.u.ih_free_space = USHRT_MAX; set_ih_free_space (&n_ih, USHRT_MAX); } else { /* indirect item */ //n_ih.ih_key.k_offset = ih->ih_key.k_offset + (ih->ih_item_len - cpy_bytes) / UNFM_P_SIZE * dest->b_size; set_offset (key_format (&ih->ih_key), &n_ih.ih_key, get_offset (&ih->ih_key) + (get_ih_item_len (ih) - cpy_bytes) / UNFM_P_SIZE * dest->b_size); //n_ih.ih_key.k_uniqueness = TYPE_INDIRECT; set_type (key_format (&ih->ih_key), &n_ih.ih_key, TYPE_INDIRECT); //n_ih.u.ih_free_space = ih->u.ih_free_space; set_ih_free_space (&n_ih, get_ih_free_space (ih)); } /* set item length */ set_ih_item_len (&n_ih, cpy_bytes); //n_ih.ih_version = ih->ih_version; set_ih_key_format (&n_ih, get_ih_key_format (ih)); set_ih_flags (&n_ih, get_ih_flags (ih)); leaf_insert_into_buf (fs, dest_bi, 0, &n_ih, B_N_PITEM(src,item_num) + get_ih_item_len (ih) - cpy_bytes, 0); } } } /* If cpy_bytes equals minus one than copy cpy_num whole items from SOURCE to DEST. If cpy_bytes not equal to minus one than copy cpy_num-1 whole items from SOURCE to DEST. From last item copy cpy_num bytes for regular item and cpy_num directory entries for directory item. */ static int leaf_copy_items (reiserfs_filsys_t * fs, struct buffer_info * dest_bi, struct buffer_head * src, int last_first, int cpy_num, int cpy_bytes) { struct buffer_head * dest; int pos, i, src_nr_item, bytes; dest = dest_bi->bi_bh; if ( cpy_num == 0 ) return 0; if ( last_first == FIRST_TO_LAST ) { /* copy items to left */ pos = 0; if ( cpy_num == 1 ) bytes = cpy_bytes; else bytes = -1; /* copy the first item or it part or nothing to the end of the DEST (i = leaf_copy_boundary_item(DEST,SOURCE,0,bytes)) */ i = leaf_copy_boundary_item (fs, dest_bi, src, FIRST_TO_LAST, bytes); cpy_num -= i; if ( cpy_num == 0 ) return i; pos += i; if ( cpy_bytes == -1 ) /* copy first cpy_num items starting from position 'pos' of SOURCE to end of DEST */ leaf_copy_items_entirely(fs, dest_bi, src, FIRST_TO_LAST, pos, cpy_num); else { /* copy first cpy_num-1 items starting from position 'pos-1' of the SOURCE to the end of the DEST */ leaf_copy_items_entirely(fs, dest_bi, src, FIRST_TO_LAST, pos, cpy_num-1); /* copy part of the item which number is cpy_num+pos-1 to the end of the DEST */ leaf_item_bottle (fs, dest_bi, src, FIRST_TO_LAST, cpy_num+pos-1, cpy_bytes); } } else { /* copy items to right */ src_nr_item = B_NR_ITEMS (src); if ( cpy_num == 1 ) bytes = cpy_bytes; else bytes = -1; /* copy the last item or it part or nothing to the begin of the DEST (i = leaf_copy_boundary_item(DEST,SOURCE,1,bytes)); */ i = leaf_copy_boundary_item (fs, dest_bi, src, LAST_TO_FIRST, bytes); cpy_num -= i; if ( cpy_num == 0 ) return i; pos = src_nr_item - cpy_num - i; if ( cpy_bytes == -1 ) { /* starting from position 'pos' copy last cpy_num items of SOURCE to begin of DEST */ leaf_copy_items_entirely(fs, dest_bi, src, LAST_TO_FIRST, pos, cpy_num); } else { /* copy last cpy_num-1 items starting from position 'pos+1' of the SOURCE to the begin of the DEST; */ leaf_copy_items_entirely(fs, dest_bi, src, LAST_TO_FIRST, pos+1, cpy_num-1); /* copy part of the item which number is pos to the begin of the DEST */ leaf_item_bottle (fs, dest_bi, src, LAST_TO_FIRST, pos, cpy_bytes); } } return i; } /* there are types of coping: from S[0] to L[0], from S[0] to R[0], from R[0] to L[0]. for each of these we have to define parent and positions of destination and source buffers */ static void leaf_define_dest_src_infos (int shift_mode, struct tree_balance * tb, struct buffer_info * dest_bi, struct buffer_info * src_bi, int * first_last, struct buffer_head * Snew) { /* define dest, src, dest parent, dest position */ switch (shift_mode) { case LEAF_FROM_S_TO_L: /* it is used in leaf_shift_left */ src_bi->bi_bh = PATH_PLAST_BUFFER (tb->tb_path); src_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, 0); src_bi->bi_position = PATH_H_B_ITEM_ORDER (tb->tb_path, 0); /* src->b_item_order */ dest_bi->bi_bh = tb->L[0]; dest_bi->bi_parent = tb->FL[0]; dest_bi->bi_position = get_left_neighbor_position (tb, 0); *first_last = FIRST_TO_LAST; break; case LEAF_FROM_S_TO_R: /* it is used in leaf_shift_right */ src_bi->bi_bh = PATH_PLAST_BUFFER (tb->tb_path); src_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, 0); src_bi->bi_position = PATH_H_B_ITEM_ORDER (tb->tb_path, 0); dest_bi->bi_bh = tb->R[0]; dest_bi->bi_parent = tb->FR[0]; dest_bi->bi_position = get_right_neighbor_position (tb, 0); *first_last = LAST_TO_FIRST; break; case LEAF_FROM_R_TO_L: /* it is used in balance_leaf_when_delete */ src_bi->bi_bh = tb->R[0]; src_bi->bi_parent = tb->FR[0]; src_bi->bi_position = get_right_neighbor_position (tb, 0); dest_bi->bi_bh = tb->L[0]; dest_bi->bi_parent = tb->FL[0]; dest_bi->bi_position = get_left_neighbor_position (tb, 0); *first_last = FIRST_TO_LAST; break; case LEAF_FROM_L_TO_R: /* it is used in balance_leaf_when_delete */ src_bi->bi_bh = tb->L[0]; src_bi->bi_parent = tb->FL[0]; src_bi->bi_position = get_left_neighbor_position (tb, 0); dest_bi->bi_bh = tb->R[0]; dest_bi->bi_parent = tb->FR[0]; dest_bi->bi_position = get_right_neighbor_position (tb, 0); *first_last = LAST_TO_FIRST; break; case LEAF_FROM_S_TO_SNEW: src_bi->bi_bh = PATH_PLAST_BUFFER (tb->tb_path); src_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, 0); src_bi->bi_position = PATH_H_B_ITEM_ORDER (tb->tb_path, 0); dest_bi->bi_bh = Snew; dest_bi->bi_parent = 0; dest_bi->bi_position = 0; *first_last = LAST_TO_FIRST; break; default: reiserfs_panic (0, "vs-10250: leaf_define_dest_src_infos: shift type is unknown (%d)", shift_mode); } } /* copy mov_num items and mov_bytes of the (mov_num-1)th item to neighbor. Delete them from source */ int leaf_move_items (int shift_mode, struct tree_balance * tb, int mov_num, int mov_bytes, struct buffer_head * Snew) { int ret_value; struct buffer_info dest_bi, src_bi; int first_last; leaf_define_dest_src_infos (shift_mode, tb, &dest_bi, &src_bi, &first_last, Snew); ret_value = leaf_copy_items (tb->tb_fs, &dest_bi, src_bi.bi_bh, first_last, mov_num, mov_bytes); leaf_delete_items (tb->tb_fs, &src_bi, first_last, (first_last == FIRST_TO_LAST) ? 0 : (B_NR_ITEMS(src_bi.bi_bh) - mov_num), mov_num, mov_bytes); return ret_value; } /* Shift shift_num items (and shift_bytes of last shifted item if shift_bytes != -1) from S[0] to L[0] and replace the delimiting key */ int leaf_shift_left (struct tree_balance * tb, int shift_num, int shift_bytes) { struct buffer_head * S0 = PATH_PLAST_BUFFER (tb->tb_path); int i; /* move shift_num (and shift_bytes bytes) items from S[0] to left neighbor L[0] */ i = leaf_move_items (LEAF_FROM_S_TO_L, tb, shift_num, shift_bytes, 0); if ( shift_num ) { if (B_NR_ITEMS (S0) == 0) { /* everything is moved from S[0] */ if (PATH_H_POSITION (tb->tb_path, 1) == 0) replace_key(tb->tb_fs, tb->CFL[0], tb->lkey[0], PATH_H_PPARENT (tb->tb_path, 0), 0); } else { /* replace lkey in CFL[0] by 0-th key from S[0]; */ replace_key(tb->tb_fs, tb->CFL[0], tb->lkey[0], S0, 0); } } return i; } /* CLEANING STOPPED HERE */ /* Shift shift_num (shift_bytes) items from S[0] to the right neighbor, and replace the delimiting key */ int leaf_shift_right (struct tree_balance * tb, int shift_num, int shift_bytes) { int ret_value; /* move shift_num (and shift_bytes) items from S[0] to right neighbor R[0] */ ret_value = leaf_move_items (LEAF_FROM_S_TO_R, tb, shift_num, shift_bytes, 0); /* replace rkey in CFR[0] by the 0-th key from R[0] */ if (shift_num) { replace_key(tb->tb_fs, tb->CFR[0], tb->rkey[0], tb->R[0], 0); } return ret_value; } static void leaf_delete_items_entirely (reiserfs_filsys_t * sb, /*struct reiserfs_transaction_handle *th,*/ struct buffer_info * bi, int first, int del_num); /* If del_bytes == -1, starting from position 'first' delete del_num items in whole in buffer CUR. If not. If last_first == 0. Starting from position 'first' delete del_num-1 items in whole. Delete part of body of the first item. Part defined by del_bytes. Don't delete first item header If last_first == 1. Starting from position 'first+1' delete del_num-1 items in whole. Delete part of body of the last item . Part defined by del_bytes. Don't delete last item header. */ void leaf_delete_items (reiserfs_filsys_t * fs, struct buffer_info * cur_bi, int last_first, int first, int del_num, int del_bytes) { struct buffer_head * bh; int item_amount = B_NR_ITEMS (bh = cur_bi->bi_bh); if ( del_num == 0 ) return; if ( first == 0 && del_num == item_amount && del_bytes == -1 ) { make_empty_node (cur_bi); mark_buffer_dirty (bh); return; } if ( del_bytes == -1 ) /* delete del_num items beginning from item in position first */ leaf_delete_items_entirely (fs, cur_bi, first, del_num); else { if ( last_first == FIRST_TO_LAST ) { /* delete del_num-1 items beginning from item in position first */ leaf_delete_items_entirely (fs, cur_bi, first, del_num-1); /* delete the part of the first item of the bh do not delete item header */ leaf_cut_from_buffer (fs, cur_bi, 0, 0, del_bytes); } else { struct item_head * ih; int len; /* delete del_num-1 items beginning from item in position first+1 */ leaf_delete_items_entirely (fs, cur_bi, first+1, del_num-1); if (I_IS_DIRECTORY_ITEM(ih = B_N_PITEM_HEAD(bh, B_NR_ITEMS(bh)-1))) /* the last item is directory */ /* len = numbers of directory entries in this item */ len = get_ih_entry_count(ih); else /* len = body len of item */ len = get_ih_item_len (ih); /* delete the part of the last item of the bh do not delete item header */ leaf_cut_from_buffer (fs, cur_bi, B_NR_ITEMS(bh) - 1, len - del_bytes, del_bytes); } } } /* insert item into the leaf node in position before */ void leaf_insert_into_buf (reiserfs_filsys_t * s, struct buffer_info * bi, int before, struct item_head * inserted_item_ih, const char * inserted_item_body, int zeros_number ) { struct buffer_head * bh = bi->bi_bh; int nr; struct block_head * blkh; struct item_head * ih; int i; int last_loc, unmoved_loc; char * to; blkh = B_BLK_HEAD (bh); nr = get_blkh_nr_items (blkh); /* get item new item must be inserted before */ ih = B_N_PITEM_HEAD (bh, before); /* prepare space for the body of new item */ last_loc = nr ? get_ih_location (&ih[nr - before - 1]) : bh->b_size; unmoved_loc = before ? get_ih_location (ih-1) : bh->b_size; memmove (bh->b_data + last_loc - get_ih_item_len (inserted_item_ih), bh->b_data + last_loc, unmoved_loc - last_loc); to = bh->b_data + unmoved_loc - get_ih_item_len (inserted_item_ih); memset (to, 0, zeros_number); to += zeros_number; /* copy body to prepared space */ if (inserted_item_body) //if (mem_mode == REISERFS_USER_MEM) // copy_from_user (to, inserted_item_body, inserted_item_ih->ih_item_len - zeros_number); //else { memmove (to, inserted_item_body, get_ih_item_len (inserted_item_ih) - zeros_number); //} else memset(to, '\0', get_ih_item_len (inserted_item_ih) - zeros_number); /* insert item header */ memmove (ih + 1, ih, IH_SIZE * (nr - before)); memmove (ih, inserted_item_ih, IH_SIZE); /* change locations */ for (i = before; i < nr + 1; i ++) { unmoved_loc -= get_ih_item_len (&ih[i-before]); set_ih_location (&ih[i-before], unmoved_loc); } /* sizes, free space, item number */ set_blkh_nr_items (blkh, get_blkh_nr_items (blkh) + 1); set_blkh_free_space (blkh, get_blkh_free_space (blkh) - (IH_SIZE + get_ih_item_len (inserted_item_ih))); mark_buffer_dirty(bh) ; if (bi->bi_parent) { struct disk_child * dc; dc = B_N_CHILD (bi->bi_parent, bi->bi_position); set_dc_child_size (dc, get_dc_child_size (dc) + IH_SIZE + get_ih_item_len (inserted_item_ih)); mark_buffer_dirty(bi->bi_parent) ; } if (is_a_leaf(bh->b_data, bh->b_size) != THE_LEAF) reiserfs_panic ("leaf_insert_into_buf: bad leaf %lu: %b", bh->b_blocknr, bh); } /* paste paste_size bytes to affected_item_num-th item. When item is a directory, this only prepare space for new entries */ void leaf_paste_in_buffer (reiserfs_filsys_t * fs, struct buffer_info * bi, int affected_item_num, int pos_in_item, int paste_size, const char * body, int zeros_number) { struct buffer_head * bh = bi->bi_bh; int nr; struct block_head * blkh; struct item_head * ih; int i; int last_loc, unmoved_loc; blkh = B_BLK_HEAD (bh); nr = get_blkh_nr_items (blkh); /* item to be appended */ ih = B_N_PITEM_HEAD(bh, affected_item_num); last_loc = get_ih_location (&ih[nr - affected_item_num - 1]); unmoved_loc = affected_item_num ? get_ih_location (ih-1) : bh->b_size; /* prepare space */ memmove (bh->b_data + last_loc - paste_size, bh->b_data + last_loc, unmoved_loc - last_loc); /* change locations */ for (i = affected_item_num; i < nr; i ++) set_ih_location (&ih[i-affected_item_num], get_ih_location (&ih[i-affected_item_num]) - paste_size); if ( body ) { if (!I_IS_DIRECTORY_ITEM(ih)) { //if (mem_mode == REISERFS_USER_MEM) { //memset (bh->b_data + unmoved_loc - paste_size, 0, zeros_number); //copy_from_user (bh->b_data + unmoved_loc - paste_size + zeros_number, body, paste_size - zeros_number); //} else { if (!pos_in_item) { /* shift data to right */ memmove (bh->b_data + get_ih_location (ih) + paste_size, bh->b_data + get_ih_location (ih), get_ih_item_len (ih)); /* paste data in the head of item */ memset (bh->b_data + get_ih_location (ih), 0, zeros_number); memcpy (bh->b_data + get_ih_location (ih) + zeros_number, body, paste_size - zeros_number); } else { memset (bh->b_data + unmoved_loc - paste_size, 0, zeros_number); memcpy (bh->b_data + unmoved_loc - paste_size + zeros_number, body, paste_size - zeros_number); } } } } else memset(bh->b_data + unmoved_loc - paste_size,'\0',paste_size); set_ih_item_len (ih, get_ih_item_len (ih) + paste_size); /* change free space */ set_blkh_free_space (blkh, get_blkh_free_space (blkh) - paste_size); mark_buffer_dirty(bh) ; if (bi->bi_parent) { struct disk_child * dc; dc = B_N_CHILD (bi->bi_parent, bi->bi_position); set_dc_child_size (dc, get_dc_child_size (dc) + paste_size); mark_buffer_dirty(bi->bi_parent); } if (is_a_leaf(bh->b_data, bh->b_size) != THE_LEAF) reiserfs_panic ("leaf_paste_in_buffer: bad leaf %lu: %b", bh->b_blocknr, bh); } /* cuts DEL_COUNT entries beginning from FROM-th entry. Directory item does not have free space, so it moves DEHs and remaining records as necessary. Return value is size of removed part of directory item in bytes. */ static int leaf_cut_entries (struct buffer_head * bh, struct item_head * ih, int from, int del_count) { char * item; struct reiserfs_de_head * deh; int prev_record_offset; /* offset of record, that is (from-1)th */ char * prev_record; /* */ int cut_records_len; /* length of all removed records */ int i; int entry_count; /* first byte of item */ item = B_I_PITEM (bh, ih); /* entry head array */ deh = B_I_DEH (bh, ih); entry_count = get_ih_entry_count (ih); if (del_count == 0) { int shift; int last_location; last_location = get_deh_location (deh + entry_count - 1); shift = last_location - DEH_SIZE * entry_count; memmove (deh + entry_count, item + last_location, get_ih_item_len (ih) - last_location); for (i = 0; i < entry_count; i ++) set_deh_location (&deh[i], get_deh_location (&deh[i]) - shift); return shift; } /* first byte of remaining entries, those are BEFORE cut entries (prev_record) and length of all removed records (cut_records_len) */ prev_record_offset = (from ? get_deh_location (&deh[from - 1]) : get_ih_item_len (ih)); cut_records_len = prev_record_offset/*from_record*/ - get_deh_location (&deh[from + del_count - 1]); prev_record = item + prev_record_offset; /* adjust locations of remaining entries */ for (i = get_ih_entry_count (ih) - 1; i > from + del_count - 1; i --) { set_deh_location (deh + i, get_deh_location (deh + i) - (DEH_SIZE * del_count)); } for (i = 0; i < from; i ++) { set_deh_location (deh + i, get_deh_location (deh + i) - (DEH_SIZE * del_count + cut_records_len)); } set_ih_entry_count (ih, get_ih_entry_count (ih) - del_count); /* shift entry head array and entries those are AFTER removed entries */ memmove ((char *)(deh + from), deh + from + del_count, prev_record - cut_records_len - (char *)(deh + from + del_count)); /* shift records, those are BEFORE removed entries */ memmove (prev_record - cut_records_len - DEH_SIZE * del_count, prev_record, item + get_ih_item_len (ih) - prev_record); return DEH_SIZE * del_count + cut_records_len; } /* when cut item is part of regular file pos_in_item - first byte that must be cut cut_size - number of bytes to be cut beginning from pos_in_item when cut item is part of directory pos_in_item - number of first deleted entry cut_size - count of deleted entries */ void leaf_cut_from_buffer (reiserfs_filsys_t * fs, struct buffer_info * bi, int cut_item_num, int pos_in_item, int cut_size) { int nr; struct buffer_head * bh = bi->bi_bh; struct block_head * blkh; struct item_head * ih; int last_loc, unmoved_loc; int i; blkh = B_BLK_HEAD (bh); nr = get_blkh_nr_items (blkh); /* item head of truncated item */ ih = B_N_PITEM_HEAD (bh, cut_item_num); if (I_IS_DIRECTORY_ITEM (ih)) { /* first cut entry ()*/ cut_size = leaf_cut_entries (bh, ih, pos_in_item, cut_size); if (pos_in_item == 0) { /* change item key by key of first entry in the item */ set_key_offset_v1 (&ih->ih_key, get_deh_offset (B_I_DEH (bh, ih))); /*memcpy (&ih->ih_key.k_offset, &(B_I_DEH (bh, ih)->deh_offset), SHORT_KEY_SIZE);*/ } } else { /* item is direct or indirect */ /* shift item body to left if cut is from the head of item */ if (pos_in_item == 0) { memmove (bh->b_data + get_ih_location (ih), bh->b_data + get_ih_location (ih) + cut_size, get_ih_item_len (ih) - cut_size); /* change key of item */ if (I_IS_DIRECT_ITEM(ih)) { //ih->ih_key.k_offset += cut_size; set_offset (key_format (&ih->ih_key), &ih->ih_key, get_offset (&ih->ih_key) + cut_size); } else { //ih->ih_key.k_offset += (cut_size / UNFM_P_SIZE) * bh->b_size; set_offset (key_format (&ih->ih_key), &ih->ih_key, get_offset (&ih->ih_key) + (cut_size / UNFM_P_SIZE) * bh->b_size); } } } /* location of the last item */ last_loc = get_ih_location (&ih[nr - cut_item_num - 1]); /* location of the item, which is remaining at the same place */ unmoved_loc = cut_item_num ? get_ih_location (ih-1) : bh->b_size; /* shift */ memmove (bh->b_data + last_loc + cut_size, bh->b_data + last_loc, unmoved_loc - last_loc - cut_size); /* change item length */ set_ih_item_len (ih, get_ih_item_len (ih) - cut_size); if (I_IS_INDIRECT_ITEM(ih)) { if (pos_in_item) //ih->u.ih_free_space = 0; set_ih_free_space (ih, 0); } /* change locations */ for (i = cut_item_num; i < nr; i ++) { set_ih_location (&ih[i-cut_item_num], get_ih_location (&ih[i-cut_item_num]) + cut_size); } /* size, free space */ set_blkh_free_space (blkh, get_blkh_free_space (blkh) + cut_size); mark_buffer_dirty(bh); if (bi->bi_parent) { struct disk_child * dc; dc = B_N_CHILD (bi->bi_parent, bi->bi_position); set_dc_child_size (dc, get_dc_child_size (dc) - cut_size); mark_buffer_dirty(bi->bi_parent); } if (is_a_leaf(bh->b_data, bh->b_size) != THE_LEAF) reiserfs_panic ("leaf_cut_from_buffer: bad leaf %lu: %b", bh->b_blocknr, bh); } /* delete del_num items from buffer starting from the first'th item */ static void leaf_delete_items_entirely (reiserfs_filsys_t * fs, struct buffer_info * bi, int first, int del_num) { struct buffer_head * bh = bi->bi_bh; int nr; int i, j; int last_loc, last_removed_loc; struct block_head * blkh; struct item_head * ih; if (del_num == 0) return; blkh = B_BLK_HEAD (bh); nr = get_blkh_nr_items (blkh); if (first == 0 && del_num == nr) { /* this does not work */ make_empty_node (bi); mark_buffer_dirty(bh); return; } ih = B_N_PITEM_HEAD (bh, first); /* location of unmovable item */ j = (first == 0) ? bh->b_size : get_ih_location (ih-1); /* delete items */ last_loc = get_ih_location (&ih[nr - 1 - first]); last_removed_loc = get_ih_location (&ih[del_num-1]); memmove (bh->b_data + last_loc + j - last_removed_loc, bh->b_data + last_loc, last_removed_loc - last_loc); /* delete item headers */ memmove (ih, ih + del_num, (nr - first - del_num) * IH_SIZE); /* change item location */ for (i = first; i < nr - del_num; i ++) { set_ih_location (&ih[i-first], get_ih_location (&ih[i-first]) + j - last_removed_loc); } /* sizes, item number */ set_blkh_nr_items (blkh, get_blkh_nr_items (blkh)/*nr*/ - del_num); set_blkh_free_space (blkh, get_blkh_free_space (blkh) + j - last_removed_loc + IH_SIZE * del_num); mark_buffer_dirty(bh); if (bi->bi_parent) { struct disk_child * dc; dc = B_N_CHILD (bi->bi_parent, bi->bi_position); set_dc_child_size (dc, get_dc_child_size (dc) - (j - last_removed_loc + IH_SIZE * del_num)); mark_buffer_dirty(bi->bi_parent); } if (is_a_leaf(bh->b_data, bh->b_size) != THE_LEAF) reiserfs_panic ("leaf_delete_items_entirely: bad leaf %lu: %b", bh->b_blocknr, bh); } /* paste new_entry_count entries (new_dehs, records) into position before to item_num-th item */ void leaf_paste_entries (struct buffer_head * bh, int item_num, int before, int new_entry_count, struct reiserfs_de_head * new_dehs, const char * records, int paste_size) { struct item_head * ih; char * item; struct reiserfs_de_head * deh; char * insert_point; int i, old_entry_num; if (new_entry_count == 0) return; ih = B_N_PITEM_HEAD(bh, item_num); /* first byte of dest item */ item = B_I_PITEM (bh, ih); /* entry head array */ deh = B_I_DEH (bh, ih); /* new records will be pasted at this point */ insert_point = item + (before ? get_deh_location (&deh[before - 1]) : (get_ih_item_len (ih) - paste_size)); /* adjust locations of records that will be AFTER new records */ for (i = get_ih_entry_count (ih) - 1; i >= before; i --) set_deh_location (deh + i, get_deh_location (deh + i) + DEH_SIZE * new_entry_count); /* adjust locations of records that will be BEFORE new records */ for (i = 0; i < before; i ++) set_deh_location (deh + i, get_deh_location (deh + i) + paste_size); old_entry_num = get_ih_entry_count (ih); //I_ENTRY_COUNT(ih) += new_entry_count; set_ih_entry_count (ih, old_entry_num + new_entry_count); /* prepare space for pasted records */ memmove (insert_point + paste_size, insert_point, item + (get_ih_item_len (ih) - paste_size) - insert_point); /* copy new records */ memcpy (insert_point + DEH_SIZE * new_entry_count, records, paste_size - DEH_SIZE * new_entry_count); /* prepare space for new entry heads */ deh += before; memmove ((char *)(deh + new_entry_count), deh, insert_point - (char *)deh); /* copy new entry heads */ memcpy (deh, new_dehs, DEH_SIZE * new_entry_count); /* set locations of new records */ for (i = 0; i < new_entry_count; i ++) set_deh_location (deh + i, get_deh_location (deh + i) + (- get_deh_location (&new_dehs[new_entry_count - 1]) + insert_point + DEH_SIZE * new_entry_count - item)); /* change item key if neccessary (when we paste before 0-th entry */ if (!before) set_key_offset_v1 (&ih->ih_key, get_deh_offset (new_dehs)); } /* wrappers for operations on one separated node */ void delete_item (reiserfs_filsys_t * fs, struct buffer_head * bh, int item_num) { struct buffer_info bi; bi.bi_bh = bh; bi.bi_parent = 0; bi.bi_position = 0; leaf_delete_items_entirely (fs, &bi, item_num, 1); } void cut_entry (reiserfs_filsys_t * fs, struct buffer_head * bh, int item_num, int entry_num, int del_count) { struct buffer_info bi; bi.bi_bh = bh; bi.bi_parent = 0; bi.bi_position = 0; leaf_cut_from_buffer (fs, &bi, item_num, entry_num, del_count); } reiserfsprogs-3.6.9/reiserfscore/journal.c0000664000077100007710000006200707705261642014444 /* * Copyright 2002-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "includes.h" /* this is provided for anybody who wants to deal with journal */ int replay_one_transaction (reiserfs_filsys_t *, reiserfs_trans_t *); void for_each_transaction (reiserfs_filsys_t *, action_on_trans_t); void for_each_block (reiserfs_filsys_t *, reiserfs_trans_t *, action_on_block_t); int get_boundary_transactions (reiserfs_filsys_t *, reiserfs_trans_t *, reiserfs_trans_t *); int next_transaction (reiserfs_filsys_t *, reiserfs_trans_t *, reiserfs_trans_t); /* compares description block with commit block. returns 0 if they differ, 1 if they match */ static int does_desc_match_commit (struct buffer_head *d_bh, struct buffer_head *c_bh) { return (get_commit_trans_id (c_bh) == get_desc_trans_id (d_bh) && get_commit_trans_len (c_bh) == get_desc_trans_len (d_bh)); } /* d_bh is descriptor, return number of block where commit block of this transaction is to be */ unsigned long commit_expected (reiserfs_filsys_t * fs, struct buffer_head * d_bh) { unsigned long offset; struct journal_params * sb_jp; sb_jp = sb_jp (fs->fs_ondisk_sb); //desc = (struct reiserfs_journal_desc *)d_bh->b_data; offset = d_bh->b_blocknr - get_jp_journal_1st_block (sb_jp); return get_jp_journal_1st_block (sb_jp) + ((offset + get_desc_trans_len (d_bh) + 1) % get_jp_journal_size (sb_jp)); } /* d_bh contains journal descriptor, returns number of block where descriptor block of next transaction should be */ unsigned long next_desc_expected (reiserfs_filsys_t * fs, struct buffer_head * d_bh) { unsigned long offset; struct journal_params * sb_jp; sb_jp = sb_jp (fs->fs_ondisk_sb); //desc = (struct reiserfs_journal_desc *)d_bh->b_data; offset = d_bh->b_blocknr - get_jp_journal_1st_block (sb_jp); return get_jp_journal_1st_block (sb_jp) + ((offset + get_desc_trans_len (d_bh) + 2) % get_jp_journal_size (sb_jp)); } /* common checks for validness of a transaction */ int transaction_check_content (reiserfs_filsys_t * fs, reiserfs_trans_t * trans) { struct buffer_head *d_bh, *c_bh; struct reiserfs_journal_desc * desc; struct reiserfs_journal_commit * commit; unsigned long block; unsigned int trans_half, i; d_bh = bread (fs->fs_journal_dev, trans->desc_blocknr, fs->fs_blocksize); if (!d_bh || who_is_this (d_bh->b_data, d_bh->b_size) != THE_JDESC) goto error_desc_brelse; /* read expected commit block and compare with descriptor block */ c_bh = bread (fs->fs_journal_dev, commit_expected (fs, d_bh), fs->fs_blocksize); if (!c_bh) goto error_desc_brelse; if (!does_desc_match_commit (d_bh, c_bh)) goto error_commit_brelse; /* Check that all target blocks are journalable */ desc = (struct reiserfs_journal_desc *)(d_bh->b_data); commit = (struct reiserfs_journal_commit *)(c_bh->b_data); trans_half = journal_trans_half (d_bh->b_size); for (i = 0; i < get_desc_trans_len(d_bh); i++) { if (i < trans_half) block = le32_to_cpu (desc->j2_realblock[i]); else block = le32_to_cpu (commit->j3_realblock[i - trans_half]); if (not_journalable(fs, block)) goto error_commit_brelse; } brelse (d_bh); brelse (c_bh); return 1; error_commit_brelse: brelse (c_bh); error_desc_brelse: brelse(d_bh); return 0; } /* common checks for validness of a transaction */ int transaction_check_desc(reiserfs_filsys_t * fs, struct buffer_head * d_bh) { struct buffer_head * c_bh; int ret = 1; if (!d_bh || who_is_this (d_bh->b_data, d_bh->b_size) != THE_JDESC) return 0; /* read expected commit block and compare with descriptor block */ c_bh = bread (fs->fs_journal_dev, commit_expected (fs, d_bh), fs->fs_blocksize); if (!c_bh) return 0; if (!does_desc_match_commit (d_bh, c_bh)) ret = 0; brelse (c_bh); return ret; } /* read the journal and find the oldest and newest transactions, return number of transactions found */ int get_boundary_transactions (reiserfs_filsys_t * fs, reiserfs_trans_t * oldest, reiserfs_trans_t * newest) { struct reiserfs_super_block * sb; unsigned long j_cur; unsigned long j_start; unsigned long j_size; struct buffer_head * d_bh; __u32 newest_trans_id, oldest_trans_id, trans_id; int trans_nr; sb = fs->fs_ondisk_sb; j_start = get_jp_journal_1st_block (sb_jp (sb)); j_size = get_jp_journal_size (sb_jp (sb)); oldest_trans_id = 0xffffffff; newest_trans_id = 0; trans_nr = 0; for (j_cur = 0; j_cur < j_size; j_cur ++) { d_bh = bread (fs->fs_journal_dev, j_start + j_cur, fs->fs_blocksize); if (!transaction_check_desc (fs, d_bh)) { brelse (d_bh); continue; } trans_nr ++; trans_id = get_desc_trans_id (d_bh); if (trans_id < oldest_trans_id) { oldest_trans_id = trans_id; oldest->mount_id = get_desc_mount_id (d_bh); oldest->trans_id = get_desc_trans_id (d_bh); oldest->desc_blocknr = d_bh->b_blocknr; oldest->trans_len = get_desc_trans_len (d_bh); oldest->commit_blocknr = commit_expected (fs, d_bh); oldest->next_trans_offset = next_desc_expected (fs, d_bh) - j_start; } if (trans_id > newest_trans_id) { newest_trans_id = trans_id; newest->mount_id = get_desc_mount_id (d_bh); newest->trans_id = get_desc_trans_id (d_bh); newest->desc_blocknr = d_bh->b_blocknr; newest->trans_len = get_desc_trans_len (d_bh); newest->commit_blocknr = commit_expected (fs, d_bh); newest->next_trans_offset = next_desc_expected (fs, d_bh) - j_start; } j_cur += get_desc_trans_len (d_bh) + 1; brelse (d_bh); } return trans_nr; } #define TRANS_FOUND 1 #define TRANS_LAST 2 #define TRANS_NOT_FOUND 0 /* trans is a valid transaction. Look for valid transaction with smallest trans id which is greater than the id of the current one */ int next_transaction (reiserfs_filsys_t * fs, reiserfs_trans_t * trans, reiserfs_trans_t break_trans) { struct buffer_head * d_bh, * next_d_bh; int found; unsigned long j_start; unsigned long j_offset; unsigned long block; j_start = get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb)); found = TRANS_NOT_FOUND; if (trans->trans_id == break_trans.trans_id) return found; /* make sure that 'trans' is a valid transaction */ d_bh = bread (fs->fs_journal_dev, trans->desc_blocknr, fs->fs_blocksize); if (!transaction_check_desc (fs, d_bh)) die ("next_transaction: valid transaction is expected"); block = next_desc_expected (fs, d_bh); j_offset = block - j_start; while (1) { next_d_bh = bread (fs->fs_journal_dev, block, fs->fs_blocksize); if (transaction_check_desc (fs, next_d_bh)) break; brelse (next_d_bh); j_offset ++; block = j_start + (j_offset % get_jp_journal_size (sb_jp (fs->fs_ondisk_sb))); } //next_desc = (struct reiserfs_journal_desc *)next_d_bh->b_data; if (break_trans.trans_id >= get_desc_trans_id (next_d_bh)) { /* found transaction is newer */ trans->mount_id = get_desc_mount_id (next_d_bh); trans->trans_id = get_desc_trans_id (next_d_bh); trans->desc_blocknr = next_d_bh->b_blocknr; trans->trans_len = get_desc_trans_len (next_d_bh); trans->commit_blocknr = commit_expected (fs, next_d_bh); trans->next_trans_offset = next_desc_expected (fs, next_d_bh) - j_start; found = TRANS_FOUND; if (break_trans.trans_id == get_desc_trans_id (next_d_bh)) found = TRANS_LAST; } brelse (d_bh); brelse (next_d_bh); return found; } static void read_journal_write_in_place (reiserfs_filsys_t * fs, reiserfs_trans_t * trans, unsigned int index, unsigned long in_journal, unsigned long in_place) { struct buffer_head * j_bh, * bh; j_bh = bread (fs->fs_journal_dev, in_journal, fs->fs_blocksize); if (!j_bh) { fprintf (stderr, "replay_one_transaction: transaction %lu: reading %lu block failed\n", trans->trans_id, in_journal); return; } if (not_journalable (fs, in_place)) { fprintf (stderr, "replay_one_transaction: transaction %lu: block %ld should not be journalled (%lu)\n", trans->trans_id, in_journal, in_place); brelse (j_bh); return; } bh = getblk (fs->fs_dev, in_place, fs->fs_blocksize); memcpy (bh->b_data, j_bh->b_data, bh->b_size); mark_buffer_dirty (bh); mark_buffer_uptodate (bh, 1); bwrite (bh); brelse (bh); brelse (j_bh); } /* go through all blocks of transaction and call 'action' each of them */ void for_each_block (reiserfs_filsys_t * fs, reiserfs_trans_t * trans, action_on_block_t action) { struct buffer_head * d_bh, * c_bh; struct reiserfs_journal_desc * desc; struct reiserfs_journal_commit * commit; unsigned long j_start, j_offset, j_size; unsigned int i, trans_half; unsigned long block; d_bh = bread (fs->fs_journal_dev, trans->desc_blocknr, fs->fs_blocksize); if (!d_bh) { reiserfs_warning (stdout, "reading descriptor block %lu failed\n", trans->desc_blocknr); return; } c_bh = bread (fs->fs_journal_dev, trans->commit_blocknr, fs->fs_blocksize); if (!c_bh) { reiserfs_warning (stdout, "reading commit block %lu failed\n", trans->commit_blocknr); brelse (d_bh); return; } desc = (struct reiserfs_journal_desc *)(d_bh->b_data); commit = (struct reiserfs_journal_commit *)(c_bh->b_data); /* first block of journal and size of journal */ j_start = get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb)); j_size = get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)); /* offset in the journal where the transaction starts */ j_offset = trans->desc_blocknr - j_start + 1; trans_half = journal_trans_half (d_bh->b_size); for (i = 0; i < trans->trans_len; i ++, j_offset ++) { if (i < trans_half) block = le32_to_cpu (desc->j2_realblock[i]); else block = le32_to_cpu (commit->j3_realblock[i - trans_half]); action (fs, trans, i, j_start + (j_offset % j_size), block); } brelse (d_bh); brelse (c_bh); } /* transaction is supposed to be valid */ int replay_one_transaction (reiserfs_filsys_t * fs, reiserfs_trans_t * trans) { for_each_block (fs, trans, read_journal_write_in_place); return 0; } void for_each_transaction (reiserfs_filsys_t * fs, action_on_trans_t action) { reiserfs_trans_t oldest, newest; int ret = 0; if (!get_boundary_transactions (fs, &oldest, &newest)) return; while (1) { action (fs, &oldest); if (ret == TRANS_LAST) break; ret = next_transaction (fs, &oldest, newest); if (ret == TRANS_NOT_FOUND) break; } } unsigned long get_size_of_journal_or_reserved_area( struct reiserfs_super_block * sb) { if (is_reiserfs_jr_magic_string (sb)) return get_sb_reserved_for_journal (sb); /* with standard journal */ return get_jp_journal_size (sb_jp (sb)) + 1; } __u32 advise_journal_max_trans_len (__u32 desired, __u32 journal_size /* no j_header */, int blocksize, int verbose) { __u32 saved; __u32 ratio = 1; if (blocksize < 4096) ratio = 4096/blocksize; saved = desired; if (!desired) desired = JOURNAL_TRANS_MAX/ratio; if (journal_size / desired < JOURNAL_MIN_RATIO) desired = journal_size / JOURNAL_MIN_RATIO; if (desired > JOURNAL_TRANS_MAX/ratio) desired = JOURNAL_TRANS_MAX/ratio; if (desired < JOURNAL_TRANS_MIN/ratio) desired = JOURNAL_TRANS_MIN/ratio; if (verbose) { if (saved && saved != desired) reiserfs_warning (stderr, "WARNING: wrong transaction max size (%u). Changed to %u\n", saved, desired); } return desired; } #if 0 __u32 ret_val; ret_val = 0; if (!desired) ret_val = JOURNAL_TRANS_MAX; if (desiredjournal_size/2) ret_val = journal_size/2; if (desired>JOURNAL_TRANS_MAX) ret_val = JOURNAL_TRANS_MAX; if (ret_val) { reiserfs_warning (stderr, "WARNING: Journal max trans length is wrong seting: %u, resetting to available possible %u\n", desired, ret_val); } else { ret_val = desired; } return ret_val; } #endif __u32 advise_journal_max_batch (unsigned long journal_trans_max) { return journal_trans_max*JOURNAL_MAX_BATCH/JOURNAL_TRANS_MAX; } __u32 advise_journal_max_commit_age (void) { return JOURNAL_MAX_COMMIT_AGE; } __u32 advise_journal_max_trans_age (void) { return JOURNAL_MAX_TRANS_AGE; } int reiserfs_journal_params_check (reiserfs_filsys_t * fs) { struct reiserfs_journal_header * j_head; struct reiserfs_super_block * sb = fs->fs_ondisk_sb; j_head = (struct reiserfs_journal_header *)(fs->fs_jh_bh->b_data); /* Check the superblock's journal parameters. */ if (!is_reiserfs_jr_magic_string (sb)) { if (get_jp_journal_dev (sb_jp(sb)) != 0 || get_jp_journal_1st_block (sb_jp(sb)) != get_journal_start_must (fs) || get_jp_journal_size (sb_jp(sb)) != journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) { reiserfs_warning (stderr, "\nreiserfs_open_journal: wrong journal parameters found in the " "super block. \nYou should run reiserfsck with --rebuild-sb to " "check your superblock consistency.\n\n"); return 1; } } if (memcmp(&j_head->jh_journal, sb_jp (sb), sizeof(struct journal_params))) { if (!is_reiserfs_jr_magic_string (sb)) { reiserfs_warning (stderr, "\nreiserfs_open_journal: journal parameters from the superblock " "does not match \nto the journal headers ones. It looks like that " "you created your fs with old\nreiserfsprogs. Journal header is " "fixed.\n\n", fs->fs_j_file_name); memcpy(&j_head->jh_journal, sb_jp(sb), sizeof(struct journal_params)); mark_buffer_dirty(fs->fs_jh_bh); bwrite(fs->fs_jh_bh); } else { reiserfs_warning (stderr, "\nreiserfs_open_journal: journal parameters from the super block " "does not match \nto journal parameters from the journal. You should " "run reiserfsck with --rebuild-sb to check your superblock consistency.\n\n"); return 1; } } return 0; } /* read journal header and make sure that it matches with the filesystem opened */ int reiserfs_open_journal (reiserfs_filsys_t * fs, char * j_filename, int flags) { struct reiserfs_super_block * sb; __u64 count; sb = fs->fs_ondisk_sb; if (!j_filename) { if (is_reiserfs_jr_magic_string (sb)) { /* create a special file to access journal */ return 1; } j_filename = fs->fs_file_name; } else if (!is_reiserfs_jr_magic_string (sb)) { /* make sure that name specified is a correct name */ if (strcmp (j_filename, fs->fs_file_name)) { reiserfs_warning (stderr, "Filesystem with standard journal found, " "wrong name of specified journal device %s \n", j_filename); return 1; } } fs->fs_journal_dev = open (j_filename, flags | O_LARGEFILE); if (fs->fs_journal_dev == -1) return -1; asprintf (&fs->fs_j_file_name, "%s", j_filename); if (get_jp_journal_size(sb_jp(sb)) < JOURNAL_MIN_SIZE) { reiserfs_warning (stderr, "Journal of (%lu) block size found on specified journal " "device %s.\nMust be not less than (%lu).\nRun --rebuild-sb to rebuild journal " "parameters.\n", get_jp_journal_size (sb_jp (sb)) + 1, j_filename, JOURNAL_MIN_SIZE + 1); return 1; } count = count_blocks (j_filename, fs->fs_blocksize); if (get_jp_journal_1st_block (sb_jp (sb)) + get_jp_journal_size (sb_jp (sb)) + 1 > count) { reiserfs_warning (stderr, "Detected journal on specified device %s does not fit to " "the device.\nStart block (%lu) + size (%lu) less than device size (%lu).\n" "Run --rebuild-sb to rebuild journal parameters.\n", get_jp_journal_1st_block(sb_jp (sb)), get_jp_journal_size(sb_jp (sb)) + 1, count); return 1; } /* read journal header */ fs->fs_jh_bh = bread (fs->fs_journal_dev, get_jp_journal_1st_block (sb_jp (sb)) + get_jp_journal_size (sb_jp (sb)), fs->fs_blocksize); if (!fs->fs_jh_bh) { reiserfs_warning (stderr, "reiserfs_open_journal: bread failed reading " "journal header.\n"); return -1; } return 0; } /* initialize super block's journal related fields and journal header fields. * If len is 0 - make journal of default size */ int reiserfs_create_journal( reiserfs_filsys_t * fs, char * j_device, /* journal device name */ unsigned long offset, /* journal offset on the j_device */ unsigned long len, /* including journal header */ int transaction_max_size) { struct stat st; struct buffer_head * bh; struct reiserfs_journal_header * jh; struct reiserfs_super_block * sb; unsigned long blocks; sb = fs->fs_ondisk_sb; if (!j_device || !strcmp (j_device, fs->fs_file_name)) { /* Journal is to be on the host device, check the amount space for the * journal on it. */ len = len ? len : journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1; offset = offset ? offset : get_journal_start_must(fs); if (offset < get_journal_start_must(fs)) { reiserfs_warning (stderr, "reiserfs_create_journal: offset is " "%lu, but it cannot be less then %llu on the device %s\n", offset, get_journal_start_must(fs), j_device); return 0; } if (!is_block_count_correct(offset, fs->fs_blocksize, get_sb_block_count(sb), len)) { /* host device does not contain enough blocks */ reiserfs_warning (stderr, "reiserfs_create_journal: cannot create " "a journal of %lu blocks with %lu offset on %d blocks\n", len, offset, get_sb_block_count(sb)); return 0; } j_device = fs->fs_file_name; st.st_rdev = 0; } else { /* journal is to be on separate device */ blocks = count_blocks (j_device, fs->fs_blocksize); if (!len) { /* default size of a journal on a separate device is whole device */ if (blocks < offset) { reiserfs_warning (stderr, "reiserfs_create_journal: offset is " "%lu, blocks on device %lu\n", offset, blocks); return 0; } len = blocks - offset; } if (len > journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1) { fflush(stderr); reiserfs_warning (stdout, "NOTE: journal new size %lu is greater " "than default size %lu:\nthis may slow down initializing and " "mounting of the journal. Hope it is ok.\n\n", len, journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1); } if (blocks < offset + len) { reiserfs_warning (stderr, "reiserfs_create_journal: no enough " "blocks on device %lu, needed %lu\n", blocks, offset + len); return 0; } if (stat (j_device, &st) == -1) { reiserfs_warning (stderr, "reiserfs_create_journal: stat %s failed" ": %s\n", j_device, strerror(errno)); return 0; } /* if (!S_ISBLK (st.st_mode)) { reiserfs_warning (stderr, "reiserfs_create_journal: " "%s is not a block device (%x)\n", j_device, st.st_rdev); return 0; } */ } fs->fs_journal_dev = open (j_device, O_RDWR | O_LARGEFILE); if (fs->fs_journal_dev == -1) { reiserfs_warning (stderr, "reiserfs_create_journal: could not open " "%s: %s\n", j_device, strerror(errno)); return 0; } asprintf (&fs->fs_j_file_name, "%s", j_device); if (len < JOURNAL_MIN_SIZE) { reiserfs_warning (stderr, "WARNING: Journal size (%u) is less, than " "minimal supported journal size (%u).", len, JOURNAL_MIN_SIZE + 1); return 0; } /* get journal header */ bh = getblk (fs->fs_journal_dev, offset + len - 1, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "reiserfs_create_journal: getblk failed\n"); return 0; } /* fill journal header */ jh = (struct reiserfs_journal_header *)bh->b_data; set_jp_journal_1st_block(&jh->jh_journal, offset); set_jp_journal_dev(&jh->jh_journal, st.st_rdev); set_jp_journal_magic(&jh->jh_journal, get_random()); set_jp_journal_size(&jh->jh_journal, len - 1); set_jp_journal_max_trans_len(&jh->jh_journal, advise_journal_max_trans_len( transaction_max_size, len - 1, fs->fs_blocksize, 1)); set_jp_journal_max_batch(&jh->jh_journal, advise_journal_max_batch( get_jp_journal_max_trans_len(&jh->jh_journal))); set_jp_journal_max_commit_age(&jh->jh_journal, advise_journal_max_commit_age()); set_jp_journal_max_trans_age(&jh->jh_journal, advise_journal_max_trans_age ()); mark_buffer_uptodate (bh, 1); mark_buffer_dirty (bh); fs->fs_jh_bh = bh; /* make a copy of journal header in the super block */ memcpy (sb_jp (sb), &jh->jh_journal, sizeof (struct journal_params)); mark_buffer_dirty (fs->fs_super_bh); return 1; } /* brelse journal header, flush all dirty buffers, close device, open, read journal header */ void reiserfs_reopen_journal (reiserfs_filsys_t * fs, int flag) { unsigned long jh_block; if (!reiserfs_journal_opened (fs)) return; jh_block = fs->fs_jh_bh->b_blocknr; brelse (fs->fs_jh_bh); flush_buffers (fs->fs_journal_dev); invalidate_buffers (fs->fs_journal_dev); if (close (fs->fs_journal_dev)) die ("reiserfs_reopen_journal: closed failed: %s", strerror(errno)); fs->fs_journal_dev = open (fs->fs_j_file_name, flag | O_LARGEFILE); if (fs->fs_journal_dev == -1) die ("reiserfs_reopen_journal: could not reopen journal device"); fs->fs_jh_bh = bread (fs->fs_journal_dev, jh_block, fs->fs_blocksize); if (!fs->fs_jh_bh) die ("reiserfs_reopen_journal: reading journal header failed"); } int reiserfs_journal_opened (reiserfs_filsys_t * fs) { return fs->fs_jh_bh ? 1 : 0; } void reiserfs_flush_journal (reiserfs_filsys_t * fs) { if (!reiserfs_journal_opened (fs)) return; flush_buffers (fs->fs_journal_dev); } void reiserfs_free_journal (reiserfs_filsys_t * fs) { if (!reiserfs_journal_opened (fs)) return; brelse (fs->fs_jh_bh); fs->fs_jh_bh = 0; free (fs->fs_j_file_name); fs->fs_j_file_name = 0; } void reiserfs_close_journal (reiserfs_filsys_t * fs) { reiserfs_flush_journal (fs); reiserfs_free_journal (fs); } /* update journal header */ static void update_journal_header (struct buffer_head * bh_jh, reiserfs_trans_t trans) { struct reiserfs_journal_header * j_head; j_head = (struct reiserfs_journal_header *)(bh_jh->b_data); /* update journal header */ set_jh_last_flushed (j_head, trans.trans_id); set_jh_mount_id (j_head, trans.mount_id); set_jh_replay_start_offset (j_head, trans.next_trans_offset); mark_buffer_dirty (bh_jh); bwrite (bh_jh); } /* fixme: what should be done when not all transactions can be replayed in proper order? */ int replay_journal (reiserfs_filsys_t * fs) { struct buffer_head * bh; struct reiserfs_journal_header * j_head; reiserfs_trans_t cur, newest, control; int replayed, ret; if (!reiserfs_journal_opened (fs)) reiserfs_panic ("replay_journal: journal is not opened"); if (!is_opened_rw (fs)) reiserfs_panic ("replay_journal: fs is not opened with write perms"); reiserfs_warning (stderr, "Replaying journal..\n"); bh = fs->fs_jh_bh; j_head = (struct reiserfs_journal_header *)(bh->b_data); control.mount_id = get_jh_mount_id (j_head); control.trans_id = get_jh_last_flushed (j_head); control.desc_blocknr = get_jh_replay_start_offset (j_head); if (!get_boundary_transactions (fs, &cur, &newest)) { reiserfs_warning (stderr, "No transactions found\n"); return 0; } /* Smth strange with journal header or journal. We cannot say for sure what was the last replaied transaction, but relying on JH data is preferable. */ replayed = 0; ret = TRANS_FOUND; while (cur.mount_id != control.mount_id || cur.trans_id != control.trans_id) { if (control.mount_id == cur.mount_id && control.trans_id == 0 && control.desc_blocknr == 0) break; ret = next_transaction (fs, &cur, newest); if (ret != TRANS_FOUND) break; } while (ret == TRANS_FOUND) { if (control.mount_id != cur.mount_id || control.trans_id != 0 || control.desc_blocknr != 0) { ret = next_transaction (fs, &cur, newest); if (ret == TRANS_NOT_FOUND) break; if (cur.mount_id != control.mount_id || cur.trans_id != control.trans_id + 1) break; } if (!transaction_check_content(fs, &cur)) { reiserfs_warning (stderr, "Trans broken: mountid %lu, transid %lu, desc %lu, " "len %lu, commit %lu, next trans offset %lu\n", cur.mount_id, cur.trans_id, cur.desc_blocknr, cur.trans_len, cur.commit_blocknr, cur.next_trans_offset); break; } reiserfs_warning (stderr, "Trans replayed: mountid %lu, transid %lu, desc %lu, " "len %lu, commit %lu, next trans offset %lu\n", cur.mount_id, cur.trans_id, cur.desc_blocknr, cur.trans_len, cur.commit_blocknr, cur.next_trans_offset); replay_one_transaction (fs, &cur); update_journal_header (bh, cur); control = cur; replayed ++; } reiserfs_warning (stderr, "%d transactions replayed\n", replayed); mark_buffer_dirty (fs->fs_super_bh); bwrite (fs->fs_super_bh); update_journal_header (bh, newest); return 0; } reiserfsprogs-3.6.9/reiserfscore/stree.c0000664000077100007710000003440207665645673014131 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ /* * Written by Anatoly P. Pinchuk pap@namesys.botik.ru * Programm System Institute * Pereslavl-Zalessky Russia */ /* * This file contains functions dealing with internal tree * * comp_keys * comp_short_keys * bin_search * get_lkey * get_rkey * key_in_buffer * decrement_bcount * decrement_counters_in_path * pathrelse * search_by_key * search_for_position_by_key * comp_items * prepare_for_delete_or_cut * calc_deleted_bytes_number * init_tb_struct * reiserfs_delete_item * indirect_to_direct * maybe_indirect_to_direct * reiserfs_cut_from_item * reiserfs_cut_dir_entry * reiserfs_paste_into_item * reiserfs_insert_item */ #include "includes.h" /* Does the buffer contain a disk block which is in the tree. */ inline int B_IS_IN_TREE (struct buffer_head * p_s_bh) { return ( get_blkh_level (B_BLK_HEAD (p_s_bh)) != FREE_LEVEL ); } /* Compare keys using REISERFS_SHORT_KEY_LEN fields. Returns: -1 if key1 < key2 0 if key1 = key2 1 if key1 > key2 */ int comp_short_keys (const void * k1, const void * k2) { int n_key_length = REISERFS_SHORT_KEY_LEN; __u32 * p_s_key1 = (__u32 *)k1; __u32 * p_s_key2 = (__u32 *)k2; __u32 u1, u2; for( ; n_key_length--; ++p_s_key1, ++p_s_key2 ) { u1 = le32_to_cpu(*p_s_key1) ; u2 = le32_to_cpu(*p_s_key2) ; if ( u1 < u2 ) return -1; if ( u1 > u2 ) return 1; } return 0; } int comp_keys_3 (const void * p1, const void * p2) { int retval; const struct key * k1 = p1; const struct key * k2 = p2; loff_t off1, off2; retval = comp_short_keys (k1, k2); if (retval) return retval; off1 = get_offset(k1) ; off2 = get_offset(k2) ; if (off1 < off2) return -1; if (off1 > off2) return 1; return 0; } /* Compare keys using all 4 key fields. Returns: -1 if key1 < key2 0 if key1 = key2 1 if key1 > key2 */ int comp_keys (const void * p1, const void * p2) { int retval; const struct key * k1 = p1; const struct key * k2 = p2; __u32 u1, u2; retval = comp_keys_3 (k1, k2); if (retval) return retval; u1 = get_type (k1); u2 = get_type (k2); if (u1 < u2) return -1; if (u1 > u2) return 1; return 0; } /************************************************************************** * Binary search toolkit function * * Search for an item in the array by the item key * * Returns: 1 if found, 0 if not found; * * *p_n_pos = number of the searched element if found, else the * * number of the first element that is larger than p_v_key. * **************************************************************************/ /* For those not familiar with binary search: n_lbound is the leftmost item that it could be, n_rbound the rightmost item that it could be. We examine the item halfway between n_lbound and n_rbound, and that tells us either that we can increase n_lbound, or decrease n_rbound, or that we have found it, or if n_lbound <= n_rbound that there are no possible items, and we have not found it. With each examination we cut the number of possible items it could be by one more than half rounded down, or we find it. */ inline int bin_search ( void * p_v_key, /* Key to search for. */ void * p_v_base, /* First item in the array. */ int p_n_num, /* Number of items in the array. */ int p_n_width, /* Item size in the array. searched. Lest the reader be confused, note that this is crafted as a general function, and when it is applied specifically to the array of item headers in a node, p_n_width is actually the item header size not the item size. */ int * p_n_pos /* Number of the searched for element. */ ) { int n_rbound, n_lbound, n_j; for ( n_j = ((n_rbound = p_n_num - 1) + (n_lbound = 0))/2; n_lbound <= n_rbound; n_j = (n_rbound + n_lbound)/2 ) switch( COMP_KEYS((struct key *)((char * )p_v_base + n_j * p_n_width), p_v_key) ) { case -1: n_lbound = n_j + 1; continue; case 1: n_rbound = n_j - 1; continue; case 0: *p_n_pos = n_j; return ITEM_FOUND; /* Key found in the array. */ } /* bin_search did not find given key, it returns position of key, that is minimal and greater than the given one. */ *p_n_pos = n_lbound; return ITEM_NOT_FOUND; } /* Minimal possible key. It is never in the tree. */ struct key MIN_KEY = {0, 0, {{0, 0},}}; /* Maximal possible key. It is never in the tree. */ struct key MAX_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; /* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom of the path, and going upwards. We must check the path's validity at each step. If the key is not in the path, there is no delimiting key in the tree (buffer is first or last buffer in tree), and in this case we return a special key, either MIN_KEY or MAX_KEY. */ struct key * get_lkey (struct path * p_s_chk_path, reiserfs_filsys_t * fs) { struct reiserfs_super_block * sb; int n_position, n_path_offset = p_s_chk_path->path_length; struct buffer_head * p_s_parent; sb = fs->fs_ondisk_sb; /* While not higher in path than first element. */ while ( n_path_offset-- > FIRST_PATH_ELEMENT_OFFSET ) { /* Parent at the path is not in the tree now. */ if ( ! B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)) ) return &MAX_KEY; /* Check whether position in the parent is correct. */ if ( (n_position = PATH_OFFSET_POSITION(p_s_chk_path, n_path_offset)) > B_NR_ITEMS(p_s_parent) ) return &MAX_KEY; /* Check whether parent at the path really points to the child. */ if ( get_dc_child_blocknr (B_N_CHILD (p_s_parent, n_position)) != PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset + 1)->b_blocknr ) return &MAX_KEY; /* Return delimiting key if position in the parent is not equal to zero. */ if ( n_position ) return B_N_PDELIM_KEY(p_s_parent, n_position - 1); } /* Return MIN_KEY if we are in the root of the buffer tree. */ if ( PATH_OFFSET_PBUFFER(p_s_chk_path, FIRST_PATH_ELEMENT_OFFSET)->b_blocknr == get_sb_root_block (sb) ) return &MIN_KEY; return &MAX_KEY; } /* Get delimiting key of the buffer at the path and its right neighbor. */ struct key * get_rkey (struct path * p_s_chk_path, reiserfs_filsys_t * fs) { struct reiserfs_super_block * sb; int n_position, n_path_offset = p_s_chk_path->path_length; struct buffer_head * p_s_parent; sb = fs->fs_ondisk_sb; while ( n_path_offset-- > FIRST_PATH_ELEMENT_OFFSET ) { /* Parent at the path is not in the tree now. */ if ( ! B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)) ) return &MIN_KEY; /* Check whether position in the parrent is correct. */ if ( (n_position = PATH_OFFSET_POSITION(p_s_chk_path, n_path_offset)) > B_NR_ITEMS(p_s_parent) ) return &MIN_KEY; /* Check whether parent at the path really points to the child. */ if ( get_dc_child_blocknr (B_N_CHILD (p_s_parent, n_position)) != PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset + 1)->b_blocknr ) return &MIN_KEY; /* Return delimiting key if position in the parent is not the last one. */ if ( n_position != B_NR_ITEMS(p_s_parent) ) return B_N_PDELIM_KEY(p_s_parent, n_position); } /* Return MAX_KEY if we are in the root of the buffer tree. */ if ( PATH_OFFSET_PBUFFER(p_s_chk_path, FIRST_PATH_ELEMENT_OFFSET)->b_blocknr == get_sb_root_block (sb) ) return &MAX_KEY; return &MIN_KEY; } /* Check whether a key is contained in the tree rooted from a buffer at a path. This works by looking at the left and right delimiting keys for the buffer in the last path_element in the path. These delimiting keys are stored at least one level above that buffer in the tree. If the buffer is the first or last node in the tree order then one of the delimiting keys may be absent, and in this case get_lkey and get_rkey return a special key which is MIN_KEY or MAX_KEY. */ static inline int key_in_buffer ( struct path * p_s_chk_path, /* Path which should be checked. */ struct key * p_s_key, /* Key which should be checked. */ reiserfs_filsys_t * fs /* Super block pointer. */ ) { if ( COMP_KEYS(get_lkey(p_s_chk_path, fs), p_s_key) == 1 ) return 0; if ( COMP_KEYS(p_s_key, get_rkey(p_s_chk_path, fs)) != -1 ) return 0; return 1; } /* Release all buffers in the path. */ void pathrelse (struct path * p_s_search_path) { int n_path_offset = p_s_search_path->path_length; while ( n_path_offset > ILLEGAL_PATH_ELEMENT_OFFSET ) brelse(PATH_OFFSET_PBUFFER(p_s_search_path, n_path_offset--)); p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET; } /************************************************************************** * Algorithm SearchByKey * * look for item in internal tree on the disk by its key * * Input: p_s_sb - super block * * p_s_key - pointer to the key to search * * Output: true value - 1 - found, 0 - not found * * p_s_search_path - path from the root to the needed leaf * **************************************************************************/ /* This function fills up the path from the root to the leaf as it descends the tree looking for the key. It uses reiserfs_bread to try to find buffers in the cache given their block number. If it does not find them in the cache it reads them from disk. For each node search_by_key finds using reiserfs_bread it then uses bin_search to look through that node. bin_search will find the position of the block_number of the next node if it is looking through an internal node. If it is looking through a leaf node bin_search will find the position of the item which has key either equal to given key, or which is the maximal key less than the given key. search_by_key returns a path that must be checked for the correctness of the top of the path but need not be checked for the correctness of the bottom of the path */ int search_by_key (reiserfs_filsys_t * fs, struct key * p_s_key, /* Key to search */ struct path * p_s_search_path,/* This structure was allocated and initialized by the calling function. It is filled up by this function. */ int n_stop_level) /* How far down the tree to search.*/ { struct reiserfs_super_block * sb; int n_block_number, expected_level, n_block_size = fs->fs_blocksize; struct buffer_head * p_s_bh; struct path_element * p_s_last_element; int n_retval; sb = fs->fs_ondisk_sb; n_block_number = get_sb_root_block (sb); expected_level = get_sb_tree_height (sb); /* As we add each node to a path we increase its count. This means that we must be careful to release all nodes in a path before we either discard the path struct or re-use the path struct, as we do here. */ pathrelse (p_s_search_path); /* With each iteration of this loop we search through the items in the current node, and calculate the next current node(next path element) for the next iteration of this loop.. */ while ( 1 ) { /* prep path to have another element added to it. */ p_s_last_element = PATH_OFFSET_PELEMENT(p_s_search_path, ++p_s_search_path->path_length); expected_level --; /* Read the next tree node, and set the last element in the path to have a pointer to it. */ if ( ! (p_s_bh = p_s_last_element->pe_buffer = bread (fs->fs_dev, n_block_number, n_block_size)) ) { p_s_search_path->path_length --; pathrelse(p_s_search_path); return IO_ERROR; } /* It is possible that schedule occured. We must check whether the key to search is still in the tree rooted from the current buffer. If not then repeat search from the root. */ if (!B_IS_IN_TREE (p_s_bh) || ! key_in_buffer(p_s_search_path, p_s_key, fs)) reiserfs_panic ("search_by_key: something wrong with the tree"); /* make sure, that the node contents look like a node of certain level */ if (!is_tree_node (p_s_bh, expected_level)) { print_block (stderr, 0, p_s_bh, 3, -1, -1); reiserfs_panic ("search_by_key: expected level %d", expected_level); } /* ok, we have acquired next formatted node in the tree */ n_retval = bin_search (p_s_key, B_N_PITEM_HEAD(p_s_bh, 0), B_NR_ITEMS(p_s_bh), is_leaf_node (p_s_bh) ? IH_SIZE : KEY_SIZE, &(p_s_last_element->pe_position)); if (get_blkh_level (B_BLK_HEAD (p_s_bh)) == n_stop_level) return n_retval; /* we are not in the stop level */ if (n_retval == ITEM_FOUND) /* item has been found, so we choose the pointer which is to the right of the found one */ p_s_last_element->pe_position++; /* if item was not found we choose the position which is to the left of the found item. This requires no code, bin_search did it already.*/ /* So we have chosen a position in the current node which is an internal node. Now we calculate child block number by position in the node. */ n_block_number = get_dc_child_blocknr (B_N_CHILD (p_s_bh, p_s_last_element->pe_position)); } } int bin_search_in_dir_item (struct item_head * ih, struct reiserfs_de_head * deh, struct key * key, int * pos_in_item) { int rbound, lbound, j; lbound = 0; rbound = get_ih_entry_count (ih) - 1; for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) { if (get_offset (key) < get_deh_offset (deh + j)) { rbound = j - 1; continue; } if (get_offset (key) > get_deh_offset (deh + j)) { lbound = j + 1; continue; } /* key found */ *pos_in_item = j; return POSITION_FOUND; } *pos_in_item = lbound; return POSITION_NOT_FOUND; } reiserfsprogs-3.6.9/reiserfscore/hashes.c0000664000077100007710000001036407665645673014263 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ /* * Keyed 32-bit hash function using TEA in a Davis-Meyer function * H0 = Key * Hi = E Mi(Hi-1) + Hi-1 * * (see Applied Cryptography, 2nd edition, p448). * * Jeremy Fitzhardinge 1998 * * Jeremy has agreed to the contents of reiserfs/README. -Hans * Yura's function is added (04/07/2000) */ // // keyed_hash // yura_hash // r5 // #include #define DELTA 0x9E3779B9 #define FULLROUNDS 10 /* 32 is overkill, 16 is strong crypto */ #define PARTROUNDS 6 /* 6 gets complete mixing */ #ifndef __KERNEL__ typedef __u32 u32; #endif /* a, b, c, d - data; h0, h1 - accumulated hash */ #define TEACORE(rounds) \ do { \ u32 sum = 0; \ int n = rounds; \ u32 b0, b1; \ \ b0 = h0; \ b1 = h1; \ \ do \ { \ sum += DELTA; \ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); \ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); \ } while(--n); \ \ h0 += b0; \ h1 += b1; \ } while(0) u32 keyed_hash(const signed char *msg, int len) { u32 k[] = { 0x9464a485, 0x542e1a94, 0x3e846bff, 0xb75bcfc3}; u32 h0 = k[0], h1 = k[1]; u32 a, b, c, d; u32 pad; int i; pad = (u32)len | ((u32)len << 8); pad |= pad << 16; while(len >= 16) { a = (u32)msg[ 0] | (u32)msg[ 1] << 8 | (u32)msg[ 2] << 16| (u32)msg[ 3] << 24; b = (u32)msg[ 4] | (u32)msg[ 5] << 8 | (u32)msg[ 6] << 16| (u32)msg[ 7] << 24; c = (u32)msg[ 8] | (u32)msg[ 9] << 8 | (u32)msg[10] << 16| (u32)msg[11] << 24; d = (u32)msg[12] | (u32)msg[13] << 8 | (u32)msg[14] << 16| (u32)msg[15] << 24; TEACORE(PARTROUNDS); len -= 16; msg += 16; } if (len >= 12) { if (len >= 16) *(int *)0 = 0; a = (u32)msg[ 0] | (u32)msg[ 1] << 8 | (u32)msg[ 2] << 16| (u32)msg[ 3] << 24; b = (u32)msg[ 4] | (u32)msg[ 5] << 8 | (u32)msg[ 6] << 16| (u32)msg[ 7] << 24; c = (u32)msg[ 8] | (u32)msg[ 9] << 8 | (u32)msg[10] << 16| (u32)msg[11] << 24; d = pad; for(i = 12; i < len; i++) { d <<= 8; d |= msg[i]; } } else if (len >= 8) { if (len >= 12) *(int *)0 = 0; a = (u32)msg[ 0] | (u32)msg[ 1] << 8 | (u32)msg[ 2] << 16| (u32)msg[ 3] << 24; b = (u32)msg[ 4] | (u32)msg[ 5] << 8 | (u32)msg[ 6] << 16| (u32)msg[ 7] << 24; c = d = pad; for(i = 8; i < len; i++) { c <<= 8; c |= msg[i]; } } else if (len >= 4) { if (len >= 8) *(int *)0 = 0; a = (u32)msg[ 0] | (u32)msg[ 1] << 8 | (u32)msg[ 2] << 16| (u32)msg[ 3] << 24; b = c = d = pad; for(i = 4; i < len; i++) { b <<= 8; b |= msg[i]; } } else { if (len >= 4) *(int *)0 = 0; a = b = c = d = pad; for(i = 0; i < len; i++) { a <<= 8; a |= msg[i]; } } TEACORE(FULLROUNDS); return h0^h1; } u32 yura_hash (const signed char *msg, int len) { int j, pow; u32 a, c; int i; for (pow=1,i=1; i < len; i++) pow = pow * 10; if (len == 1) a = msg[0]-48; else a = (msg[0] - 48) * pow; for (i=1; i < len; i++) { c = msg[i] - 48; for (pow=1,j=i; j < len-1; j++) pow = pow * 10; a = a + c * pow; } for (; i < 40; i++) { c = '0' - 48; for (pow=1,j=i; j < len-1; j++) pow = pow * 10; a = a + c * pow; } for (; i < 256; i++) { c = i; for (pow=1,j=i; j < len-1; j++) pow = pow * 10; a = a + c * pow; } a = a << 7; return a; } u32 r5_hash (const signed char *msg, int len) { u32 a=0; int i; for (i = 0; i < len; i ++) { a += msg[i] << 4; a += msg[i] >> 4; a *= 11; } return a; } #if 0 #include int main (void) { char * name = 0; size_t n = 0; while (1) { getline (&name, &n, stdin); if (!strcmp (name, "\n")) break; name [strlen (name) - 1] = 0; printf ("tea %lu\n, r5 %lu\nyura %lu\n", keyed_hash (name, strlen (name)) & 0x7fffff80, r5_hash (name, strlen (name)) & 0x7fffff80, yura_hash (name, strlen (name)) & 0x7fffff80); free (name); name = 0; n = 0; } } #endif reiserfsprogs-3.6.9/reiserfscore/Makefile.am0000664000077100007710000000026607665645673014700 noinst_LIBRARIES = libcore.a libcore_a_SOURCES = do_balan.c fix_node.c hashes.c ibalance.c lbalance.c prints.c \ stree.c node_formats.c reiserfslib.c bitmap.c journal.c includes.h reiserfsprogs-3.6.9/reiserfscore/Makefile.in0000644000077100007710000002735007705315225014670 # Makefile.in generated by automake 1.7.2 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__quote = @am__quote@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ noinst_LIBRARIES = libcore.a libcore_a_SOURCES = do_balan.c fix_node.c hashes.c ibalance.c lbalance.c prints.c \ stree.c node_formats.c reiserfslib.c bitmap.c journal.c includes.h subdir = reiserfscore mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) libcore_a_AR = $(AR) cru libcore_a_LIBADD = am_libcore_a_OBJECTS = do_balan.$(OBJEXT) fix_node.$(OBJEXT) \ hashes.$(OBJEXT) ibalance.$(OBJEXT) lbalance.$(OBJEXT) \ prints.$(OBJEXT) stree.$(OBJEXT) node_formats.$(OBJEXT) \ reiserfslib.$(OBJEXT) bitmap.$(OBJEXT) journal.$(OBJEXT) libcore_a_OBJECTS = $(am_libcore_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/bitmap.Po ./$(DEPDIR)/do_balan.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/fix_node.Po ./$(DEPDIR)/hashes.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/ibalance.Po ./$(DEPDIR)/journal.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/lbalance.Po ./$(DEPDIR)/node_formats.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/prints.Po ./$(DEPDIR)/reiserfslib.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/stree.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libcore_a_SOURCES) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(libcore_a_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu reiserfscore/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) AR = ar clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libcore.a: $(libcore_a_OBJECTS) $(libcore_a_DEPENDENCIES) -rm -f libcore.a $(libcore_a_AR) libcore.a $(libcore_a_OBJECTS) $(libcore_a_LIBADD) $(RANLIB) libcore.a mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitmap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/do_balan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fix_node.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hashes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ibalance.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/journal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lbalance.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node_formats.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prints.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reiserfslib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stree.Po@am__quote@ distclean-depend: -rm -rf ./$(DEPDIR) .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ distclean-depend distclean-generic distclean-tags distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: reiserfsprogs-3.6.9/reiserfscore/ibalance.c0000664000077100007710000007345407665645673014557 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "includes.h" /* this is one and only function that is used outside (do_balance.c) */ int balance_internal ( /*struct reiserfs_transaction_handle *th,*/ struct tree_balance * , int, int, struct item_head * , struct buffer_head ** ); /* modes of internal_shift_left, internal_shift_right and internal_insert_childs */ #define INTERNAL_SHIFT_FROM_S_TO_L 0 #define INTERNAL_SHIFT_FROM_R_TO_S 1 #define INTERNAL_SHIFT_FROM_L_TO_S 2 #define INTERNAL_SHIFT_FROM_S_TO_R 3 #define INTERNAL_INSERT_TO_S 4 #define INTERNAL_INSERT_TO_L 5 #define INTERNAL_INSERT_TO_R 6 static void internal_define_dest_src_infos ( int shift_mode, struct tree_balance * tb, int h, struct buffer_info * dest_bi, struct buffer_info * src_bi, int * d_key, struct buffer_head ** cf ) { /* define dest, src, dest parent, dest position */ switch (shift_mode) { case INTERNAL_SHIFT_FROM_S_TO_L: /* used in internal_shift_left */ src_bi->bi_bh = PATH_H_PBUFFER (tb->tb_path, h); src_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, h); src_bi->bi_position = PATH_H_POSITION (tb->tb_path, h + 1); dest_bi->bi_bh = tb->L[h]; dest_bi->bi_parent = tb->FL[h]; dest_bi->bi_position = get_left_neighbor_position (tb, h); *d_key = tb->lkey[h]; *cf = tb->CFL[h]; break; case INTERNAL_SHIFT_FROM_L_TO_S: src_bi->bi_bh = tb->L[h]; src_bi->bi_parent = tb->FL[h]; src_bi->bi_position = get_left_neighbor_position (tb, h); dest_bi->bi_bh = PATH_H_PBUFFER (tb->tb_path, h); dest_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, h); dest_bi->bi_position = PATH_H_POSITION (tb->tb_path, h + 1); /* dest position is analog of dest->b_item_order */ *d_key = tb->lkey[h]; *cf = tb->CFL[h]; break; case INTERNAL_SHIFT_FROM_R_TO_S: /* used in internal_shift_left */ src_bi->bi_bh = tb->R[h]; src_bi->bi_parent = tb->FR[h]; src_bi->bi_position = get_right_neighbor_position (tb, h); dest_bi->bi_bh = PATH_H_PBUFFER (tb->tb_path, h); dest_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, h); dest_bi->bi_position = PATH_H_POSITION (tb->tb_path, h + 1); *d_key = tb->rkey[h]; *cf = tb->CFR[h]; break; case INTERNAL_SHIFT_FROM_S_TO_R: src_bi->bi_bh = PATH_H_PBUFFER (tb->tb_path, h); src_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, h); src_bi->bi_position = PATH_H_POSITION (tb->tb_path, h + 1); dest_bi->bi_bh = tb->R[h]; dest_bi->bi_parent = tb->FR[h]; dest_bi->bi_position = get_right_neighbor_position (tb, h); *d_key = tb->rkey[h]; *cf = tb->CFR[h]; break; case INTERNAL_INSERT_TO_L: dest_bi->bi_bh = tb->L[h]; dest_bi->bi_parent = tb->FL[h]; dest_bi->bi_position = get_left_neighbor_position (tb, h); break; case INTERNAL_INSERT_TO_S: dest_bi->bi_bh = PATH_H_PBUFFER (tb->tb_path, h); dest_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, h); dest_bi->bi_position = PATH_H_POSITION (tb->tb_path, h + 1); break; case INTERNAL_INSERT_TO_R: dest_bi->bi_bh = tb->R[h]; dest_bi->bi_parent = tb->FR[h]; dest_bi->bi_position = get_right_neighbor_position (tb, h); break; default: reiserfs_panic ("internal_define_dest_src_infos", "shift type is unknown (%d)", shift_mode); } } /* Insert 'count' node pointers into buffer cur before position 'to' + 1. * Insert count items into buffer cur before position to. * Items and node pointers are specified by inserted and bh respectively. */ static void internal_insert_childs (reiserfs_filsys_t * fs, struct buffer_info * cur_bi, int to, int count, struct item_head * inserted, struct buffer_head ** bh) { struct buffer_head * cur = cur_bi->bi_bh; struct block_head * blkh; int nr; struct key * key; struct disk_child new_dc[2]; struct disk_child * dc; int i; int from; if (count <= 0) return; blkh = B_BLK_HEAD (cur); nr = get_blkh_nr_items (blkh); /* prepare space for count disk_child */ dc = B_N_CHILD (cur,to+1); memmove (dc + count, dc, (nr+1-(to+1)) * DC_SIZE); /* make disk child array for insertion */ for (i = 0; i < count; i ++) { set_dc_child_size (new_dc + i, MAX_CHILD_SIZE(bh[i]->b_size) - get_blkh_free_space (B_BLK_HEAD (bh[i]))); set_dc_child_blocknr (new_dc + i, bh[i]->b_blocknr); } memcpy (dc, new_dc, DC_SIZE * count); /* prepare space for 'count' items */ from = ((to == -1) ? 0 : to); key = B_N_PDELIM_KEY (cur, from); memmove (key + count, key, (nr - from/*to*/) * KEY_SIZE + (nr + 1 + count) * DC_SIZE); /* copy keys */ memcpy (key, inserted, KEY_SIZE); if ( count > 1 ) memcpy (key + 1, inserted + 1, KEY_SIZE); /* sizes, item number */ set_blkh_nr_items (blkh, nr + count); set_blkh_free_space (blkh, get_blkh_free_space (blkh) - count * (DC_SIZE + KEY_SIZE)); mark_buffer_dirty (cur); if (cur_bi->bi_parent) { dc = B_N_CHILD (cur_bi->bi_parent,cur_bi->bi_position); set_dc_child_size (dc, get_dc_child_size (dc) + count * (DC_SIZE + KEY_SIZE)); mark_buffer_dirty (cur_bi->bi_parent); } } /* Delete del_num items and node pointers from buffer cur starting from * * the first_i'th item and first_p'th pointers respectively. */ static void internal_delete_pointers_items (reiserfs_filsys_t * fs, struct buffer_info * cur_bi, int first_p, int first_i, int del_num) { struct buffer_head * cur = cur_bi->bi_bh; int nr; struct block_head * blkh; struct key * key; struct disk_child * dc; if ( del_num == 0 ) return; blkh = B_BLK_HEAD(cur); nr = get_blkh_nr_items (blkh); if ( first_p == 0 && del_num == nr + 1 ) { make_empty_node (cur_bi); return; } /* deleting */ dc = B_N_CHILD (cur, first_p); memmove (dc, dc + del_num, (nr + 1 - first_p - del_num) * DC_SIZE); key = B_N_PDELIM_KEY (cur, first_i); memmove (key, key + del_num, (nr - first_i - del_num) * KEY_SIZE + (nr + 1 - del_num) * DC_SIZE); /* sizes, item number */ set_blkh_nr_items (blkh, get_blkh_nr_items (blkh) - del_num); set_blkh_free_space (blkh, get_blkh_free_space (blkh) + del_num * (KEY_SIZE + DC_SIZE)); mark_buffer_dirty (cur); if (cur_bi->bi_parent) { dc = B_N_CHILD (cur_bi->bi_parent, cur_bi->bi_position); set_dc_child_size (dc, get_dc_child_size (dc) - del_num * (KEY_SIZE + DC_SIZE)); mark_buffer_dirty (cur_bi->bi_parent); } } /* delete n node pointers and items starting from given position */ static void internal_delete_childs (reiserfs_filsys_t * fs, struct buffer_info * cur_bi, int from, int n) { int i_from; i_from = (from == 0) ? from : from - 1; /* delete n pointers starting from `from' position in CUR; delete n keys starting from 'i_from' position in CUR; */ internal_delete_pointers_items (fs, cur_bi, from, i_from, n); } /* copy cpy_num node pointers and cpy_num - 1 items from buffer src to buffer dest * last_first == FIRST_TO_LAST means, that we copy first items from src to tail of dest * last_first == LAST_TO_FIRST means, that we copy last items from src to head of dest */ static void internal_copy_pointers_items (reiserfs_filsys_t * fs, struct buffer_info * dest_bi, struct buffer_head * src, int last_first, int cpy_num) { /* ATTENTION! Number of node pointers in DEST is equal to number of items in DEST * * as delimiting key have already inserted to buffer dest.*/ struct buffer_head * dest = dest_bi->bi_bh; int nr_dest, nr_src; int dest_order, src_order; struct block_head * blkh; struct key * key; struct disk_child * dc; nr_src = B_NR_ITEMS (src); if ( cpy_num == 0 ) return; /* coping */ blkh = B_BLK_HEAD (dest); nr_dest = get_blkh_nr_items (blkh); /*dest_order = (last_first == LAST_TO_FIRST) ? 0 : nr_dest;*/ /*src_order = (last_first == LAST_TO_FIRST) ? (nr_src - cpy_num + 1) : 0;*/ (last_first == LAST_TO_FIRST) ? (dest_order = 0, src_order = nr_src - cpy_num + 1) : (dest_order = nr_dest, src_order = 0); /* prepare space for cpy_num pointers */ dc = B_N_CHILD (dest, dest_order); memmove (dc + cpy_num, dc, (nr_dest - dest_order) * DC_SIZE); /* insert pointers */ memcpy (dc, B_N_CHILD (src, src_order), DC_SIZE * cpy_num); /* prepare space for cpy_num - 1 item headers */ key = B_N_PDELIM_KEY(dest, dest_order); memmove (key + cpy_num - 1, key, KEY_SIZE * (nr_dest - dest_order) + DC_SIZE * (nr_dest + cpy_num)); /* insert headers */ memcpy (key, B_N_PDELIM_KEY (src, src_order), KEY_SIZE * (cpy_num - 1)); /* sizes, item number */ set_blkh_nr_items (blkh, get_blkh_nr_items (blkh) + cpy_num - 1); set_blkh_free_space (blkh, get_blkh_free_space (blkh) - (KEY_SIZE * (cpy_num - 1) + DC_SIZE * cpy_num)); mark_buffer_dirty (dest); if (dest_bi->bi_parent) { dc = B_N_CHILD(dest_bi->bi_parent,dest_bi->bi_position); set_dc_child_size (dc, get_dc_child_size (dc) + KEY_SIZE * (cpy_num - 1) + DC_SIZE * cpy_num); mark_buffer_dirty (dest_bi->bi_parent); } } /* Copy cpy_num node pointers and cpy_num - 1 items from buffer src to buffer dest. * Delete cpy_num - del_par items and node pointers from buffer src. * last_first == FIRST_TO_LAST means, that we copy/delete first items from src. * last_first == LAST_TO_FIRST means, that we copy/delete last items from src. */ static void internal_move_pointers_items (reiserfs_filsys_t * fs, struct buffer_info * dest_bi, struct buffer_info * src_bi, int last_first, int cpy_num, int del_par) { int first_pointer; int first_item; internal_copy_pointers_items (fs, dest_bi, src_bi->bi_bh, last_first, cpy_num); if (last_first == FIRST_TO_LAST) { /* shift_left occurs */ first_pointer = 0; first_item = 0; /* delete cpy_num - del_par pointers and keys starting for pointers with first_pointer, for key - with first_item */ internal_delete_pointers_items (fs, src_bi, first_pointer, first_item, cpy_num - del_par); } else { /* shift_right occurs */ int i, j; i = ( cpy_num - del_par == ( j = B_NR_ITEMS(src_bi->bi_bh)) + 1 ) ? 0 : j - cpy_num + del_par; internal_delete_pointers_items (fs, src_bi, j + 1 - cpy_num + del_par, i, cpy_num - del_par); } } /* Insert n_src'th key of buffer src before n_dest'th key of buffer dest. */ static void internal_insert_key (reiserfs_filsys_t * fs, struct buffer_info * dest_bi, int dest_position_before, /* insert key before key with n_dest number */ struct buffer_head * src, int src_position ) { struct buffer_head * dest = dest_bi->bi_bh; int nr; struct block_head * blkh; struct key * key; blkh = B_BLK_HEAD(dest); nr = get_blkh_nr_items (blkh); /* prepare space for inserting key */ key = B_N_PDELIM_KEY (dest, dest_position_before); memmove (key + 1, key, (nr - dest_position_before) * KEY_SIZE + (nr + 1) * DC_SIZE); /* insert key */ memcpy (key, B_N_PDELIM_KEY(src, src_position), KEY_SIZE); /* Change dirt, free space, item number fields. */ set_blkh_nr_items (blkh, get_blkh_nr_items (blkh) + 1); set_blkh_free_space (blkh, get_blkh_free_space (blkh) - KEY_SIZE); mark_buffer_dirty (dest); if (dest_bi->bi_parent) { struct disk_child * dc; dc = B_N_CHILD(dest_bi->bi_parent,dest_bi->bi_position); set_dc_child_size (dc, get_dc_child_size (dc) + KEY_SIZE); mark_buffer_dirty (dest_bi->bi_parent); } } /* Insert d_key'th (delimiting) key from buffer cfl to tail of dest. * Copy pointer_amount node pointers and pointer_amount - 1 items from buffer src to buffer dest. * Replace d_key'th key in buffer cfl. * Delete pointer_amount items and node pointers from buffer src. */ /* this can be invoked both to shift from S to L and from R to S */ static void internal_shift_left (int mode, /* INTERNAL_FROM_S_TO_L | INTERNAL_FROM_R_TO_S */ struct tree_balance * tb, int h, int pointer_amount) { struct buffer_info dest_bi, src_bi; struct buffer_head * cf; int d_key_position; internal_define_dest_src_infos (mode, tb, h, &dest_bi, &src_bi, &d_key_position, &cf); /*printk("pointer_amount = %d\n",pointer_amount);*/ if (pointer_amount) { /* insert delimiting key from common father of dest and src to node dest into position B_NR_ITEM(dest) */ internal_insert_key (tb->tb_fs, &dest_bi, B_NR_ITEMS(dest_bi.bi_bh), cf, d_key_position); if (B_NR_ITEMS(src_bi.bi_bh) == pointer_amount - 1) { if (src_bi.bi_position/*src->b_item_order*/ == 0) replace_key (tb->tb_fs, cf, d_key_position, src_bi.bi_parent/*src->b_parent*/, 0); } else replace_key (tb->tb_fs, cf, d_key_position, src_bi.bi_bh, pointer_amount - 1); } /* last parameter is del_parameter */ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, FIRST_TO_LAST, pointer_amount, 0); } /* Insert delimiting key to L[h]. * Copy n node pointers and n - 1 items from buffer S[h] to L[h]. * Delete n - 1 items and node pointers from buffer S[h]. */ /* it always shifts from S[h] to L[h] */ static void internal_shift1_left (struct tree_balance * tb, int h, int pointer_amount) { struct buffer_info dest_bi, src_bi; struct buffer_head * cf; int d_key_position; internal_define_dest_src_infos (INTERNAL_SHIFT_FROM_S_TO_L, tb, h, &dest_bi, &src_bi, &d_key_position, &cf); if ( pointer_amount > 0 ) /* insert lkey[h]-th key from CFL[h] to left neighbor L[h] */ internal_insert_key (tb->tb_fs, &dest_bi, B_NR_ITEMS(dest_bi.bi_bh), cf, d_key_position); /* last parameter is del_parameter */ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, FIRST_TO_LAST, pointer_amount, 1); } /* Insert d_key'th (delimiting) key from buffer cfr to head of dest. * Copy n node pointers and n - 1 items from buffer src to buffer dest. * Replace d_key'th key in buffer cfr. * Delete n items and node pointers from buffer src. */ static void internal_shift_right (int mode, /* INTERNAL_FROM_S_TO_R | INTERNAL_FROM_L_TO_S */ struct tree_balance * tb, int h, int pointer_amount) { struct buffer_info dest_bi, src_bi; struct buffer_head * cf; int d_key_position; int nr; internal_define_dest_src_infos (mode, tb, h, &dest_bi, &src_bi, &d_key_position, &cf); nr = B_NR_ITEMS (src_bi.bi_bh); if (pointer_amount > 0) { /* insert delimiting key from common father of dest and src to dest node into position 0 */ internal_insert_key (tb->tb_fs, &dest_bi, 0, cf, d_key_position); if (nr == pointer_amount - 1) { /* when S[h] disappers replace left delemiting key as well */ if (tb->CFL[h]) replace_key(tb->tb_fs, cf, d_key_position, tb->CFL[h], tb->lkey[h]); } else replace_key(tb->tb_fs, cf, d_key_position, src_bi.bi_bh, nr - pointer_amount); } /* last parameter is del_parameter */ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, LAST_TO_FIRST, pointer_amount, 0); } /* Insert delimiting key to R[h]. * Copy n node pointers and n - 1 items from buffer S[h] to R[h]. * Delete n - 1 items and node pointers from buffer S[h]. */ /* it always shift from S[h] to R[h] */ static void internal_shift1_right (struct tree_balance * tb, int h, int pointer_amount) { struct buffer_info dest_bi, src_bi; struct buffer_head * cf; int d_key_position; internal_define_dest_src_infos (INTERNAL_SHIFT_FROM_S_TO_R, tb, h, &dest_bi, &src_bi, &d_key_position, &cf); if (pointer_amount > 0) /* insert rkey from CFR[h] to right neighbor R[h] */ internal_insert_key (tb->tb_fs, &dest_bi, 0, cf, d_key_position); /* last parameter is del_parameter */ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, LAST_TO_FIRST, pointer_amount, 1); } /* Delete insert_num node pointers together with their left items * and balance current node.*/ static void balance_internal_when_delete (struct tree_balance * tb, int h, int child_pos) { int insert_num; int n; struct buffer_head * tbSh = PATH_H_PBUFFER (tb->tb_path, h); struct buffer_info bi; insert_num = tb->insert_size[h] / ((int)(DC_SIZE + KEY_SIZE)); /* delete child-node-pointer(s) together with their left item(s) */ bi.bi_bh = tbSh; bi.bi_parent = PATH_H_PPARENT (tb->tb_path, h); bi.bi_position = PATH_H_POSITION (tb->tb_path, h + 1); internal_delete_childs (tb->tb_fs, &bi, child_pos, -insert_num); n = B_NR_ITEMS(tbSh); if ( tb->lnum[h] == 0 && tb->rnum[h] == 0 ) { if ( tb->blknum[h] == 0 ) { /* node S[h] (root of the tree) is empty now */ struct buffer_head *new_root; struct reiserfs_super_block * sb; /* choose a new root */ if ( ! tb->L[h-1] || ! B_NR_ITEMS(tb->L[h-1]) ) new_root = tb->R[h-1]; else new_root = tb->L[h-1]; /* update super block's tree height and pointer to a root block */ sb = tb->tb_fs->fs_ondisk_sb; set_sb_root_block (sb, new_root->b_blocknr); set_sb_tree_height (sb, get_sb_tree_height (sb) - 1); mark_buffer_dirty (tb->tb_fs->fs_super_bh); tb->tb_fs->fs_dirt = 1; /* mark buffer S[h] not uptodate and put it in free list */ reiserfs_invalidate_buffer(tb, tbSh, 1); return; } return; } if ( tb->L[h] && tb->lnum[h] == -B_NR_ITEMS(tb->L[h]) - 1 ) { /* join S[h] with L[h] */ internal_shift_left (INTERNAL_SHIFT_FROM_S_TO_L, tb, h, n + 1);/*tb->L[h], tb->CFL[h], tb->lkey[h], tb->S[h], n+1);*/ reiserfs_invalidate_buffer(tb, tbSh, 1); /* preserve not needed, internal, 1 mean free block */ return; } if ( tb->R[h] && tb->rnum[h] == -B_NR_ITEMS(tb->R[h]) - 1 ) { /* join S[h] with R[h] */ internal_shift_right (INTERNAL_SHIFT_FROM_S_TO_R, tb, h, n + 1); reiserfs_invalidate_buffer (tb, tbSh, 1); return; } if ( tb->lnum[h] < 0 ) { /* borrow from left neighbor L[h] */ internal_shift_right (INTERNAL_SHIFT_FROM_L_TO_S, tb, h, -tb->lnum[h]); return; } if ( tb->rnum[h] < 0 ) { /* borrow from right neighbor R[h] */ internal_shift_left (INTERNAL_SHIFT_FROM_R_TO_S, tb, h, -tb->rnum[h]);/*tb->S[h], tb->CFR[h], tb->rkey[h], tb->R[h], -tb->rnum[h]);*/ return; } if ( tb->lnum[h] > 0 ) { /* split S[h] into two parts and put them into neighbors */ internal_shift_left (INTERNAL_SHIFT_FROM_S_TO_L, tb, h, tb->lnum[h]);/*tb->L[h], tb->CFL[h], tb->lkey[h], tb->S[h], tb->lnum[h]);*/ internal_shift_right (INTERNAL_SHIFT_FROM_S_TO_R, tb, h, tb->rnum[h]); reiserfs_invalidate_buffer (tb, tbSh, 1); return; } reiserfs_panic ("balance_internal_when_delete", "unexpected tb->lnum[%d]==%d or tb->rnum[%d]==%d", h, tb->lnum[h], h, tb->rnum[h]); } /* Replace delimiting key of buffers L[h] and S[h] by the given key.*/ void replace_lkey (struct tree_balance * tb, int h, struct item_head * key) { if (B_NR_ITEMS(PATH_H_PBUFFER(tb->tb_path, h)) == 0) return; memcpy (B_N_PDELIM_KEY(tb->CFL[h],tb->lkey[h]), key, KEY_SIZE); mark_buffer_dirty (tb->CFL[h]); } /* Replace delimiting key of buffers S[h] and R[h] by the given key.*/ void replace_rkey (struct tree_balance * tb, int h, struct item_head * key) { memcpy (B_N_PDELIM_KEY(tb->CFR[h],tb->rkey[h]), key, KEY_SIZE); mark_buffer_dirty (tb->CFR[h]); } int balance_internal (struct tree_balance * tb, /* tree_balance structure */ int h, /* level of the tree */ int child_pos, struct item_head * insert_key, /* key for insertion on higher level */ struct buffer_head ** insert_ptr) /* node for insertion on higher level*/ /* if inserting/pasting { child_pos is the position of the node-pointer in S[h] that * pointed to S[h-1] before balancing of the h-1 level; * this means that new pointers and items must be inserted AFTER * child_pos } else { it is the position of the leftmost pointer that must be deleted (together with its corresponding key to the left of the pointer) as a result of the previous level's balancing. } */ { struct buffer_head * tbSh = PATH_H_PBUFFER (tb->tb_path, h); struct buffer_info bi; int order; /* we return this: it is 0 if there is no S[h], else it is tb->S[h]->b_item_order */ int insert_num, n, k; struct buffer_head * S_new; struct item_head new_insert_key; struct buffer_head * new_insert_ptr = NULL; struct item_head * new_insert_key_addr = insert_key; order = ( tbSh ) ? PATH_H_POSITION (tb->tb_path, h + 1)/*tb->S[h]->b_item_order*/ : 0; /* Using insert_size[h] calculate the number insert_num of items that must be inserted to or deleted from S[h]. */ insert_num = tb->insert_size[h]/((int)(KEY_SIZE + DC_SIZE)); /* Check whether insert_num is proper **/ /* Make balance in case insert_num < 0 */ if ( insert_num < 0 ) { balance_internal_when_delete (tb, h, child_pos); return order; } k = 0; if ( tb->lnum[h] > 0 ) { /* shift lnum[h] items from S[h] to the left neighbor L[h]. check how many of new items fall into L[h] or CFL[h] after shifting */ n = get_blkh_nr_items (B_BLK_HEAD(tb->L[h])); /* number of items in L[h] */ if ( tb->lnum[h] <= child_pos ) { /* new items don't fall into L[h] or CFL[h] */ internal_shift_left (INTERNAL_SHIFT_FROM_S_TO_L, tb, h, tb->lnum[h]); child_pos -= tb->lnum[h]; } else if ( tb->lnum[h] > child_pos + insert_num ) { /* all new items fall into L[h] */ internal_shift_left (INTERNAL_SHIFT_FROM_S_TO_L, tb, h, tb->lnum[h] - insert_num); /* insert insert_num keys and node-pointers into L[h] */ bi.bi_bh = tb->L[h]; bi.bi_parent = tb->FL[h]; bi.bi_position = get_left_neighbor_position (tb, h); internal_insert_childs (tb->tb_fs, &bi,/*tb->L[h], tb->S[h-1]->b_next*/ n + child_pos + 1, insert_num,insert_key,insert_ptr); insert_num = 0; } else { struct disk_child * dc; /* some items fall into L[h] or CFL[h], but some don't fall */ internal_shift1_left (tb, h, child_pos + 1); /* calculate number of new items that fall into L[h] */ k = tb->lnum[h] - child_pos - 1; bi.bi_bh = tb->L[h]; bi.bi_parent = tb->FL[h]; bi.bi_position = get_left_neighbor_position (tb, h); internal_insert_childs (tb->tb_fs, &bi,/*tb->L[h], tb->S[h-1]->b_next,*/ n + child_pos + 1,k, insert_key,insert_ptr); replace_lkey(tb, h, insert_key + k); /* replace the first node-ptr in S[h] by node-ptr to insert_ptr[k] */ dc = B_N_CHILD(tbSh, 0); set_dc_child_size (dc, MAX_CHILD_SIZE(insert_ptr[k]->b_size) - get_blkh_free_space (B_BLK_HEAD(insert_ptr[k]))); set_dc_child_blocknr (dc, insert_ptr[k]->b_blocknr); mark_buffer_dirty (tbSh); k++; insert_key += k; insert_ptr += k; insert_num -= k; child_pos = 0; } } /* tb->lnum[h] > 0 */ if ( tb->rnum[h] > 0 ) { /*shift rnum[h] items from S[h] to the right neighbor R[h]*/ /* check how many of new items fall into R or CFR after shifting */ n = get_blkh_nr_items (B_BLK_HEAD (tbSh)); /* number of items in S[h] */ if ( n - tb->rnum[h] >= child_pos ) /* new items fall into S[h] */ /*internal_shift_right(tb,h,tbSh,tb->CFR[h],tb->rkey[h],tb->R[h],tb->rnum[h]);*/ internal_shift_right (INTERNAL_SHIFT_FROM_S_TO_R, tb, h, tb->rnum[h]); else if ( n + insert_num - tb->rnum[h] < child_pos ) { /* all new items fall into R[h] */ internal_shift_right (INTERNAL_SHIFT_FROM_S_TO_R, tb, h, tb->rnum[h] - insert_num); /* insert insert_num keys and node-pointers into R[h] */ bi.bi_bh = tb->R[h]; bi.bi_parent = tb->FR[h]; bi.bi_position = get_right_neighbor_position (tb, h); internal_insert_childs (tb->tb_fs, &bi, /*tb->R[h],tb->S[h-1]->b_next*/ child_pos - n - insert_num + tb->rnum[h] - 1, insert_num,insert_key,insert_ptr); insert_num = 0; } else { struct disk_child * dc; /* one of the items falls into CFR[h] */ internal_shift1_right(tb, h, n - child_pos + 1); /* calculate number of new items that fall into R[h] */ k = tb->rnum[h] - n + child_pos - 1; bi.bi_bh = tb->R[h]; bi.bi_parent = tb->FR[h]; bi.bi_position = get_right_neighbor_position (tb, h); internal_insert_childs (tb->tb_fs, &bi, /*tb->R[h], tb->R[h]->b_child,*/ 0, k, insert_key + 1, insert_ptr + 1); replace_rkey(tb, h, insert_key + insert_num - k - 1); /* replace the first node-ptr in R[h] by node-ptr insert_ptr[insert_num-k-1]*/ dc = B_N_CHILD(tb->R[h], 0); set_dc_child_size (dc, MAX_CHILD_SIZE(insert_ptr[insert_num-k-1]->b_size) - get_blkh_free_space (B_BLK_HEAD(insert_ptr[insert_num-k-1]))); set_dc_child_blocknr (dc, insert_ptr[insert_num-k-1]->b_blocknr); mark_buffer_dirty (tb->R[h]); insert_num -= (k + 1); } } /** Fill new node that appears instead of S[h] **/ if ( ! tb->blknum[h] ) { /* node S[h] is empty now */ /* Mark buffer as invalid and put it to head of free list. */ reiserfs_invalidate_buffer(tb, tbSh, 1);/* do not preserve, internal node*/ return order; } if ( ! tbSh ) { /* create new root */ struct disk_child * dc; struct buffer_head * tbSh_1 = PATH_H_PBUFFER (tb->tb_path, h - 1); struct reiserfs_super_block * sb; if ( tb->blknum[h] != 1 ) reiserfs_panic(0, "balance_internal", "One new node required for creating the new root"); /* S[h] = empty buffer from the list FEB. */ tbSh = get_FEB (tb); set_blkh_level (B_BLK_HEAD(tbSh), h + 1); /* Put the unique node-pointer to S[h] that points to S[h-1]. */ dc = B_N_CHILD(tbSh, 0); set_dc_child_size (dc, MAX_CHILD_SIZE (tbSh_1->b_size) - get_blkh_free_space (B_BLK_HEAD(tbSh_1))); set_dc_child_blocknr (dc, tbSh_1->b_blocknr); tb->insert_size[h] -= DC_SIZE; set_blkh_free_space (B_BLK_HEAD(tbSh), get_blkh_free_space (B_BLK_HEAD(tbSh)) - DC_SIZE); mark_buffer_dirty (tbSh); /* put new root into path structure */ PATH_OFFSET_PBUFFER(tb->tb_path, ILLEGAL_PATH_ELEMENT_OFFSET) = tbSh; /* Change root in structure super block. */ sb = tb->tb_fs->fs_ondisk_sb; set_sb_root_block (sb, tbSh->b_blocknr); set_sb_tree_height (sb, get_sb_tree_height (sb) + 1); mark_buffer_dirty (tb->tb_fs->fs_super_bh); tb->tb_fs->fs_dirt = 1; } if ( tb->blknum[h] == 2 ) { int snum; struct buffer_info dest_bi, src_bi; /* S_new = free buffer from list FEB */ S_new = get_FEB(tb); set_blkh_level (B_BLK_HEAD(S_new), h + 1); dest_bi.bi_bh = S_new; dest_bi.bi_parent = 0; dest_bi.bi_position = 0; src_bi.bi_bh = tbSh; src_bi.bi_parent = PATH_H_PPARENT (tb->tb_path, h); src_bi.bi_position = PATH_H_POSITION (tb->tb_path, h + 1); n = get_blkh_nr_items (B_BLK_HEAD(tbSh)); /* number of items in S[h] */ snum = (insert_num + n + 1)/2; if ( n - snum >= child_pos ) { /* new items don't fall into S_new */ /* store the delimiting key for the next level */ /* new_insert_key = (n - snum)'th key in S[h] */ memcpy (&new_insert_key,B_N_PDELIM_KEY(tbSh,n - snum), KEY_SIZE); /* last parameter is del_par */ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, LAST_TO_FIRST, snum, 0); } else if ( n + insert_num - snum < child_pos ) { /* all new items fall into S_new */ /* store the delimiting key for the next level */ /* new_insert_key = (n + insert_item - snum)'th key in S[h] */ memcpy(&new_insert_key,B_N_PDELIM_KEY(tbSh,n + insert_num - snum), KEY_SIZE); /* last parameter is del_par */ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, LAST_TO_FIRST, snum - insert_num, 0); /* internal_move_pointers_items(S_new,tbSh,1,snum - insert_num,0);*/ /* insert insert_num keys and node-pointers into S_new */ internal_insert_childs (tb->tb_fs, &dest_bi, /*S_new,tb->S[h-1]->b_next,*/child_pos - n - insert_num + snum - 1, insert_num,insert_key,insert_ptr); insert_num = 0; } else { struct disk_child * dc; /* some items fall into S_new, but some don't fall */ /* last parameter is del_par */ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, LAST_TO_FIRST, n - child_pos + 1, 1); /* internal_move_pointers_items(S_new,tbSh,1,n - child_pos + 1,1);*/ /* calculate number of new items that fall into S_new */ k = snum - n + child_pos - 1; internal_insert_childs (tb->tb_fs, &dest_bi, /*S_new,*/ 0, k, insert_key + 1, insert_ptr+1); /* new_insert_key = insert_key[insert_num - k - 1] */ memcpy(&new_insert_key,insert_key + insert_num - k - 1, KEY_SIZE); /* replace first node-ptr in S_new by node-ptr to insert_ptr[insert_num-k-1] */ dc = B_N_CHILD(S_new,0); set_dc_child_size (dc, MAX_CHILD_SIZE(insert_ptr[insert_num-k-1]->b_size) - get_blkh_free_space (B_BLK_HEAD(insert_ptr[insert_num-k-1]))); set_dc_child_blocknr (dc, insert_ptr[insert_num-k-1]->b_blocknr); mark_buffer_dirty (S_new); insert_num -= (k + 1); } /* new_insert_ptr = node_pointer to S_new */ new_insert_ptr = S_new; /* S_new->b_count --; */ /*brelse(S_new);*/ } n = get_blkh_nr_items (B_BLK_HEAD(tbSh)); /*number of items in S[h] */ if ( -1 <= child_pos && child_pos <= n && insert_num > 0 ) { bi.bi_bh = tbSh; bi.bi_parent = PATH_H_PPARENT (tb->tb_path, h); bi.bi_position = PATH_H_POSITION (tb->tb_path, h + 1); if (child_pos == -1) { /* this is a little different from original do_balance: here we insert the minimal keys in the tree, that has never happened when file system works */ if (tb->CFL[h-1] || insert_num != 1 || h != 1) die ("balance_internal: invalid child_pos"); /* insert_child (tb->S[h], tb->S[h-1], child_pos, insert_num, B_N_ITEM_HEAD(tb->S[0],0), insert_ptr);*/ internal_insert_childs (tb->tb_fs, &bi, child_pos, insert_num, B_N_PITEM_HEAD (PATH_PLAST_BUFFER (tb->tb_path), 0), insert_ptr); } else internal_insert_childs (tb->tb_fs, &bi, child_pos,insert_num,insert_key,insert_ptr); } memcpy (new_insert_key_addr,&new_insert_key,KEY_SIZE); insert_ptr[0] = new_insert_ptr; return order; } reiserfsprogs-3.6.9/reiserfscore/node_formats.c0000664000077100007710000010266607705261642015460 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "includes.h" int leaf_count_ih(char * buf, int blocksize) { struct item_head * ih; int prev_location; int nr; /* look at the table of item head */ prev_location = blocksize; ih = (struct item_head *)(buf + BLKH_SIZE); nr = 0; while (1) { if (get_ih_location (ih) + get_ih_item_len (ih) != prev_location) break; if (get_ih_location (ih) < IH_SIZE * (nr + 1) + BLKH_SIZE) break; if (get_ih_item_len (ih) > MAX_ITEM_LEN (blocksize)) break; prev_location = get_ih_location (ih); ih ++; nr ++; } return nr; } int leaf_free_space_estimate(char * buf, int blocksize) { struct block_head * blkh; struct item_head * ih; int nr; blkh = (struct block_head *)buf; nr = get_blkh_nr_items(blkh); ih = (struct item_head *)(buf + BLKH_SIZE) + nr - 1; return (nr ? get_ih_location (ih) : blocksize) - BLKH_SIZE - IH_SIZE * nr; } static int leaf_blkh_correct(char * buf, int blocksize) { struct block_head * blkh; unsigned int nr; blkh = (struct block_head *)buf; if (!is_leaf_block_head (buf)) return 0; nr = get_blkh_nr_items(blkh); if (nr > ((blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN))) /* item number is too big or too small */ return 0; return leaf_free_space_estimate(buf, blocksize) == get_blkh_free_space (blkh); } int is_a_leaf(char * buf, int blocksize) { struct block_head * blkh; int counted; blkh = (struct block_head *)buf; if (!is_leaf_block_head (buf)) return 0; counted = leaf_count_ih(buf, blocksize); /* if leaf block header is ok, check item count also. */ if (leaf_blkh_correct(buf, blocksize)) return counted >= get_blkh_nr_items (blkh) ? THE_LEAF : HAS_IH_ARRAY; /* leaf block header is corrupted, it is ih_array if some items were detected.*/ return counted ? HAS_IH_ARRAY : 0; } int leaf_item_number_estimate(struct buffer_head * bh) { struct block_head * blkh; int nr; nr = leaf_count_ih(bh->b_data, bh->b_size); blkh = (struct block_head *)bh->b_data; return nr >= get_blkh_nr_items (blkh) ? get_blkh_nr_items (blkh) : nr; } #if 0 /* this only checks block header and item head array (ih_location-s and ih_item_len-s). Item internals are not checked */ int does_node_look_like_a_leaf (char * buf, int blocksize) { struct block_head * blkh; struct item_head * ih; int used_space; int prev_location; int i; int nr; blkh = (struct block_head *)buf; if (!is_leaf_block_head (buf)) return 0; nr = get_blkh_nr_items (blkh); if (nr < 0 || nr > ((blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN))) /* item number is too big or too small */ return 0; ih = (struct item_head *)(buf + BLKH_SIZE) + nr - 1; used_space = BLKH_SIZE + IH_SIZE * nr + (blocksize - (nr ? get_ih_location (ih) : blocksize)); if (used_space != blocksize - get_blkh_free_space (blkh)) /* free space does not match to calculated amount of use space */ return 0; // FIXME: it is_leaf will hit performance too much - we may have // return 1 here /* check tables of item heads */ ih = (struct item_head *)(buf + BLKH_SIZE); prev_location = blocksize; for (i = 0; i < nr; i ++, ih ++) { /* items of zero length are allowed - they may exist for short time during balancing */ if (get_ih_location (ih) > blocksize || get_ih_location (ih) < IH_SIZE * nr) return 0; if (/*ih_item_len (ih) < 1 ||*/ get_ih_item_len (ih) > MAX_ITEM_LEN (blocksize)) return 0; if (prev_location - get_ih_location (ih) != get_ih_item_len (ih)) return 0; prev_location = get_ih_location (ih); } // one may imagine much more checks return 1; } /* check ih_item_len and ih_location. Should be useful when block head is corrupted */ static int does_node_have_ih_array (char * buf, int blocksize) { struct item_head * ih; int prev_location; int nr; /* look at the table of item head */ prev_location = blocksize; ih = (struct item_head *)(buf + BLKH_SIZE); nr = 0; while (1) { if (get_ih_location (ih) + get_ih_item_len (ih) != prev_location) break; prev_location = get_ih_location (ih); ih ++; nr ++; } if (nr < 2) return 0; return nr; } #endif /* returns 1 if buf looks like an internal node, 0 otherwise */ static int is_correct_internal (char * buf, int blocksize) { struct block_head * blkh; unsigned int nr; int used_space; blkh = (struct block_head *)buf; if (!is_internal_block_head (buf)) return 0; nr = get_blkh_nr_items (blkh); if (nr > (blocksize - BLKH_SIZE - DC_SIZE) / (KEY_SIZE + DC_SIZE)) /* for internal which is not root we might check min number of keys */ return 0; used_space = BLKH_SIZE + KEY_SIZE * nr + DC_SIZE * (nr + 1); if (used_space != blocksize - get_blkh_free_space (blkh)) return 0; // one may imagine much more checks return 1; } // make sure that bh contains formatted node of reiserfs tree of // 'level'-th level int is_tree_node (struct buffer_head * bh, int level) { if (B_LEVEL (bh) != level) return 0; if (is_leaf_node (bh)) return is_a_leaf(bh->b_data, bh->b_size); return is_correct_internal (bh->b_data, bh->b_size); } static int is_desc_block (char * buf, unsigned long buf_size) { if (!memcmp(buf + buf_size - 12, JOURNAL_DESC_MAGIC, 8) && //get_jdesc_len (desc) > 0) le32_to_cpu(*((__u32*)(buf + 4))) > 0) return 1; return 0; } int is_reiserfs_3_5_magic_string (struct reiserfs_super_block * rs) { return (!strncmp (rs->s_v1.s_magic, REISERFS_3_5_SUPER_MAGIC_STRING, strlen ( REISERFS_3_5_SUPER_MAGIC_STRING))); } int is_reiserfs_3_6_magic_string (struct reiserfs_super_block * rs) { return (!strncmp (rs->s_v1.s_magic, REISERFS_3_6_SUPER_MAGIC_STRING, strlen ( REISERFS_3_6_SUPER_MAGIC_STRING))); } int is_reiserfs_jr_magic_string (struct reiserfs_super_block * rs) { return (!strncmp (rs->s_v1.s_magic, REISERFS_JR_SUPER_MAGIC_STRING, strlen ( REISERFS_JR_SUPER_MAGIC_STRING))); } int is_any_reiserfs_magic_string (struct reiserfs_super_block * rs) { if (is_reiserfs_3_5_magic_string (rs) || is_reiserfs_3_6_magic_string (rs) || is_reiserfs_jr_magic_string (rs)) return 1; return 0; } int get_reiserfs_format (struct reiserfs_super_block * sb) { /* after conversion to 3.6 format we change magic correctly, but do not change sb_format. When we create non-standard journal field format in sb get adjusted correctly. Thereby, for standard journal we should rely on magic and for non-standard - on format */ if (is_reiserfs_3_5_magic_string (sb) || (is_reiserfs_jr_magic_string (sb) && get_sb_version (sb) == REISERFS_FORMAT_3_5)) return REISERFS_FORMAT_3_5; if (is_reiserfs_3_6_magic_string (sb) || (is_reiserfs_jr_magic_string (sb) && get_sb_version (sb) == REISERFS_FORMAT_3_6)) return REISERFS_FORMAT_3_6; return REISERFS_FORMAT_UNKNOWN; } int reiserfs_super_block_size (struct reiserfs_super_block * sb) { switch (get_reiserfs_format (sb)) { case REISERFS_FORMAT_3_5: return SB_SIZE_V1; case REISERFS_FORMAT_3_6: return SB_SIZE; } reiserfs_panic ("Unknown format found"); return 0; } /* this one had signature in different place of the super_block structure */ int is_prejournaled_reiserfs (struct reiserfs_super_block * rs) { return (!strncmp((char*)rs + REISERFS_SUPER_MAGIC_STRING_OFFSET_NJ, REISERFS_3_5_SUPER_MAGIC_STRING, strlen(REISERFS_3_5_SUPER_MAGIC_STRING))); } int does_look_like_super_block (struct reiserfs_super_block * sb) { if (!is_any_reiserfs_magic_string (sb)) return 0; if (!is_blocksize_correct(get_sb_block_size (sb))) return 0; return 1; } /* returns code of reiserfs metadata block (leaf, internal, super block, journal descriptor), unformatted */ int who_is_this (char * buf, int blocksize) { int res; /* super block? */ if (does_look_like_super_block ((void *)buf)) return THE_SUPER; if ((res = is_a_leaf(buf, blocksize))) /* if block head and item head array seem matching (node level, free space, item number, item locations and length), then it is THE_LEAF, otherwise, it is HAS_IH_ARRAY */ return res; if (is_correct_internal (buf, blocksize)) return THE_INTERNAL; /* journal descriptor block? */ if (is_desc_block (buf, blocksize)) return THE_JDESC; /* contents of buf does not look like reiserfs metadata. Bitmaps are possible here */ return THE_UNKNOWN; } char * which_block (int code) { static char * leaf = "leaf"; static char * broken_leaf = "broken leaf"; static char * internal = "internal"; static char * other = "unknown"; switch (code) { case THE_LEAF: return leaf; case HAS_IH_ARRAY: return broken_leaf; case THE_INTERNAL: return internal; } return other; } /** */ int block_of_journal (reiserfs_filsys_t * fs, unsigned long block) { if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb)) { /* standard journal */ if (block >= get_journal_start_must (fs) && block <= get_journal_start_must (fs) + get_jp_journal_size (sb_jp (fs->fs_ondisk_sb))) return 1; return 0; } if (get_sb_reserved_for_journal (fs->fs_ondisk_sb)) /* there is space reserved for the journal on the host device */ if (block >= get_journal_start_must (fs) && block < get_journal_start_must (fs) + get_sb_reserved_for_journal (fs->fs_ondisk_sb)) return 1; return 0; } int block_of_bitmap (reiserfs_filsys_t * fs, unsigned long block) { if (spread_bitmaps (fs)) { if (!(block % (fs->fs_blocksize * 8))) /* bitmap block */ return 1; return (block == (REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize + 1)) ; } else { /* bitmap in */ return (block > 2ul && block < 3ul + get_sb_bmap_nr(fs->fs_ondisk_sb)) ? 1 : 0; } return 0; } /* check whether 'block' can be pointed to by an indirect item */ int not_data_block (reiserfs_filsys_t * fs, unsigned long block) { if (block_of_bitmap (fs, block)) /* it is one of bitmap blocks */ return 1; if (block_of_journal (fs, block)) /* block of journal area */ return 1; if (block <= fs->fs_super_bh->b_blocknr) /* either super block or a block from skipped area at the beginning of filesystem */ return 1; return 0; } /* check whether 'block' can be logged */ int not_journalable (reiserfs_filsys_t * fs, unsigned long block) { /* we should not update SB with journal copy during fsck */ if (block < fs->fs_super_bh->b_blocknr) return 1; if (block_of_journal (fs, block)) return 1; if (block >= get_sb_block_count (fs->fs_ondisk_sb)) return 1; return 0; } // in reiserfs version 0 (undistributed bitmap) // FIXME: what if number of bitmaps is 15? unsigned int get_journal_old_start_must (reiserfs_filsys_t * fs) { return (REISERFS_OLD_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) + 1 + get_sb_bmap_nr (fs->fs_ondisk_sb); } unsigned int get_journal_new_start_must (reiserfs_filsys_t * fs) { return (REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) + 2; } unsigned int get_journal_start_must(reiserfs_filsys_t * fs) { if (is_old_sb_location(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) return get_journal_old_start_must (fs); return get_journal_new_start_must(fs); } __u32 get_bytes_number (struct item_head * ih, int blocksize) { switch (get_type (&ih->ih_key)) { case TYPE_DIRECT: return get_ih_item_len (ih); case TYPE_INDIRECT: return I_UNFM_NUM(ih) * blocksize;// - get_ih_free_space (ih); case TYPE_STAT_DATA: case TYPE_DIRENTRY: return 0; } reiserfs_warning (stderr, "get_bytes_number: called for wrong type of item %h", ih); return 0; } int check_item_f (reiserfs_filsys_t * fs, struct item_head * ih, char * item); /* ih_key, ih_location and ih_item_len seem correct, check other fields */ static int does_ih_look_correct (struct item_head * ih) { int ih_key_format; int key_key_format; /* key format from item_head */ ih_key_format = get_ih_key_format (ih); if (ih_key_format != KEY_FORMAT_1 && ih_key_format != KEY_FORMAT_2) return 0; /* key format calculated on key */ key_key_format = key_format (&ih->ih_key); if (is_stat_data_ih (ih)) { /* for stat data we can not find key format from a key itself, so look at the item length */ if (get_ih_item_len (ih) == SD_SIZE) key_key_format = KEY_FORMAT_2; else if (get_ih_item_len (ih) == SD_V1_SIZE) key_key_format = KEY_FORMAT_1; else return 0; } if (key_key_format != ih_key_format) return 0; /* we do not check ih_format.fsck_need as fsck might change it. So, debugreiserfs -p will have to dump it */ return 1; } /* check item length, ih_free_space for pure 3.5 format, unformatted node pointers */ static int is_bad_indirect (reiserfs_filsys_t * fs, struct item_head * ih, char * item, check_unfm_func_t check_unfm_func) { unsigned int i; __u32 * ind = (__u32 *)item; if (get_ih_item_len (ih) % UNFM_P_SIZE) return 1; for (i = 0; i < I_UNFM_NUM (ih); i ++) { if (!ind [i]) continue; if (check_unfm_func && check_unfm_func (fs, le32_to_cpu(ind [i]))) return 1; } if (fs->fs_format == REISERFS_FORMAT_3_5) { /* check ih_free_space for 3.5 format only */ if (get_ih_free_space (ih) > fs->fs_blocksize - 1) return 1; } return 0; } static const struct { hashf_t func; char * name; } hashes[] = {{0, "not set"}, {keyed_hash, "\"tea\""}, {yura_hash, "\"rupasov\""}, {r5_hash, "\"r5\""}}; #define HASH_AMOUNT (sizeof (hashes) / sizeof (hashes [0])) int known_hashes (void) { return HASH_AMOUNT; } #define good_name(hashfn,name,namelen,deh_offset) \ (GET_HASH_VALUE ((hashfn) (name, namelen)) == GET_HASH_VALUE (deh_offset)) /* this also sets hash function */ int is_properly_hashed (reiserfs_filsys_t * fs, char * name, int namelen, __u32 offset) { unsigned int i; if (namelen == 1 && name[0] == '.') { if (offset == DOT_OFFSET) return 1; return 0; } if (namelen == 2 && name[0] == '.' && name[1] == '.') { if (offset == DOT_DOT_OFFSET) return 1; return 0; } if (hash_func_is_unknown (fs)) { /* try to find what hash function the name is sorted with */ for (i = 1; i < HASH_AMOUNT; i ++) { if (good_name (hashes [i].func, name, namelen, offset)) { if (!hash_func_is_unknown (fs)) { /* two or more hash functions give the same value for this name */ fprintf (stderr, "Detecting hash code: could not detect hash with name \"%.*s\"\n", namelen, name); reiserfs_hash (fs) = 0; return 1; } /* set hash function */ reiserfs_hash(fs) = hashes [i].func; } } if (hash_func_is_unknown (fs)) { return 0; } } if (good_name (reiserfs_hash(fs), name, namelen, offset)) return 1; return 0; } int find_hash_in_use (char * name, int namelen, __u32 hash_value_masked, unsigned int code_to_try_first) { unsigned int i; if (!namelen || !name[0]) return UNSET_HASH; if (code_to_try_first) { if (hash_value_masked == GET_HASH_VALUE (hashes [code_to_try_first].func (name, namelen))) return code_to_try_first; } for (i = 1; i < HASH_AMOUNT; i ++) { if (i == code_to_try_first) continue; if (hash_value_masked == GET_HASH_VALUE (hashes [i].func (name, namelen))) return i; } /* not matching hash found */ return UNSET_HASH; } char * code2name(unsigned int code) { if (code >= HASH_AMOUNT || code < 0) return 0; return hashes [code].name; } int func2code (hashf_t func) { unsigned int i; for (i = 0; i < HASH_AMOUNT; i ++) if (func == hashes [i].func) return i; reiserfs_panic ("func2code: no hashes matches this function\n"); return 0; } hashf_t code2func(unsigned int code) { if (code >= HASH_AMOUNT) { reiserfs_warning (stderr, "code2func: wrong hash code %d.\n" "Using default %s hash function\n", code, code2name (DEFAULT_HASH)); code = DEFAULT_HASH; } return hashes [code].func; } hashf_t name2func (char * hash) { unsigned int i; for (i = 0; i < HASH_AMOUNT; i ++) if (!strcmp (hash, hashes [i].name)) return hashes [i].func; return 0; } int dir_entry_bad_location (struct reiserfs_de_head * deh, struct item_head * ih, int first) { if (get_deh_location (deh) < DEH_SIZE * get_ih_entry_count (ih)) return 1; if (get_deh_location (deh) >= get_ih_item_len (ih)) return 1; if (!first && get_deh_location (deh) >= get_deh_location (deh - 1)) return 1; return 0; } /* the only corruption which is not considered fatal - is hash mismatching. If bad_dir is set - directory item having such names is considered bad */ static int is_bad_directory (reiserfs_filsys_t * fs, struct item_head * ih, char * item, int bad_dir) { int i; int namelen; struct reiserfs_de_head * deh = (struct reiserfs_de_head *)item; __u32 prev_offset = 0; __u16 prev_location = get_ih_item_len (ih); for (i = 0; i < get_ih_entry_count (ih); i ++, deh ++) { if (get_deh_location (deh) >= prev_location) return 1; prev_location = get_deh_location (deh); namelen = name_in_entry_length (ih, deh, i); if (namelen > (int)REISERFS_MAX_NAME_LEN(fs->fs_blocksize)) return 1; if (get_deh_offset (deh) <= prev_offset) return 1; prev_offset = get_deh_offset (deh); /* check hash value */ if (!is_properly_hashed (fs, item + prev_location, namelen, prev_offset)) { if (bad_dir) /* make is_bad_leaf to not insert whole leaf. Node will be marked not-insertable and put into tree item by item in pass 2 */ return 1; } } return 0; } /* used by debugreisrefs -p only yet */ int is_it_bad_item (reiserfs_filsys_t * fs, struct item_head * ih, char * item, check_unfm_func_t check_unfm, int bad_dir) { int retval; /* if (!does_key_look_correct (fs, &ih->ih_key)) return 1; if (!does_ih_look_correct (ih)) return 1; */ if (!does_ih_look_correct (ih)) return 1; if (is_stat_data_ih (ih) || is_direct_ih (ih)) return 0; if (is_direntry_ih (ih)) { retval = is_bad_directory (fs, ih, item, bad_dir); /* if (retval) reiserfs_warning (stderr, "is_bad_directory %H\n", ih);*/ return retval; } if (is_indirect_ih (ih)) { retval = is_bad_indirect (fs, ih, item, check_unfm); /* if (retval) reiserfs_warning (stderr, "is_bad_indirect %H\n", ih);*/ return retval; } return 1; } /* prepare new or old stat data for the new directory */ void make_dir_stat_data (int blocksize, int key_format, __u32 dirid, __u32 objectid, struct item_head * ih, void * sd) { memset (ih, 0, IH_SIZE); set_key_dirid (&ih->ih_key, dirid); set_key_objectid (&ih->ih_key, objectid); set_key_offset_v1 (&ih->ih_key, SD_OFFSET); set_key_uniqueness (&ih->ih_key, 0); set_ih_key_format (ih, key_format); set_ih_free_space (ih, MAX_US_INT); if (key_format == KEY_FORMAT_2) { struct stat_data *sd_v2 = (struct stat_data *)sd; set_ih_item_len (ih, SD_SIZE); set_sd_v2_mode (sd_v2, S_IFDIR + 0755); set_sd_v2_nlink (sd_v2, 2); set_sd_v2_uid (sd_v2, 0); set_sd_v2_gid (sd_v2, 0); set_sd_v2_size (sd_v2, EMPTY_DIR_SIZE); set_sd_v2_atime (sd_v2, time(NULL)); sd_v2->sd_ctime = sd_v2->sd_mtime = sd_v2->sd_atime; /* all le */ set_sd_v2_rdev (sd_v2, 0); set_sd_v2_blocks (sd_v2, dir_size2st_blocks (EMPTY_DIR_SIZE)); }else{ struct stat_data_v1 *sd_v1 = (struct stat_data_v1 *)sd; set_ih_item_len (ih, SD_V1_SIZE); set_sd_v1_mode(sd_v1, S_IFDIR + 0755); set_sd_v1_nlink(sd_v1, 2); set_sd_v1_uid (sd_v1, 0); set_sd_v1_gid (sd_v1, 0); set_sd_v1_size(sd_v1, EMPTY_DIR_SIZE_V1); set_sd_v1_atime(sd_v1, time(NULL)); sd_v1->sd_ctime = sd_v1->sd_mtime = sd_v1->sd_atime; /* all le */ set_sd_v1_blocks(sd_v1, dir_size2st_blocks(EMPTY_DIR_SIZE_V1)); set_sd_v1_first_direct_byte(sd_v1, NO_BYTES_IN_DIRECT_ITEM); } } static void _empty_dir_item (int format, char * body, __u32 dirid, __u32 objid, __u32 par_dirid, __u32 par_objid) { struct reiserfs_de_head * deh; __u16 state; memset (body, 0, (format == KEY_FORMAT_2 ? EMPTY_DIR_SIZE : EMPTY_DIR_SIZE_V1)); deh = (struct reiserfs_de_head *)body; /* direntry header of "." */ set_deh_offset (deh, DOT_OFFSET); set_deh_dirid (deh, dirid); set_deh_objectid (deh, objid); state = (1 << DEH_Visible2); set_deh_state (deh, state); /* direntry header of ".." */ set_deh_offset (deh + 1, DOT_DOT_OFFSET); /* key of ".." for the root directory */ set_deh_dirid (deh + 1, par_dirid); set_deh_objectid (deh + 1, par_objid); set_deh_state (deh + 1, state); if (format == KEY_FORMAT_2) { set_deh_location (deh, EMPTY_DIR_SIZE - ROUND_UP (strlen ("."))); set_deh_location (deh + 1, get_deh_location (deh) - ROUND_UP (strlen (".."))); } else { set_deh_location (deh, EMPTY_DIR_SIZE_V1 - strlen (".")); set_deh_location (deh + 1, get_deh_location (deh) - strlen ("..")); } /* copy ".." and "." */ memcpy (body + get_deh_location (deh), ".", 1); memcpy (body + get_deh_location (deh + 1), "..", 2); } void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, __u32 par_dirid, __u32 par_objid) { _empty_dir_item (KEY_FORMAT_1, body, dirid, objid, par_dirid, par_objid); } void make_empty_dir_item (char * body, __u32 dirid, __u32 objid, __u32 par_dirid, __u32 par_objid) { _empty_dir_item (KEY_FORMAT_2, body, dirid, objid, par_dirid, par_objid); } /* for every item call common action and an action corresponding to item type */ void for_every_item (struct buffer_head * bh, item_head_action_t action, item_action_t * actions) { int i; struct item_head * ih; item_action_t iaction; ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) { if (action) action (ih); iaction = actions[get_type (&ih->ih_key)]; if (iaction) iaction (bh, ih); } } #if __BYTE_ORDER == __LITTLE_ENDIAN # define get_key_offset_v2(key) (__u64)((key->u.k2_offset_v2.k_offset)) # define set_key_offset_v2(key,val) (void)(key->u.k2_offset_v2.k_offset = (val)) # define get_key_type_v2(key) (__u16)((key->u.k2_offset_v2.k_type)) # define set_key_type_v2(key,val) (void)(key->u.k2_offset_v2.k_type = (val)) #elif __BYTE_ORDER == __BIG_ENDIAN typedef union { struct offset_v2 offset_v2; __u64 linear; } __attribute__ ((__packed__)) offset_v2_esafe_overlay; static inline __u64 get_key_offset_v2 (const struct key *key) { offset_v2_esafe_overlay tmp = *(offset_v2_esafe_overlay *) (&(key->u.k2_offset_v2)); tmp.linear = le64_to_cpu( tmp.linear ); return tmp.offset_v2.k_offset; } static inline __u32 get_key_type_v2 (const struct key *key) { offset_v2_esafe_overlay tmp = *(offset_v2_esafe_overlay *) (&(key->u.k2_offset_v2)); tmp.linear = le64_to_cpu( tmp.linear ); return tmp.offset_v2.k_type; } static inline void set_key_offset_v2 (struct key *key, __u64 offset) { offset_v2_esafe_overlay *tmp = (offset_v2_esafe_overlay *)(&(key->u.k2_offset_v2)); tmp->linear = le64_to_cpu(tmp->linear); tmp->offset_v2.k_offset = offset; tmp->linear = cpu_to_le64(tmp->linear); } static inline void set_key_type_v2 (struct key *key, __u32 type) { offset_v2_esafe_overlay *tmp = (offset_v2_esafe_overlay *)(&(key->u.k2_offset_v2)); if (type > 15) reiserfs_panic ("set_key_type_v2: type is too big %d", type); tmp->linear = le64_to_cpu(tmp->linear); tmp->offset_v2.k_type = type; tmp->linear = cpu_to_le64(tmp->linear); } #else # error "nuxi/pdp-endian archs are not supported" #endif static inline int is_key_format_1 (int type) { return ( (type == 0 || type == 15) ? 1 : 0); } /* old keys (on i386) have k_offset_v2.k_type == 15 (direct and indirect) or == 0 (dir items and stat data) */ /* */ int key_format (const struct key * key) { int type; type = get_key_type_v2 (key); if (is_key_format_1 (type)) return KEY_FORMAT_1; return KEY_FORMAT_2; } unsigned long long get_offset (const struct key * key) { if (key_format (key) == KEY_FORMAT_1) return get_key_offset_v1 (key); return get_key_offset_v2 (key); } int uniqueness2type (__u32 uniqueness) { switch (uniqueness) { case V1_SD_UNIQUENESS: return TYPE_STAT_DATA; case V1_INDIRECT_UNIQUENESS: return TYPE_INDIRECT; case V1_DIRECT_UNIQUENESS: return TYPE_DIRECT; case V1_DIRENTRY_UNIQUENESS: return TYPE_DIRENTRY; } return TYPE_UNKNOWN; } __u32 type2uniqueness (int type) { switch (type) { case TYPE_STAT_DATA: return V1_SD_UNIQUENESS; case TYPE_INDIRECT: return V1_INDIRECT_UNIQUENESS; case TYPE_DIRECT: return V1_DIRECT_UNIQUENESS; case TYPE_DIRENTRY: return V1_DIRENTRY_UNIQUENESS; } return V1_UNKNOWN_UNIQUENESS; } int get_type (const struct key * key) { int type_v2 = get_key_type_v2 (key); if (is_key_format_1 (type_v2)) return uniqueness2type (get_key_uniqueness (key)); return type_v2; } char * key_of_what (const struct key * key) { switch (get_type (key)) { case TYPE_STAT_DATA: return "SD"; case TYPE_INDIRECT: return "IND"; case TYPE_DIRECT: return "DRCT"; case TYPE_DIRENTRY: return "DIR"; default: return "???"; } } int type_unknown (struct key * key) { int type = get_type (key); switch (type) { case TYPE_STAT_DATA: case TYPE_INDIRECT: case TYPE_DIRECT: case TYPE_DIRENTRY: return 0; default: break; } return 1; } // this sets key format as well as type of item key belongs to // void set_type (int format, struct key * key, int type) { if (format == KEY_FORMAT_1) set_key_uniqueness (key, type2uniqueness (type)); else set_key_type_v2 (key, type); } // void set_offset (int format, struct key * key, loff_t offset) { if (format == KEY_FORMAT_1) set_key_offset_v1 (key, offset); else set_key_offset_v2 (key, offset); } void set_type_and_offset (int format, struct key * key, loff_t offset, int type) { set_type (format, key, type); set_offset (format, key, offset); } /* length of the directory entry in directory item. This define calculates length of i-th directory entry using directory entry locations from dir entry head. When it calculates length of 0-th directory entry, it uses length of whole item in place of entry location of the non-existent following entry in the calculation. See picture above.*/ // NOTE: this is not name length. This is length of whole entry int entry_length (struct item_head * ih, struct reiserfs_de_head * deh, int pos_in_item) { if (pos_in_item) return (get_deh_location (deh - 1) - get_deh_location (deh)); return (get_ih_item_len (ih) - get_deh_location (deh)); } char * name_in_entry (struct reiserfs_de_head * deh, int pos_in_item) { return ((char *)(deh - pos_in_item) + get_deh_location(deh)); } int name_in_entry_length (struct item_head * ih, struct reiserfs_de_head * deh, int pos_in_item) { int len; char * name; len = entry_length (ih, deh, pos_in_item); name = name_in_entry (deh, pos_in_item); // name might be padded with 0s while (!name [len - 1] && len > 0) len --; return len; } int name_length (char * name, int key_format) { if (key_format == KEY_FORMAT_2) return ROUND_UP (strlen(name)); else if (key_format == KEY_FORMAT_1) return strlen(name); return -1; } /* key format is stored in 12 bits starting from 0-th of item_head's ih2_format*/ __u16 get_ih_key_format (const struct item_head * ih) { get_bit_field_XX (16, &ih->ih_format, 0, 12); } __u16 get_ih_flags (const struct item_head * ih) { get_bit_field_XX (16, &ih->ih_format, 12, 4); } void set_ih_key_format (struct item_head * ih, __u16 val) { set_bit_field_XX (16, &ih->ih_format, val, 0, 12); } void set_ih_flags (struct item_head * ih, __u16 val) { set_bit_field_XX (16, &ih->ih_format, val, 12, 4); } /* access to fields of stat data (both v1 and v2) */ void get_set_sd_field (int field, struct item_head * ih, void * sd, void * value, int set) { if (get_ih_key_format (ih) == KEY_FORMAT_1) { struct stat_data_v1 * sd_v1 = sd; switch (field) { case GET_SD_MODE: if (set) sd_v1->sd_mode = cpu_to_le16 (*(__u16 *)value); else *(__u16 *)value = le16_to_cpu (sd_v1->sd_mode); break; case GET_SD_SIZE: /* value must point to 64 bit int */ if (set) sd_v1->sd_size = cpu_to_le32 (*(__u64 *)value); else *(__u64 *)value = le32_to_cpu (sd_v1->sd_size); break; case GET_SD_BLOCKS: if (set) sd_v1->u.sd_blocks = cpu_to_le32 (*(__u32 *)value); else *(__u32 *)value = le32_to_cpu (sd_v1->u.sd_blocks); break; case GET_SD_NLINK: /* value must point to 32 bit int */ if (set) sd_v1->sd_nlink = cpu_to_le16 (*(__u32 *)value); else *(__u32 *)value = le16_to_cpu (sd_v1->sd_nlink); break; case GET_SD_FIRST_DIRECT_BYTE: if (set) sd_v1->sd_first_direct_byte = cpu_to_le32 (*(__u32 *)value); else *(__u32 *)value = le32_to_cpu (sd_v1->sd_first_direct_byte); break; default: reiserfs_panic ("get_set_sd_field: unknown field of old stat data"); } } else { struct stat_data * sd_v2 = sd; switch (field) { case GET_SD_MODE: if (set) sd_v2->sd_mode = cpu_to_le16 (*(__u16 *)value); else *(__u16 *)value = le16_to_cpu (sd_v2->sd_mode); break; case GET_SD_SIZE: if (set) sd_v2->sd_size = cpu_to_le64 (*(__u64 *)value); else *(__u64 *)value = le64_to_cpu (sd_v2->sd_size); break; case GET_SD_BLOCKS: if (set) sd_v2->sd_blocks = cpu_to_le32 (*(__u32 *)value); else *(__u32 *)value = le32_to_cpu (sd_v2->sd_blocks); break; case GET_SD_NLINK: if (set) sd_v2->sd_nlink = cpu_to_le32 (*(__u32 *)value); else *(__u32 *)value = le32_to_cpu (sd_v2->sd_nlink); break; case GET_SD_FIRST_DIRECT_BYTE: default: reiserfs_panic ("get_set_sd_field: unknown field of new stat data"); } } } int comp_ids (const void * p1, const void * p2) { __u32 id1 = le32_to_cpu(*(__u32 *)p1) ; __u32 id2 = le32_to_cpu(*(__u32 *)p2) ; if (id1 < id2) return -1; if (id1 > id2) return 1 ; return 0 ; } /* functions to manipulate with super block's objectid map */ int is_objectid_used (reiserfs_filsys_t * fs, __u32 objectid) { __u32 * objectid_map; __u32 count = get_sb_oid_cursize(fs->fs_ondisk_sb); int ret; __u32 pos; __u32 le_id = cpu_to_le32(objectid); objectid_map = (__u32 *)((char *)fs->fs_ondisk_sb + reiserfs_super_block_size (fs->fs_ondisk_sb)); ret = reiserfs_bin_search(&le_id, objectid_map, count, sizeof(__u32), &pos, comp_ids); /* if the position returned is odd, the oid is in use */ if (ret == POSITION_NOT_FOUND) return (pos & 1) ; /* if the position returned is even, the oid is in use */ return !(pos & 1) ; } void mark_objectid_used (reiserfs_filsys_t * fs, __u32 objectid) { int i; __u32 * objectid_map; int cursize; if (is_objectid_used (fs, objectid)) { return; } objectid_map = (__u32 *)((char *)fs->fs_ondisk_sb + reiserfs_super_block_size (fs->fs_ondisk_sb)); cursize = get_sb_oid_cursize (fs->fs_ondisk_sb); for (i = 0; i < cursize; i += 2) { if (objectid >= le32_to_cpu (objectid_map [i]) && objectid < le32_to_cpu (objectid_map [i + 1])) /* it is used */ return; if (objectid + 1 == le32_to_cpu (objectid_map[i])) { /* size of objectid map does not change */ objectid_map[i] = cpu_to_le32 (objectid); return; } if (objectid == le32_to_cpu (objectid_map[i + 1])) { /* size of objectid map is decreased */ objectid_map [i + 1] = cpu_to_le32 (le32_to_cpu (objectid_map [i + 1]) + 1); if (i + 2 < cursize) { if (objectid_map[i + 1] == objectid_map[i + 2]) { memmove (objectid_map + i + 1, objectid_map + i + 1 + 2, (cursize - (i + 2 + 2 - 1)) * sizeof (__u32)); set_sb_oid_cursize (fs->fs_ondisk_sb, cursize - 2); } } return; } if (objectid < le32_to_cpu (objectid_map[i])) { /* size of objectid map must be increased */ if (cursize == get_sb_oid_maxsize (fs->fs_ondisk_sb)) { /* here all objectids between objectid and objectid_map[i] get used */ objectid_map[i] = cpu_to_le32 (objectid); return; } else { memmove (objectid_map + i + 2, objectid_map + i, (cursize - i) * sizeof (__u32)); set_sb_oid_cursize (fs->fs_ondisk_sb, cursize + 2); } objectid_map[i] = cpu_to_le32 (objectid); objectid_map[i+1] = cpu_to_le32 (objectid + 1); return; } } /* append to current objectid map, if we have space */ if (i < get_sb_oid_maxsize (fs->fs_ondisk_sb)) { objectid_map[i] = cpu_to_le32 (objectid); objectid_map[i + 1] = cpu_to_le32 (objectid + 1); set_sb_oid_cursize (fs->fs_ondisk_sb, cursize + 2); } else if (i == get_sb_oid_maxsize (fs->fs_ondisk_sb)) { objectid_map[i - 1] = cpu_to_le32 (objectid + 1); } else die ("mark_objectid_as_used: objectid map corrupted"); return; } int is_blocksize_correct (unsigned int blocksize) { return ((blocksize == 0) || (((blocksize & -blocksize) == blocksize) && (blocksize >=512) && (blocksize <= 8192))); } reiserfsprogs-3.6.9/reiserfscore/prints.c0000664000077100007710000007357407705261642014324 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "includes.h" #include #include #include #define PA_KEY (PA_LAST) #define PA_BUFFER_HEAD (PA_LAST + 1) #define PA_ITEM_HEAD (PA_LAST + 2) #define PA_DISK_CHILD (PA_LAST + 3) static int _arginfo_b (const struct printf_info *info, size_t n, int *argtypes) { if (n > 0) argtypes[0] = PA_BUFFER_HEAD | PA_FLAG_PTR; return 1; } static int _arginfo_K (const struct printf_info *info, size_t n, int *argtypes) { if (n > 0) argtypes[0] = PA_KEY | PA_FLAG_PTR; return 1; } static int _arginfo_H (const struct printf_info *info, size_t n, int *argtypes) { if (n > 0) argtypes[0] = PA_ITEM_HEAD | PA_FLAG_PTR; return 1; } static int _arginfo_y (const struct printf_info *info, size_t n, int *argtypes) { if (n > 0) argtypes[0] = PA_DISK_CHILD | PA_FLAG_PTR; return 1; } static int _arginfo_M (const struct printf_info *info, size_t n, int *argtypes) { if (n > 0) argtypes[0] = PA_INT | PA_FLAG_SHORT | PA_FLAG_PTR; return 1; } static int _arginfo_U (const struct printf_info *info, size_t n, int *argtypes) { if (n > 0) argtypes[0] = (PA_CHAR|PA_FLAG_PTR); 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 key * key; char * buffer; int len; key = *((const struct 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 key * key; char * buffer; int len; key = *((const struct 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) { int i; const unsigned char * uuid; int len = 0; uuid = *((const unsigned char **)(args[0])); for (i = 0; i < 16; i++) { if (i == 4 || i == 6 || i == 8 || i == 10) len += fprintf (stream, "-"); len += fprintf(stream, "%02x", uuid[i]); } return len; } void reiserfs_warning (FILE * fp, const char * fmt, ...) { static int registered = 0; va_list args; if (!registered) { registered = 1; register_printf_function ('K', print_short_key, _arginfo_K); register_printf_function ('k', print_key, _arginfo_K); register_printf_function ('H', print_item_head, _arginfo_H); register_printf_function ('b', print_block_head, _arginfo_b); register_printf_function ('y', print_disk_child, _arginfo_y); register_printf_function ('M', print_sd_mode, _arginfo_M); register_printf_function ('U', print_sd_uuid, _arginfo_U); } va_start (args, fmt); vfprintf (fp, fmt, args); va_end (args); } static char * vi_type (struct virtual_item * vi) { static char *types[]={"directory", "direct", "indirect", "stat data"}; if (vi->vi_type & VI_TYPE_STAT_DATA) return types[3]; if (vi->vi_type & VI_TYPE_INDIRECT) return types[2]; if (vi->vi_type & VI_TYPE_DIRECT) return types[1]; if (vi->vi_type & VI_TYPE_DIRECTORY) return types[0]; reiserfs_panic ("vi_type: 6000: unknown type (0x%x)", vi->vi_type); return NULL; } void print_virtual_node (struct virtual_node * vn) { int i, j; printf ("VIRTUAL NODE CONTAINS %d items, has size %d,%s,%s, ITEM_POS=%d POS_IN_ITEM=%d MODE=\'%c\'\n", vn->vn_nr_item, vn->vn_size, (vn->vn_vi[0].vi_type & VI_TYPE_LEFT_MERGEABLE )? "left mergeable" : "", (vn->vn_vi[vn->vn_nr_item - 1].vi_type & VI_TYPE_RIGHT_MERGEABLE) ? "right mergeable" : "", vn->vn_affected_item_num, vn->vn_pos_in_item, vn->vn_mode); for (i = 0; i < vn->vn_nr_item; i ++) { printf ("%s %d %d", vi_type (&vn->vn_vi[i]), i, vn->vn_vi[i].vi_item_len); if (vn->vn_vi[i].vi_entry_sizes) { printf ("It is directory with %d entries: ", vn->vn_vi[i].vi_entry_count); for (j = 0; j < vn->vn_vi[i].vi_entry_count; j ++) printf ("%d ", vn->vn_vi[i].vi_entry_sizes[j]); } printf ("\n"); } } void print_path (struct tree_balance * tb, struct path * path) { int offset = path->path_length; struct buffer_head * bh; printf ("Offset Bh (b_blocknr, b_count) Position Nr_item\n"); while ( offset > ILLEGAL_PATH_ELEMENT_OFFSET ) { bh = PATH_OFFSET_PBUFFER (path, offset); printf ("%6d %10p (%9lu, %7d) %8d %7d\n", offset, bh, bh ? bh->b_blocknr : 0, bh ? bh->b_count : 0, PATH_OFFSET_POSITION (path, offset), bh ? B_NR_ITEMS (bh) : -1); offset --; } } 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 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_HASH_VALUE (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 (le32_to_cpu (start) == INT_MAX) return 1; if (start == 0 && new == 0) { (*len) ++; return 0; } if (start != 0 && (le32_to_cpu (start) + *len) == le32_to_cpu (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, " %d", le32_to_cpu (start)); else reiserfs_warning (fp, " %d(%d)", le32_to_cpu (start), len); } void print_indirect_item (FILE * fp, struct buffer_head * bh, int item_num) { struct item_head * ih; unsigned int j; __u32 * unp, prev = INT_MAX; int num; ih = B_N_PITEM_HEAD (bh, item_num); unp = (__u32 *)B_I_PITEM (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, unp[j])) { print_sequence (fp, prev, num); start_new_sequence (&prev, &num, unp[j]); } } print_sequence (fp, prev, num); reiserfs_warning (fp, "]\n"); } char timebuf[256]; 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 *)B_I_PITEM (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 *)B_I_PITEM (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 - B_N_PITEM_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 - B_N_PITEM_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, 0, 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, struct buffer_head * bh, int first, int last) { struct 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 (%ld) 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 = B_N_PDELIM_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 block_head * blkh; struct item_head * ih; int i; int from, to; int nr; if (!is_tree_node (bh, DISK_LEAF_NODE_LEVEL)) return 1; blkh = B_BLK_HEAD (bh); ih = B_N_PITEM_HEAD (bh,0); nr = leaf_count_ih(bh->b_data, bh->b_size); reiserfs_warning (fp, "\n===================================================================\n"); reiserfs_warning (fp, "LEAF NODE (%ld) contains %b (real items %d)\n", bh->b_blocknr, bh, nr); if (!(print_mode & PRINT_TREE_DETAILS)) { reiserfs_warning (fp, "FIRST ITEM_KEY: %k, LAST ITEM KEY: %k\n", &(ih->ih_key), &((ih + nr - 1)->ih_key)); return 0; } if (first < 0 || first > nr - 1) from = 0; else from = first; if (last < 0 || last > nr) to = 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|\n", i, ih + i); 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 (B_I_PITEM(bh,ih+i)[j] == 10) reiserfs_warning (fp, "\\n"); else reiserfs_warning (fp, "%c", B_I_PITEM(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, 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; if (!does_look_like_super_block (sb)) return 1; rdev = get_st_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\n", get_sb_bmap_nr (sb)); reiserfs_warning (fp, "Blocksize: %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 %scleanly umounted\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"); } 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; 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 %ld contains unformatted data\n", bh->b_blocknr); } void print_tb (int mode, int item_pos, int pos_in_item, struct tree_balance * tb, 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 = 0; tbFh = 0; } printf ("* %u * %3lu(%2lu) * %3lu(%2lu) * %3lu(%2lu) * %5ld * %5ld * %5ld * %5ld * %5ld *\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, 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 = get_sb_bmap_nr (sb); 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; __u32 * omap; sb = fs->fs_ondisk_sb; if (fs->fs_format == REISERFS_FORMAT_3_6) omap = (__u32 *)(sb + 1); else if (fs->fs_format == REISERFS_FORMAT_3_5) omap = (__u32 *)((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)) ? ~0ul : (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); } reiserfsprogs-3.6.9/reiserfscore/includes.h0000664000077100007710000000066507665645673014626 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "io.h" #include "misc.h" #include "reiserfs_lib.h" #include "swab.h" reiserfsprogs-3.6.9/reiserfscore/reiserfslib.c0000664000077100007710000011401207705261642015275 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "includes.h" #include struct key root_dir_key = {0, 0, {{0, 0},}}; struct key parent_root_dir_key = {0, 0, {{0, 0},}}; struct key lost_found_dir_key = {0, 0, {{0, 0}, }}; __u16 root_dir_format = 0; __u16 lost_found_dir_format = 0; static void make_const_keys (void) { set_key_dirid (&root_dir_key, REISERFS_ROOT_PARENT_OBJECTID); set_key_objectid (&root_dir_key, REISERFS_ROOT_OBJECTID); set_key_dirid (&parent_root_dir_key, 0); set_key_objectid (&parent_root_dir_key, REISERFS_ROOT_PARENT_OBJECTID); } /* reiserfs needs at least: enough blocks for journal, 64 k at the beginning, one block for super block, bitmap block and root block. Note that first bitmap block must point to all of them */ int is_block_count_correct (unsigned long journal_offset, unsigned int block_size, unsigned long block_count, unsigned long journal_size) { unsigned long blocks; /* RESERVED, MD RAID SBs, super block, bitmap, root, journal size with journal header */ blocks = journal_offset + journal_size; /* we have a limit: skipped area, super block, journal and root block all have to be addressed by one first bitmap */ if (blocks > block_size * 8) return 0; if (blocks > block_count) return 0; return 1; } /* read super block. fixme: only 4k blocks, pre-journaled format is refused. Journal and bitmap are to be opened separately. skip_check is set to 1 if checks of openned SB should be omitted.*/ reiserfs_filsys_t * reiserfs_open (char * filename, int flags, int *error, void * vp, int check) { reiserfs_filsys_t * fs; struct buffer_head * bh; struct reiserfs_super_block * sb; int fd, i; /* convert root dir key and parent root dir key to little endian format */ make_const_keys (); fd = open (filename, flags | O_LARGEFILE); if (fd == -1) { if (error) *error = errno; return 0; } fs = getmem (sizeof (*fs)); fs->fs_dev = fd; fs->fs_vp = vp; asprintf (&fs->fs_file_name, "%s", filename); /* reiserfs super block is either in 16-th or in 2-nd 4k block of the device */ for (i = 2; i < 17; i += 14) { bh = bread (fd, i, 4096); if (!bh) { reiserfs_warning (stderr, "reiserfs_open: bread failed reading block %d\n", i); } else { sb = (struct reiserfs_super_block *)bh->b_data; if (is_any_reiserfs_magic_string(sb)) goto found; /* reiserfs signature is not found at the i-th 4k block */ brelse (bh); } } reiserfs_warning(stderr, "\nreiserfs_open: the reiserfs superblock cannot be found on %s.\n", filename); if (error) *error = 0; freemem (fs); close (fd); fs = NULL; return fs; found: if (check) { /* A few checks of found super block. */ struct buffer_head *tmp_bh; if (!is_blocksize_correct(get_sb_block_size(sb))) { reiserfs_warning(stderr, "reiserfs_open: a superblock with wrong parameters " "was found in the block (%d).\n", i); freemem (fs); close (fd); brelse(bh); return NULL; } tmp_bh = bread (fd, get_sb_block_count(sb) - 1, get_sb_block_size(sb)); if (!tmp_bh) { reiserfs_warning (stderr, "\n%s: Your partition is not big enough to contain the \n" "filesystem of (%lu) blocks as was specified in the found super block.\n", __FUNCTION__, get_sb_block_count(sb) - 1); freemem (fs); close (fd); brelse(bh); return NULL; } brelse(tmp_bh); } fs->fs_blocksize = get_sb_block_size (sb); /* check block size on the filesystem */ if (fs->fs_blocksize != 4096) { i = bh->b_blocknr * 4096 / fs->fs_blocksize; brelse (bh); bh = bread (fd, i, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "reiserfs_open: bread failed reading block %d, size %d\n", i, fs->fs_blocksize); freemem (fs); return 0; } sb = (struct reiserfs_super_block *)bh->b_data; } fs->fs_hash_function = code2func (get_sb_hash_code (sb)); fs->fs_super_bh = bh; fs->fs_ondisk_sb = sb; fs->fs_flags = flags; /* O_RDONLY or O_RDWR */ fs->fs_format = get_reiserfs_format (sb); /*reiserfs_read_bitmap_blocks(fs);*/ if (flags & O_RDWR) fs->fs_dirt = 1; else fs->fs_dirt = 0; return fs; } /* creates buffer for super block and fills it up with fields which are constant for given size and version of a filesystem */ reiserfs_filsys_t * reiserfs_create (char * filename, int version, unsigned long block_count, int block_size, int default_journal, int new_format) { reiserfs_filsys_t * fs; /* convert root dir key and parent root dir key to little endian format */ make_const_keys (); if (count_blocks (filename, block_size) < block_count) { reiserfs_warning (stderr, "reiserfs_create: no enough blocks on device\n"); return 0; } if (!is_block_count_correct (REISERFS_DISK_OFFSET_IN_BYTES / block_size, block_size, block_count, 0)) { reiserfs_warning (stderr, "reiserfs_create: can not create that small " "(%d blocks) filesystem\n", block_count); return 0; } fs = getmem (sizeof (*fs)); if (!fs) { reiserfs_warning (stderr, "reiserfs_create: getmem failed\n"); return 0; } fs->fs_dev = open (filename, O_RDWR | O_LARGEFILE); if (fs->fs_dev == -1) { reiserfs_warning (stderr, "reiserfs_create: could not open %s: %s\n", filename, strerror(errno)); freemem (fs); return 0; } fs->fs_blocksize = block_size; asprintf (&fs->fs_file_name, "%s", filename); fs->fs_format = version; if (new_format) fs->fs_super_bh = getblk (fs->fs_dev, REISERFS_DISK_OFFSET_IN_BYTES / block_size, block_size); else fs->fs_super_bh = getblk (fs->fs_dev, REISERFS_OLD_DISK_OFFSET_IN_BYTES / block_size, block_size); if (!fs->fs_super_bh) { reiserfs_warning (stderr, "reiserfs_create: getblk failed\n"); return 0; } mark_buffer_uptodate (fs->fs_super_bh, 1); fs->fs_ondisk_sb = (struct reiserfs_super_block *)fs->fs_super_bh->b_data; memset (fs->fs_ondisk_sb, 0, block_size); /* fill super block fields which are constant for given version and block count */ set_sb_block_count (fs->fs_ondisk_sb, block_count); /* sb_free_blocks */ /* sb_root_block */ /* sb_journal_1st_block */ /* sb_journal_dev */ /* sb_orig_journal_size */ /* sb_joural_magic */ /* sb_journal magic_F */ /* sb_mount_id */ /* sb_not_used0 */ /* sb_generation_number */ set_sb_block_size (fs->fs_ondisk_sb, block_size); switch (version) { case REISERFS_FORMAT_3_5: set_sb_oid_maxsize (fs->fs_ondisk_sb, (block_size - SB_SIZE_V1) / sizeof(__u32) / 2 * 2); /* sb_oid_cursize */ /* sb_state */ memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_5_SUPER_MAGIC_STRING, strlen (REISERFS_3_5_SUPER_MAGIC_STRING)); break; case REISERFS_FORMAT_3_6: set_sb_oid_maxsize (fs->fs_ondisk_sb, (block_size - SB_SIZE) / sizeof(__u32) / 2 * 2); /* sb_oid_cursize */ /* sb_state */ memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_6_SUPER_MAGIC_STRING, strlen (REISERFS_3_6_SUPER_MAGIC_STRING)); break; } if (!default_journal) memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_JR_SUPER_MAGIC_STRING, strlen (REISERFS_JR_SUPER_MAGIC_STRING)); /* sb_fsck_state */ /* sb_hash_function_code */ /* sb_tree_height */ set_sb_bmap_nr (fs->fs_ondisk_sb, (block_count + (block_size * 8 - 1)) / (block_size * 8)); set_sb_version (fs->fs_ondisk_sb, version); /* sb_not_used1 */ mark_buffer_dirty (fs->fs_super_bh); fs->fs_dirt = 1; return fs; } int no_reiserfs_found (reiserfs_filsys_t * fs) { return (fs == NULL || fs->fs_blocksize == 0) ? 1 : 0; } int new_format (reiserfs_filsys_t * fs) { return fs->fs_super_bh->b_blocknr != 2; } int spread_bitmaps (reiserfs_filsys_t * fs) { return fs->fs_super_bh->b_blocknr != 2; } /* 0 means: do not guarantee that fs is consistent */ int reiserfs_is_fs_consistent (reiserfs_filsys_t * fs) { if (get_sb_umount_state (fs->fs_ondisk_sb) == FS_CLEANLY_UMOUNTED && get_sb_fs_state (fs->fs_ondisk_sb) == FS_CONSISTENT) return 1; return 0; } /* flush bitmap, brelse super block, flush all dirty buffers, close and open again the device, read super block */ static void reiserfs_only_reopen (reiserfs_filsys_t * fs, int flag) { unsigned long super_block; /* reiserfs_flush_to_ondisk_bitmap (fs->fs_bitmap2, fs);*/ super_block = fs->fs_super_bh->b_blocknr; brelse (fs->fs_super_bh); flush_buffers (fs->fs_dev); invalidate_buffers (fs->fs_dev); if (close (fs->fs_dev)) die ("reiserfs_reopen: closed failed: %s", strerror(errno)); fs->fs_dev = open (fs->fs_file_name, flag | O_LARGEFILE); if (fs->fs_dev == -1) die ("reiserfs_reopen: could not reopen device: %s", strerror(errno)); fs->fs_super_bh = bread (fs->fs_dev, super_block, fs->fs_blocksize); if (!fs->fs_super_bh) die ("reiserfs_reopen: reading super block failed"); fs->fs_ondisk_sb = (struct reiserfs_super_block *)fs->fs_super_bh->b_data; fs->fs_flags = flag; /* O_RDONLY or O_RDWR */ if (flag & O_RDWR) fs->fs_dirt = 1; else fs->fs_dirt = 0; } void reiserfs_reopen (reiserfs_filsys_t * fs, int flag) { reiserfs_only_reopen (fs, flag); reiserfs_reopen_journal (fs, flag); } int is_opened_rw (reiserfs_filsys_t * fs) { if ((fs->fs_flags) & O_RDWR) return 1; return 0; } /* flush all changes made on a filesystem */ void reiserfs_flush (reiserfs_filsys_t * fs) { if (fs->fs_dirt) { reiserfs_flush_journal (fs); flush_buffers (fs->fs_dev); } fs->fs_dirt = 0; } /* free all memory involved into manipulating with filesystem */ void reiserfs_free (reiserfs_filsys_t * fs) { reiserfs_free_journal (fs); reiserfs_free_ondisk_bitmap (fs); /* release super block and memory used by filesystem handler */ brelse (fs->fs_super_bh); fs->fs_super_bh = 0; free_buffers (); free (fs->fs_file_name); fs->fs_file_name = 0; freemem (fs); } /* this closes everything: journal. bitmap and the fs itself */ void reiserfs_close (reiserfs_filsys_t * fs) { reiserfs_close_journal (fs); reiserfs_close_ondisk_bitmap (fs); reiserfs_flush (fs); reiserfs_free (fs); fsync(fs->fs_dev); } int reiserfs_new_blocknrs (reiserfs_filsys_t * fs, unsigned long * free_blocknrs, unsigned long start, int amount_needed) { if (fs->block_allocator) return fs->block_allocator (fs, free_blocknrs, start, amount_needed); die ("block allocator is not defined\n"); return 0; } int reiserfs_free_block (reiserfs_filsys_t * fs, unsigned long block) { if (fs->block_deallocator) return fs->block_deallocator (fs, block); die ("block deallocator is not defined\n"); return 0; } /* inline int reiserfs_bin_search (void * key, void * base, int num, int width, int *ppos, comparison_fn_t comp_func) { __u32 position = *ppos; int retval; retval = reiserfs_bin_search (key, base, num, width, &position, comp_func); *ppos = position; return retval; } */ static int reiserfs_search_by_key_x (reiserfs_filsys_t * fs, struct key * key, struct path * path, int key_length) { struct buffer_head * bh; unsigned long block; struct path_element * curr; int retval; block = get_sb_root_block (fs->fs_ondisk_sb); path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET; while (1) { curr = PATH_OFFSET_PELEMENT (path, ++ path->path_length); bh = curr->pe_buffer = bread (fs->fs_dev, block, fs->fs_blocksize); if (bh == 0) { path->path_length --; pathrelse (path); return ITEM_NOT_FOUND; } retval = reiserfs_bin_search (key, B_N_PKEY (bh, 0), B_NR_ITEMS (bh), is_leaf_node (bh) ? IH_SIZE : KEY_SIZE, &(curr->pe_position), key_length == 4 ? comp_keys : comp_keys_3); if (retval == POSITION_FOUND) { /* key found, return if this is leaf level */ if (is_leaf_node (bh)) { path->pos_in_item = 0; return ITEM_FOUND; } curr->pe_position ++; } else { /* key not found in the node */ if (is_leaf_node (bh)) return ITEM_NOT_FOUND; } block = get_dc_child_blocknr (B_N_CHILD (bh, curr->pe_position)); } printf ("search_by_key: you can not get here\n"); return ITEM_NOT_FOUND; } int reiserfs_search_by_key_3 (reiserfs_filsys_t * fs, struct key * key, struct path * path) { return reiserfs_search_by_key_x (fs, key, path, 3); } int reiserfs_search_by_key_4 (reiserfs_filsys_t * fs, struct key * key, struct path * path) { return reiserfs_search_by_key_x (fs, key, path, 4); } /* key is key of byte in the regular file. This searches in tree through items and in the found item as well */ int usearch_by_position (reiserfs_filsys_t * s, struct key * key, int version, struct path * path) { struct buffer_head * bh; struct item_head * ih; struct key * next_key; if (reiserfs_search_by_key_3 (s, key, path) == ITEM_FOUND) { ih = get_ih (path); if (!is_direct_ih (ih) && !is_indirect_ih (ih)) return DIRECTORY_FOUND; path->pos_in_item = 0; return POSITION_FOUND; } bh = get_bh (path); ih = get_ih (path); if (PATH_LAST_POSITION (path) == 0) { /* previous item does not exist, that means we are in leftmost leaf of * the tree */ if (!not_of_one_file (&ih->ih_key, key)) { if (!is_direct_ih (ih) && !is_indirect_ih (ih)) return DIRECTORY_FOUND; return POSITION_NOT_FOUND; } return FILE_NOT_FOUND; } /* take previous item */ PATH_LAST_POSITION (path) --; ih --; if (not_of_one_file (&ih->ih_key, key) || is_stat_data_ih(ih)) { /* previous item belongs to another object or is a stat data, check * next item */ PATH_LAST_POSITION (path) ++; if (PATH_LAST_POSITION (path) < B_NR_ITEMS (bh)) /* next key is in the same node */ next_key = B_N_PKEY (bh, PATH_LAST_POSITION (path)); else next_key = uget_rkey (path); if (next_key == 0 || not_of_one_file (next_key, key)) { /* there is no any part of such file in the tree */ path->pos_in_item = 0; return FILE_NOT_FOUND; } if (is_direntry_key (next_key)) { reiserfs_warning (stderr, "usearch_by_position: looking for %k found a directory with the same key\n", next_key); return DIRECTORY_FOUND; } /* next item is the part of this file */ path->pos_in_item = 0; return POSITION_NOT_FOUND; } if (is_direntry_ih (ih)) { return DIRECTORY_FOUND; } if (is_stat_data_ih(ih)) { PATH_LAST_POSITION (path) ++; return FILE_NOT_FOUND; } /* previous item is part of desired file */ if (I_K_KEY_IN_ITEM (ih, key, bh->b_size)) { path->pos_in_item = get_offset (key) - get_offset (&ih->ih_key); if (is_indirect_ih (ih) ) path->pos_in_item /= bh->b_size; return POSITION_FOUND; } path->pos_in_item = is_indirect_ih (ih) ? I_UNFM_NUM (ih) : get_ih_item_len (ih); return POSITION_NOT_FOUND; } static int comp_dir_entries (const void * p1, const void * p2) { __u32 deh_offset; const __u32 * off1, * off2; off1 = p1; off2 = p2; deh_offset = le32_to_cpu (*off1); if (deh_offset < *off2) return -1; if (deh_offset > *off2) return 1; return 0; } struct key * uget_lkey (struct path * path) { int pos, offset = path->path_length; struct buffer_head * bh; if (offset < FIRST_PATH_ELEMENT_OFFSET) die ("uget_lkey: illegal offset in the path (%d)", offset); /* While not higher in path than first element. */ while (offset-- > FIRST_PATH_ELEMENT_OFFSET) { if (! buffer_uptodate (PATH_OFFSET_PBUFFER (path, offset)) ) die ("uget_lkey: parent is not uptodate"); /* Parent at the path is not in the tree now. */ if (! B_IS_IN_TREE (bh = PATH_OFFSET_PBUFFER (path, offset))) die ("uget_lkey: buffer on the path is not in tree"); /* Check whether position in the parent is correct. */ if ((pos = PATH_OFFSET_POSITION (path, offset)) > B_NR_ITEMS (bh)) die ("uget_lkey: invalid position (%d) in the path", pos); /* Check whether parent at the path really points to the child. */ if (get_dc_child_blocknr (B_N_CHILD (bh, pos)) != PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr) die ("uget_lkey: invalid block number (%d). Must be %ld", get_dc_child_blocknr (B_N_CHILD (bh, pos)), PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr); /* Return delimiting key if position in the parent is not equal to zero. */ if (pos) return B_N_PDELIM_KEY(bh, pos - 1); } /* there is no left delimiting key */ return 0; } struct key * uget_rkey (struct path * path) { int pos, offset = path->path_length; struct buffer_head * bh; if (offset < FIRST_PATH_ELEMENT_OFFSET) die ("uget_rkey: illegal offset in the path (%d)", offset); while (offset-- > FIRST_PATH_ELEMENT_OFFSET) { if (! buffer_uptodate (PATH_OFFSET_PBUFFER (path, offset))) die ("uget_rkey: parent is not uptodate"); /* Parent at the path is not in the tree now. */ if (! B_IS_IN_TREE (bh = PATH_OFFSET_PBUFFER (path, offset))) die ("uget_rkey: buffer on the path is not in tree"); /* Check whether position in the parrent is correct. */ if ((pos = PATH_OFFSET_POSITION (path, offset)) > B_NR_ITEMS (bh)) die ("uget_rkey: invalid position (%d) in the path", pos); /* Check whether parent at the path really points to the child. */ if (get_dc_child_blocknr (B_N_CHILD (bh, pos)) != PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr) die ("uget_rkey: invalid block number (%d). Must be %ld", get_dc_child_blocknr (B_N_CHILD (bh, pos)), PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr); /* Return delimiting key if position in the parent is not the last one. */ if (pos != B_NR_ITEMS (bh)) return B_N_PDELIM_KEY (bh, pos); } /* there is no right delimiting key */ return 0; } struct key * get_next_key_2 (struct path * path) { if (PATH_LAST_POSITION (path) < B_NR_ITEMS (get_bh (path)) - 1) return B_N_PKEY (get_bh (path), PATH_LAST_POSITION (path) + 1); return uget_rkey (path); } struct key * reiserfs_next_key (struct path * path) { if (get_item_pos (path) < B_NR_ITEMS (get_bh (path)) - 1) return B_N_PKEY (get_bh (path), get_item_pos (path) + 1); return uget_rkey (path); } /* NOTE: this only should be used to look for keys who exists */ int reiserfs_search_by_entry_key (reiserfs_filsys_t * fs, struct key * key, struct path * path) { struct buffer_head * bh; int item_pos; struct item_head * ih; struct key tmpkey; __u32 offset; if (reiserfs_search_by_key_4 (fs, key, path) == ITEM_FOUND) { path->pos_in_item = 0; return POSITION_FOUND; } bh = get_bh (path); item_pos = get_item_pos (path); ih = get_ih (path); if (item_pos == 0) { /* key is less than the smallest key in the tree */ if (not_of_one_file (&(ih->ih_key), key)) /* there are no items of that directory */ return DIRECTORY_NOT_FOUND; if (!is_direntry_ih (ih)) { reiserfs_panic ("reiserfs_search_by_entry_key: found item " "is not of directory type %H", ih); } /* key we looked for should be here */ path->pos_in_item = 0; return POSITION_NOT_FOUND; } /* take previous item */ item_pos --; ih --; PATH_LAST_POSITION (path) --; if (not_of_one_file (&(ih->ih_key), key) || !is_direntry_ih (ih)) { /* previous item belongs to another object or is stat data, check next item */ item_pos ++; PATH_LAST_POSITION (path) ++; if (item_pos < B_NR_ITEMS (bh)) { /* next item is in the same node */ ih ++; if (not_of_one_file (&(ih->ih_key), key)) { /* there are no items of that directory */ path->pos_in_item = 0; return DIRECTORY_NOT_FOUND; } if (!is_direntry_ih (ih)) reiserfs_panic ("_search_by_entry_key: %k is not a directory", key); } else { /* next item is in right neighboring node */ struct key * next_key = uget_rkey (path); if (next_key == 0 || not_of_one_file (next_key, key)) { /* there are no items of that directory */ path->pos_in_item = 0; return DIRECTORY_NOT_FOUND; } if (!is_direntry_key (next_key)) reiserfs_panic ("_search_by_entry_key: %k is not a directory", key); /* we got right delimiting key - search for it - the entry will be pasted in position 0 */ copy_key (&tmpkey, next_key); pathrelse (path); if (reiserfs_search_by_key_4 (fs, &tmpkey, path) != ITEM_FOUND || PATH_LAST_POSITION (path) != 0) reiserfs_panic ("_search_by_entry_key: item corresponding to delimiting key %k not found", &tmpkey); } /* next item is the part of this directory */ path->pos_in_item = 0; return POSITION_NOT_FOUND; } /* previous item is part of desired directory */ offset = get_key_offset_v1 (key); if (reiserfs_bin_search (&offset, B_I_DEH (bh, ih), get_ih_entry_count (ih), DEH_SIZE, &(path->pos_in_item), comp_dir_entries) == POSITION_FOUND) return POSITION_FOUND; return POSITION_NOT_FOUND; } void init_tb_struct (struct tree_balance * tb, reiserfs_filsys_t * fs, struct path * path, int size) { memset (tb, '\0', sizeof(struct tree_balance)); tb->tb_fs = fs; tb->tb_path = path; PATH_OFFSET_PBUFFER(path, ILLEGAL_PATH_ELEMENT_OFFSET) = NULL; PATH_OFFSET_POSITION(path, ILLEGAL_PATH_ELEMENT_OFFSET) = 0; tb->insert_size[0] = size; } int reiserfs_remove_entry (reiserfs_filsys_t * fs, struct key * key) { struct path path; struct tree_balance tb; struct item_head * ih; struct reiserfs_de_head * deh; if (reiserfs_search_by_entry_key (fs, key, &path) != POSITION_FOUND) { pathrelse (&path); return 1; } ih = get_ih (&path); if (get_ih_entry_count (ih) == 1) { init_tb_struct (&tb, fs, &path, -(IH_SIZE + get_ih_item_len (ih))); if (fix_nodes (M_DELETE, &tb, 0) != CARRY_ON) { unfix_nodes (&tb); return 1; } do_balance (&tb, 0, 0, M_DELETE, 0); return 0; } deh = B_I_DEH (get_bh (&path), ih) + path.pos_in_item; init_tb_struct (&tb, fs, &path, -(DEH_SIZE + entry_length (ih, deh, path.pos_in_item))); if (fix_nodes (M_CUT, &tb, 0) != CARRY_ON) { unfix_nodes (&tb); return 1; } do_balance (&tb, 0, 0, M_CUT, 0); return 0; } void reiserfs_paste_into_item (reiserfs_filsys_t * fs, struct path * path, const void * body, int size) { struct tree_balance tb; init_tb_struct (&tb, fs, path, size); if (fix_nodes (M_PASTE, &tb, 0/*ih*/) != CARRY_ON) reiserfs_panic ("reiserfs_paste_into_item: fix_nodes failed"); do_balance (&tb, 0, body, M_PASTE, 0/*zero num*/); } void reiserfs_insert_item (reiserfs_filsys_t * fs, struct path * path, struct item_head * ih, const void * body) { struct tree_balance tb; init_tb_struct (&tb, fs, path, IH_SIZE + get_ih_item_len(ih)); if (fix_nodes (M_INSERT, &tb, ih) != CARRY_ON) die ("reiserfs_insert_item: fix_nodes failed"); do_balance (&tb, ih, body, M_INSERT, 0/*zero num*/); } /*===========================================================================*/ static __u32 hash_value (reiserfs_filsys_t * fs, char * name) { __u32 res; if (!strcmp (name, ".")) return DOT_OFFSET; if (!strcmp (name, "..")) return DOT_DOT_OFFSET; res = reiserfs_hash (fs) (name, strlen (name)); res = GET_HASH_VALUE(res); if (res == 0) res = 128; return res; } /* if name is found in a directory - return 1 and set path to the name, otherwise return 0 and pathrelse path */ int reiserfs_locate_entry (reiserfs_filsys_t * fs, struct key * dir, char * name, struct path * path) { struct key entry_key; struct item_head * ih; struct reiserfs_de_head * deh; __u32 hash; int i, retval; struct key * rdkey; set_key_dirid (&entry_key, get_key_dirid (dir)); set_key_objectid (&entry_key, get_key_objectid (dir)); hash = hash_value (fs, name); set_key_offset_v1 (&entry_key, hash); set_key_uniqueness (&entry_key, DIRENTRY_UNIQUENESS); if (reiserfs_search_by_entry_key (fs, &entry_key, path) == DIRECTORY_NOT_FOUND) { pathrelse (path); return 0; } do { ih = get_ih (path); deh = B_I_DEH (get_bh (path), ih) + path->pos_in_item; for (i = path->pos_in_item; i < get_ih_entry_count (ih); i ++, deh ++) { if (GET_HASH_VALUE (get_deh_offset (deh)) != GET_HASH_VALUE (hash)) { /* all entries having the same hash were scanned */ pathrelse (path); return 0; } /* the name in directory has the same hash as the given name */ if ((name_in_entry_length (ih, deh, i) == (int)strlen (name)) && !memcmp (name_in_entry (deh, i), name, strlen (name))) { path->pos_in_item = i; return 1; } } rdkey = uget_rkey (path); if (!rdkey || not_of_one_file (rdkey, dir)) { pathrelse (path); return 0; } if (!is_direntry_key (rdkey)) reiserfs_panic ("reiserfs_locate_entry: can not find name in broken directory yet"); /* next item is the item of the directory we are looking name in */ if (GET_HASH_VALUE (get_offset (rdkey)) != hash) { /* but there is no names with given hash */ pathrelse (path); return 0; } /* first name of that item may be a name we are looking for */ entry_key = *rdkey; pathrelse (path); retval = reiserfs_search_by_entry_key (fs, &entry_key, path); if (retval != POSITION_FOUND) reiserfs_panic ("reiserfs_locate_entry: wrong delimiting key in the tree"); } while (1); return 0; } /* returns 0 if name is not found in a directory and 1 if name is found. Stores key found in the entry in 'key'. Returns minimal not used generation counter in 'min_gen_counter'. dies if found object is not a directory. */ int reiserfs_find_entry (reiserfs_filsys_t * fs, struct key * dir, char * name, unsigned int * min_gen_counter, struct key * key) { struct key entry_key; int retval; int i; INITIALIZE_PATH (path); struct item_head * ih; struct reiserfs_de_head * deh; struct key * rdkey; __u32 hash; set_key_dirid (&entry_key, get_key_dirid (dir)); set_key_objectid (&entry_key, get_key_objectid (dir)); hash = hash_value (fs, name); set_key_offset_v1 (&entry_key, hash); set_key_uniqueness (&entry_key, DIRENTRY_UNIQUENESS); *min_gen_counter = 0; if (reiserfs_search_by_entry_key (fs, &entry_key, &path) == DIRECTORY_NOT_FOUND) { pathrelse (&path); return 0; } do { ih = get_ih (&path); deh = B_I_DEH (get_bh (&path), ih) + path.pos_in_item; for (i = path.pos_in_item; i < get_ih_entry_count (ih); i ++, deh ++) { if (GET_HASH_VALUE (get_deh_offset (deh)) != GET_HASH_VALUE (hash)) { /* all entries having the same hash were scanned */ pathrelse (&path); return 0; } if (GET_GENERATION_NUMBER (get_deh_offset (deh)) == *min_gen_counter) (*min_gen_counter) ++; if ((name_in_entry_length (ih, deh, i) == (int)strlen (name)) && (!memcmp (name_in_entry (deh, i), name, strlen (name)))) { /* entry found in the directory */ if (key) { memset (key, 0, sizeof (struct key)); set_key_dirid (key, get_deh_dirid (deh)); set_key_objectid (key, get_deh_objectid (deh)); } pathrelse (&path); return 1;//get_deh_objectid (deh) ? get_deh_objectid (deh) : 1; } } rdkey = uget_rkey (&path); if (!rdkey || not_of_one_file (rdkey, dir)) { pathrelse (&path); return 0; } if (!is_direntry_key (rdkey)) reiserfs_panic ("reiserfs_find_entry: can not find name in broken directory yet"); /* next item is the item of the directory we are looking name in */ if (GET_HASH_VALUE (get_offset (rdkey)) != hash) { /* but there is no names with given hash */ pathrelse (&path); return 0; } /* first name of that item may be a name we are looking for */ entry_key = *rdkey; pathrelse (&path); retval = reiserfs_search_by_entry_key (fs, &entry_key, &path); if (retval != POSITION_FOUND) reiserfs_panic ("reiserfs_find_entry: wrong delimiting key in the tree"); } while (1); return 0; } /* compose directory entry: dir entry head and name itself */ char * make_entry (char * entry, char * name, struct key * key, __u32 offset) { struct reiserfs_de_head * deh; __u16 state; if (!entry) entry = getmem (DEH_SIZE + ROUND_UP (strlen (name))); memset (entry, 0, DEH_SIZE + ROUND_UP (strlen (name))); deh = (struct reiserfs_de_head *)entry; set_deh_location (deh, 0); set_deh_offset (deh, offset); state = (1 << DEH_Visible2); set_deh_state (deh, state); /* key of object entry will point to */ set_deh_dirid (deh, get_key_dirid (key)); set_deh_objectid (deh, get_key_objectid (key)); memcpy ((char *)(deh + 1), name, strlen (name)); return entry; } /* add new name into a directory. If it exists in a directory - do nothing */ int reiserfs_add_entry (reiserfs_filsys_t * fs, struct key * dir, char * name, int name_len, struct key * key, __u16 fsck_need) { struct item_head entry_ih = {{0,}, }; char * entry; int retval; INITIALIZE_PATH(path); unsigned int gen_counter; int item_len; __u32 hash; if (reiserfs_find_entry (fs, dir, name, &gen_counter, 0)) /* entry is in the directory already or directory was not found */ return 0; /* compose entry key to look for its place in the tree */ set_key_dirid (&(entry_ih.ih_key), get_key_dirid (dir)); set_key_objectid (&(entry_ih.ih_key), get_key_objectid (dir)); hash = hash_value (fs, name) + gen_counter; if (!strcmp (name, ".")) hash = DOT_OFFSET; if (!strcmp (name, "..")) hash = DOT_DOT_OFFSET; set_key_offset_v1 (&(entry_ih.ih_key), hash); set_key_uniqueness (&(entry_ih.ih_key), DIRENTRY_UNIQUENESS); set_ih_key_format (&entry_ih, KEY_FORMAT_1); set_ih_entry_count (&entry_ih, 1); item_len = DEH_SIZE + name_len; /* if (get_reiserfs_format (fs->fs_ondisk_sb) == REISERFS_FORMAT_3_5) item_len = DEH_SIZE + strlen (name); else if (get_reiserfs_format (fs->fs_ondisk_sb) == REISERFS_FORMAT_3_6) item_len = DEH_SIZE + ROUND_UP (strlen (name)); else reiserfs_panic ("unknown fs format"); */ set_ih_item_len (&entry_ih, item_len); /* fsck may need to insert item which was not reached yet */ set_ih_flags (&entry_ih, fsck_need); entry = make_entry (0, name, key, get_offset (&(entry_ih.ih_key))); retval = reiserfs_search_by_entry_key (fs, &(entry_ih.ih_key), &path); switch (retval) { case POSITION_NOT_FOUND: reiserfs_paste_into_item (fs, &path, entry, item_len); break; case DIRECTORY_NOT_FOUND: set_deh_location ((struct reiserfs_de_head *)entry, DEH_SIZE); reiserfs_insert_item (fs, &path, &entry_ih, entry); break; default: reiserfs_panic ("reiserfs_add_entry: looking for %k (inserting name \"%s\") " "search_by_entry_key returned %d", &(entry_ih.ih_key), name, retval); } freemem (entry); return item_len; } void copy_key (void * to, void * from) { memcpy (to, from, KEY_SIZE); } void copy_short_key (void * to, void * from) { memcpy (to, from, SHORT_KEY_SIZE); } void copy_item_head(void * p_v_to, void * p_v_from) { memcpy (p_v_to, p_v_from, IH_SIZE); } /* inserts new or old stat data of a directory (unreachable, nlinks == 0) */ int create_dir_sd (reiserfs_filsys_t * fs, struct path * path, struct key * key, void (*modify_item)(struct item_head *, void *)) { struct item_head ih; struct stat_data sd; int key_format; if (fs->fs_format == REISERFS_FORMAT_3_5) key_format = KEY_FORMAT_1; else key_format = KEY_FORMAT_2; make_dir_stat_data (fs->fs_blocksize, key_format, get_key_dirid (key), get_key_objectid (key), &ih, &sd); if (modify_item) modify_item (&ih, &sd); #if 0 /* set nlink count to 0 and make the item unreachable */ zero_nlink (&ih, &sd, 0); mark_item_unreachable (&ih); #endif reiserfs_insert_item (fs, path, &ih, &sd); return key_format; } void make_sure_root_dir_exists (reiserfs_filsys_t * fs, void (*modify_item)(struct item_head *, void *), int ih_flags) { INITIALIZE_PATH (path); /* is there root's stat data */ if (reiserfs_search_by_key_4 (fs, &root_dir_key, &path) == ITEM_NOT_FOUND) { root_dir_format = create_dir_sd (fs, &path, &root_dir_key, modify_item); } else { struct item_head * ih = get_ih (&path); if (!is_stat_data_ih (ih)) reiserfs_panic ("It must be root's stat data %k\n", &ih->ih_key); root_dir_format = (get_ih_item_len (get_ih (&path)) == SD_SIZE) ? KEY_FORMAT_2 : KEY_FORMAT_1; pathrelse (&path); } /* add "." and ".." if any of them do not exist. Last two parameters say: 0 - entry is not added on lost_found pass and 1 - mark item unreachable */ reiserfs_add_entry (fs, &root_dir_key, ".", name_length (".", root_dir_format), &root_dir_key, ih_flags); reiserfs_add_entry (fs, &root_dir_key, "..", name_length ("..", root_dir_format), &parent_root_dir_key, ih_flags); } /* we only can use a file for filesystem or journal if it is either not mounted block device or regular file and we are forced to use it */ int can_we_format_it (char * device_name, int force) { mode_t mode; dev_t rdev; if (is_mounted (device_name)) { /* device looks mounted */ reiserfs_warning (stderr, "'%s' looks mounted.", device_name); check_forcing_ask_confirmation (force); } mode = get_st_mode (device_name); rdev = get_st_rdev (device_name); if (!S_ISBLK (mode)) { /* file is not a block device */ reiserfs_warning (stderr, "%s is not a block special device", device_name); check_forcing_ask_confirmation (force); } else { if ((IDE_DISK_MAJOR (MAJOR(rdev)) && MINOR(rdev) % 64 == 0) || (SCSI_BLK_MAJOR (MAJOR(rdev)) && MINOR(rdev) % 16 == 0)) { /* /dev/hda or similar */ reiserfs_warning (stderr, "%s is entire device, not just one partition!", device_name); check_forcing_ask_confirmation (force); } } return 1; } int create_badblock_bitmap (reiserfs_filsys_t * fs, char * badblocks_file) { FILE * fd; char buf[128]; __u32 blocknr; int count; fd = fopen (badblocks_file, "r"); if (fd == NULL) { fprintf (stderr, "%s: could not open badblock file %s, work without it\n", __FUNCTION__, badblocks_file); return 1; } fs->fs_badblocks_bm = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_zero (fs->fs_badblocks_bm); while (!feof (fd)) { if (fgets(buf, sizeof(buf), fd) == NULL) break; count = sscanf(buf, "%u", &blocknr); if (count <= 0) continue; if (blocknr < get_sb_block_count (fs->fs_ondisk_sb) && !not_data_block (fs, blocknr)) { reiserfs_bitmap_set_bit (fs->fs_badblocks_bm, blocknr); } else { fprintf (stderr, "%s: block number %u belongs to internal reiserfs structures.\n", __FUNCTION__, blocknr); } } fclose (fd); return 0; } void add_badblock_list (reiserfs_filsys_t * fs, int no_badblock_in_tree_yet) { struct tree_balance tb; struct key badblock_key = {-1, -1, {{0, 0}}}; struct path badblock_path; struct item_head * tmp_ih; struct item_head badblock_ih; // char item[UNFM_P_SIZE]; __u32 ni; __u64 offset; __u32 i, j; if (fs->fs_badblocks_bm == NULL) return; /* delete all items with badblock_key */ while (1) { reiserfs_search_by_key_4 (fs, &badblock_key, &badblock_path); if (get_blkh_nr_items ( B_BLK_HEAD (get_bh(&badblock_path))) <= PATH_LAST_POSITION (&badblock_path)) { pathrelse (&badblock_path); break; } tmp_ih = get_ih(&badblock_path); if (get_key_dirid(&tmp_ih->ih_key) != (__u32)-1 || get_key_objectid(&tmp_ih->ih_key) != (__u32)-1 || !is_indirect_ih (tmp_ih)) { pathrelse (&badblock_path); break; } if (no_badblock_in_tree_yet) reiserfs_panic ("$s: bad block list found in the tree\n", __FUNCTION__); memset (get_item (&badblock_path), 0, get_ih_item_len (tmp_ih)); init_tb_struct (&tb, fs, &badblock_path, -(IH_SIZE + get_ih_item_len(PATH_PITEM_HEAD (&badblock_path)))); if (fix_nodes (M_DELETE, &tb, 0) != CARRY_ON) die ("%s: fix_nodes failed", __FUNCTION__); do_balance (/*tb.transaction_handle,*/ &tb, 0, 0, M_DELETE, 0/*zero num*/); } set_ih_key_format (&badblock_ih, KEY_FORMAT_2); set_ih_item_len (&badblock_ih, UNFM_P_SIZE); set_ih_free_space (&badblock_ih, 0); set_ih_location (&badblock_ih, 0); set_key_dirid (&badblock_ih.ih_key, -1); set_key_objectid (&badblock_ih.ih_key, -1); set_type (KEY_FORMAT_2, &badblock_ih.ih_key, TYPE_INDIRECT); j = 0; /* insert all badblock pointers */ for (i = 0; i < fs->fs_badblocks_bm->bm_bit_size; i++) { int retval; if (!reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i)) continue; offset = j * fs->fs_blocksize + 1; set_offset (KEY_FORMAT_2, &badblock_ih.ih_key, offset); ni = cpu_to_le32 (i); retval = usearch_by_position (fs, &badblock_ih.ih_key, key_format (&badblock_ih.ih_key), &badblock_path); switch (retval) { case (FILE_NOT_FOUND): init_tb_struct (&tb, fs, &badblock_path, IH_SIZE + get_ih_item_len(&badblock_ih)); if (fix_nodes (/*tb.transaction_handle,*/ M_INSERT, &tb, &badblock_ih/*, body*/) != CARRY_ON) die ("reiserfsck_insert_item: fix_nodes failed"); do_balance (/*tb.transaction_handle,*/ &tb, &badblock_ih, (void *)&ni , M_INSERT, 0/*zero num*/); // reiserfsck_insert_item (&badblock_path, &badblock_ih, item); break; case (POSITION_NOT_FOUND): /* take unformatted pointer from an indirect item */ init_tb_struct (&tb, fs, &badblock_path, UNFM_P_SIZE); if (fix_nodes (M_PASTE, &tb, 0) != CARRY_ON) die ("reiserfsck_paste_into_item: fix_nodes failed"); do_balance (&tb, 0, (const char *)&ni, M_PASTE, 0); // reiserfsck_file_write (&badblock_ih, item, 1 /* was in tree to avoid problems with bitmaps */); // reiserfsck_paste_into_item (path, (const char *)&ni, UNFM_P_SIZE); break; } j++; } } reiserfsprogs-3.6.9/reiserfscore/fix_node.c0000664000077100007710000022752007705261642014570 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ /** ** old_item_num ** old_entry_num ** set_entry_sizes ** create_virtual_node ** check_left ** check_right ** directory_part_size ** get_num_ver ** item_length ** set_parameters ** is_leaf_removable ** are_leaves_removable ** get_empty_nodes ** get_lfree ** get_rfree ** is_left_neighbor_in_cache ** decrement_key ** get_far_parent ** get_parents ** can_node_be_removed ** ip_check_balance ** dc_check_balance_internal ** dc_check_balance_leaf ** dc_check_balance ** check_balance ** get_direct_parent ** get_neighbors ** fix_nodes ** ** **/ #include "includes.h" /* To make any changes in the tree we find a node, that contains item to be changed/deleted or position in the node we insert a new item to. We call this node S. To do balancing we need to decide what we will shift to left/right neighbor, or to a new node, where new item will be etc. To make this analysis simpler we build virtual node. Virtual node is an array of items, that will replace items of node S. (For instance if we are going to delete an item, virtual node does not contain it). Virtual node keeps information about item sizes and types, mergeability of first and last items, sizes of all entries in directory item. We use this array of items when calculating what we can shift to neighbors and how many nodes we have to have if we do not any shiftings, if we shift to left/right neighbor or to both. */ /* taking item number in virtual node, returns number of item, that it has in source buffer */ static inline int old_item_num (int new_num, int affected_item_num, int mode) { if (mode == M_PASTE || mode == M_CUT || new_num < affected_item_num) return new_num; if (mode == M_INSERT) return new_num - 1; /* delete mode */ return new_num + 1; } /* function returns old entry number in directory item in real node using new entry number in virtual item in virtual node */ static inline int old_entry_num (int new_num, int affected_item_num, int new_entry_num, int pos_in_item, int mode) { if ( mode == M_INSERT || mode == M_DELETE) return new_entry_num; if (new_num != affected_item_num) { /* cut or paste is applied to another item */ return new_entry_num; } if (new_entry_num < pos_in_item) return new_entry_num; if (mode == M_CUT) return new_entry_num + 1; return new_entry_num - 1; } /* * Create an array of sizes of directory entries for virtual item */ static void set_entry_sizes (struct tree_balance * tb, int old_num, int new_num, struct buffer_head * bh, struct item_head * ih) { struct virtual_node * vn = tb->tb_vn; int i; struct reiserfs_de_head * deh; struct virtual_item * vi; deh = B_I_DEH (bh, ih); /* seek to given virtual item in array of virtual items */ vi = vn->vn_vi + new_num; /* virtual directory item have this amount of entry after */ vi->vi_entry_count = get_ih_entry_count (ih) + ((old_num == vn->vn_affected_item_num) ? ((vn->vn_mode == M_CUT) ? -1 : (vn->vn_mode == M_PASTE ? 1 : 0)) : 0); vi->vi_entry_sizes = (__u16 *)vn->vn_free_ptr; vn->vn_free_ptr += vi->vi_entry_count * sizeof (__u16); /* set sizes of old entries */ for (i = 0; i < vi->vi_entry_count; i ++) { int j; j = old_entry_num (old_num, vn->vn_affected_item_num, i, vn->vn_pos_in_item, vn->vn_mode); vi->vi_entry_sizes[i] = entry_length (ih, &(deh[j]), j) + DEH_SIZE; } /* set size of pasted entry */ if (old_num == vn->vn_affected_item_num && vn->vn_mode == M_PASTE) vi->vi_entry_sizes[vn->vn_pos_in_item] = tb->insert_size[0]; } static void create_virtual_node (struct tree_balance * tb, int h) { struct item_head * ih; struct virtual_node * vn = tb->tb_vn; int new_num; struct buffer_head * Sh; /* this comes from tb->S[h] */ Sh = PATH_H_PBUFFER (tb->tb_path, h); /* size of changed node */ vn->vn_size = MAX_CHILD_SIZE (Sh->b_size) - get_blkh_free_space (B_BLK_HEAD (Sh)) + tb->insert_size[h]; /* for internal nodes array if virtual items is not created */ if (h) { vn->vn_nr_item = (vn->vn_size - DC_SIZE) / (DC_SIZE + KEY_SIZE); return; } /* number of items in virtual node */ vn->vn_nr_item = B_NR_ITEMS (Sh) + ((vn->vn_mode == M_INSERT)? 1 : 0) - ((vn->vn_mode == M_DELETE)? 1 : 0); /* first virtual item */ vn->vn_vi = (struct virtual_item *)(tb->tb_vn + 1); memset (vn->vn_vi, 0, vn->vn_nr_item * sizeof (struct virtual_item)); vn->vn_free_ptr += vn->vn_nr_item * sizeof (struct virtual_item); /* first item in the node */ ih = B_N_PITEM_HEAD (Sh, 0); /* define the mergeability for 0-th item (if it is not being deleted) */ if (is_left_mergeable (tb->tb_fs, tb->tb_path) == 1 && (vn->vn_mode != M_DELETE || vn->vn_affected_item_num)) vn->vn_vi[0].vi_type |= VI_TYPE_LEFT_MERGEABLE; /* go through all items those remain in the virtual node (except for the new (inserted) one) */ for (new_num = 0; new_num < vn->vn_nr_item; new_num ++) { int j; if (vn->vn_affected_item_num == new_num && vn->vn_mode == M_INSERT) continue; /* get item number in source node */ j = old_item_num (new_num, vn->vn_affected_item_num, vn->vn_mode); vn->vn_vi[new_num].vi_item_len += get_ih_item_len (&ih[j]) + IH_SIZE; if (I_IS_STAT_DATA_ITEM (ih + j)) { vn->vn_vi[new_num].vi_type |= VI_TYPE_STAT_DATA; continue; } /* set type of item */ if (I_IS_DIRECT_ITEM (ih + j)) vn->vn_vi[new_num].vi_type |= VI_TYPE_DIRECT; if (I_IS_INDIRECT_ITEM (ih + j)) vn->vn_vi[new_num].vi_type |= VI_TYPE_INDIRECT; if (I_IS_DIRECTORY_ITEM (ih + j)) { set_entry_sizes (tb, j, new_num, Sh, ih + j); vn->vn_vi[new_num].vi_type |= VI_TYPE_DIRECTORY; if (get_key_offset_v1 (&ih[j].ih_key) == DOT_OFFSET) vn->vn_vi[new_num].vi_type |= VI_TYPE_FIRST_DIRECTORY_ITEM; } vn->vn_vi[new_num].vi_item_offset = get_offset (&(ih + j)->ih_key); if (new_num != vn->vn_affected_item_num) /* this is not being changed */ continue; if (vn->vn_mode == M_PASTE || vn->vn_mode == M_CUT) vn->vn_vi[new_num].vi_item_len += tb->insert_size[0]; } /* virtual inserted item is not defined yet */ if (vn->vn_mode == M_INSERT) { vn->vn_vi[vn->vn_affected_item_num].vi_item_len = tb->insert_size[0]; vn->vn_vi[vn->vn_affected_item_num].vi_item_offset = get_offset (&vn->vn_ins_ih->ih_key); switch (get_type (&vn->vn_ins_ih->ih_key)) { case TYPE_STAT_DATA: vn->vn_vi[vn->vn_affected_item_num].vi_type |= VI_TYPE_STAT_DATA; break; case TYPE_DIRECT: vn->vn_vi[vn->vn_affected_item_num].vi_type |= VI_TYPE_DIRECT; break; case TYPE_INDIRECT: vn->vn_vi[vn->vn_affected_item_num].vi_type |= VI_TYPE_INDIRECT; break; default: /* inseted item is directory (it must be item with "." and "..") */ vn->vn_vi[vn->vn_affected_item_num].vi_type |= (VI_TYPE_DIRECTORY | VI_TYPE_FIRST_DIRECTORY_ITEM | VI_TYPE_INSERTED_DIRECTORY_ITEM); /* this directory item can not be split, so do not set sizes of entries */ break; } } /* set right merge flag we take right delimiting key and check whether it is a mergeable item */ if (tb->CFR[0]) { ih = (struct item_head *)B_N_PDELIM_KEY (tb->CFR[0], tb->rkey[0]); if (is_right_mergeable (tb->tb_fs, tb->tb_path) == 1 && (vn->vn_mode != M_DELETE || vn->vn_affected_item_num != B_NR_ITEMS (Sh) - 1)) vn->vn_vi[vn->vn_nr_item-1].vi_type |= VI_TYPE_RIGHT_MERGEABLE; } } /* using virtual node check, how many items can be shifted to left neighbor */ static int check_left (struct tree_balance * tb, int h, int cur_free) { int i; struct virtual_node * vn = tb->tb_vn; int d_size, ih_size, bytes = -1; /* internal level */ if (h > 0) { if (!cur_free ) { tb->lnum[h] = 0; return 0; } tb->lnum[h] = cur_free / (DC_SIZE + KEY_SIZE); return -1; } /* leaf level */ if (!cur_free || !vn->vn_nr_item) { /* no free space */ tb->lnum[h] = 0; tb->lbytes = -1; return 0; } if ((unsigned int)cur_free >= (vn->vn_size - ((vn->vn_vi[0].vi_type & VI_TYPE_LEFT_MERGEABLE) ? IH_SIZE : 0))) { /* all contents of S[0] fits into L[0] */ tb->lnum[0] = vn->vn_nr_item; tb->lbytes = -1; return -1; } d_size = 0, ih_size = IH_SIZE; /* first item may be merge with last item in left neighbor */ if (vn->vn_vi[0].vi_type & VI_TYPE_LEFT_MERGEABLE) d_size = -((int)IH_SIZE), ih_size = 0; tb->lnum[0] = 0; for (i = 0; i < vn->vn_nr_item; i ++, ih_size = IH_SIZE, d_size = 0) { d_size += vn->vn_vi[i].vi_item_len; if (cur_free >= d_size) { /* the item can be shifted entirely */ cur_free -= d_size; tb->lnum[0] ++; continue; } /* the item cannot be shifted entirely, try to split it */ /* check whether L[0] can hold ih and at least one byte of the item body */ if (cur_free <= ih_size) { /* cannot shift even a part of the current item */ tb->lbytes = -1; return -1; } cur_free -= ih_size; if (vn->vn_vi[i].vi_type & VI_TYPE_STAT_DATA || vn->vn_vi[i].vi_type & VI_TYPE_INSERTED_DIRECTORY_ITEM) { /* virtual item is a stat_data or empty directory body ("." and ".."), that is not split able */ tb->lbytes = -1; return -1; } if (vn->vn_vi[i].vi_type & VI_TYPE_DIRECT) { /* body of a direct item can be split by 8 bytes */ int align = 8 - (vn->vn_vi[i].vi_item_offset - 1) % 8; // reiserfs_warning(stderr,"\nbalancing: cur_free (%d) ", cur_free); tb->lbytes = bytes = (cur_free >= align) ? (align + ((cur_free - align) / 8 * 8)) : 0; // reiserfs_warning(stderr,"offset (0x%Lx), move_left (%d), get offset (0x%Lx)", // vn->vn_vi[i].vi_item_offset, bytes, vn->vn_vi[i].vi_item_offset + bytes); } if (vn->vn_vi[i].vi_type & VI_TYPE_INDIRECT) /* body of a indirect item can be split at unformatted pointer bound */ tb->lbytes = bytes = cur_free - cur_free % UNFM_P_SIZE; /* item is of directory type */ if (vn->vn_vi[i].vi_type & VI_TYPE_DIRECTORY) { /* directory entries are the solid granules of the directory item, they cannot be split in the middle */ /* calculate number of dir entries that can be shifted, and their total size */ int j; struct virtual_item * vi; tb->lbytes = 0; bytes = 0; vi = &vn->vn_vi[i]; for (j = 0; j < vi->vi_entry_count; j ++) { if (vi->vi_entry_sizes[j] > cur_free) /* j-th entry doesn't fit into L[0] */ break; bytes += vi->vi_entry_sizes[j]; cur_free -= vi->vi_entry_sizes[j]; tb->lbytes ++; } /* "." can not be cut from first directory item */ if ((vn->vn_vi[i].vi_type & VI_TYPE_FIRST_DIRECTORY_ITEM) && tb->lbytes < 2) tb->lbytes = 0; } if (tb->lbytes <= 0) { /* nothing can flow from the item */ tb->lbytes = -1; return -1; } /* something can flow from the item */ tb->lnum[0] ++; return bytes; /* part of split item in bytes */ } reiserfs_panic (0, "vs-8065: check_left: all items fit in the left neighbor"); return 0; } /* using virtual node check, how many items can be shifted to right neighbor */ static int check_right (struct tree_balance * tb, int h, int cur_free) { int i; struct virtual_node * vn = tb->tb_vn; int d_size, ih_size, bytes = -1; /* internal level */ if (h > 0) { if (!cur_free) { tb->rnum[h] = 0; return 0; } tb->rnum[h] = cur_free / (DC_SIZE + KEY_SIZE); return -1; } /* leaf level */ if (!cur_free || !vn->vn_nr_item) { /* no free space */ tb->rnum[h] = 0; tb->rbytes = -1; return 0; } if ((unsigned int)cur_free >= (vn->vn_size - ((vn->vn_vi[vn->vn_nr_item-1].vi_type & VI_TYPE_RIGHT_MERGEABLE) ? IH_SIZE : 0))) { /* all contents of S[0] fits into R[0] */ tb->rnum[h] = vn->vn_nr_item; tb->rbytes = -1; return -1; } d_size = 0, ih_size = IH_SIZE; /* last item may be merge with first item in right neighbor */ if (vn->vn_vi[vn->vn_nr_item - 1].vi_type & VI_TYPE_RIGHT_MERGEABLE) d_size = -(int)IH_SIZE, ih_size = 0; tb->rnum[0] = 0; for (i = vn->vn_nr_item - 1; i >= 0; i --, d_size = 0, ih_size = IH_SIZE) { d_size += vn->vn_vi[i].vi_item_len; if (cur_free >= d_size) { /* the item can be shifted entirely */ cur_free -= d_size; tb->rnum[0] ++; continue; } /* the item cannot be shifted entirely, try to split it */ if (vn->vn_vi[i].vi_type & VI_TYPE_STAT_DATA || vn->vn_vi[i].vi_type & VI_TYPE_INSERTED_DIRECTORY_ITEM) { /* virtual item is a stat_data or empty directory body ("." and "..), that is not split able */ tb->rbytes = -1; return -1; } /* check whether R[0] can hold ih and at least one byte of the item body */ if ( cur_free <= ih_size ) { /* cannot shift even a part of the current item */ tb->rbytes = -1; return -1; } /* R[0] can hold the header of the item and at least one byte of its body */ cur_free -= ih_size; /* cur_free is still > 0 */ /* item is of direct type */ if (vn->vn_vi[i].vi_type & VI_TYPE_DIRECT) { /* body of a direct item can be split by 8 bytes */ int align = vn->vn_vi[i].vi_item_len % 8; // reiserfs_warning(stderr,"\nbalancing: cur_free (%d) ", cur_free); tb->rbytes = bytes = (cur_free >= align) ? (align + ((cur_free - align) / 8 * 8)) : 0; // reiserfs_warning(stderr, "offset (0x%Lx) len (%d), move right (%d), get offset (0x%Lx)", // vn->vn_vi[i].vi_item_offset, vn->vn_vi[i].vi_item_len, bytes, // vn->vn_vi[i].vi_item_offset + vn->vn_vi[i].vi_item_len - bytes); } /* item is of indirect type */ if (vn->vn_vi[i].vi_type & VI_TYPE_INDIRECT) /* an unformatted node pointer (having size long) is a solid granule of the item */ tb->rbytes = bytes = cur_free - cur_free % UNFM_P_SIZE; /* item is of directory type */ if (vn->vn_vi[i].vi_type & VI_TYPE_DIRECTORY) { int j; struct virtual_item * vi; tb->rbytes = 0; bytes = 0; vi = &vn->vn_vi[i]; for (j = vi->vi_entry_count - 1; j >= 0; j --) { if (vi->vi_entry_sizes[j] > cur_free) /* j-th entry doesn't fit into L[0] */ break; bytes += vi->vi_entry_sizes[j]; cur_free -= vi->vi_entry_sizes[j]; tb->rbytes ++; } /* ".." can not be cut from first directory item */ if ((vn->vn_vi[i].vi_type & VI_TYPE_FIRST_DIRECTORY_ITEM) && tb->rbytes > vi->vi_entry_count - 2) tb->rbytes = vi->vi_entry_count - 2; } if ( tb->rbytes <= 0 ) { /* nothing can flow from the item */ tb->rbytes = -1; return -1; } /* something can flow from the item */ tb->rnum[0] ++; return bytes; /* part of split item in bytes */ } reiserfs_panic ("vs-8095: check_right: all items fit in the left neighbor"); return 0; } /* sum of entry sizes between from-th and to-th entries including both edges */ static int directory_part_size (struct virtual_item * vi, int from, int to) { int i, retval; retval = 0; for (i = from; i <= to; i ++) retval += vi->vi_entry_sizes[i]; return retval; } /* * from - number of items, which are shifted to left neighbor entirely * to - number of item, which are shifted to right neighbor entirely * from_bytes - number of bytes of boundary item (or directory entries) which * are shifted to left neighbor * to_bytes - number of bytes of boundary item (or directory entries) which * are shifted to right neighbor */ static int get_num_ver (int mode, struct tree_balance * tb, int h, int from, int from_bytes, int to, int to_bytes, short * snum012, int flow ) { int i; int bytes; struct virtual_node * vn = tb->tb_vn; struct virtual_item * vi; int total_node_size, max_node_size, current_item_size; int needed_nodes; int start_item, /* position of item we start filling node from */ end_item, /* position of item we finish filling node by */ start_bytes,/* number of first bytes (entries for directory) of start_item-th item we do not include into node that is being filled */ end_bytes; /* number of last bytes (entries for directory) of end_item-th item we do node include into node that is being filled */ int splitted_item_positions[2]; /* these are positions in virtual item of items, that are splitted between S[0] and S1new and S1new and S2new */ max_node_size = MAX_CHILD_SIZE (tb->tb_fs->fs_blocksize); /* snum012 [0-2] - number of items, that lay to S[0], first new node and second new node */ snum012[3] = -1; /* s1bytes */ snum012[4] = -1; /* s2bytes */ /* internal level */ if (h > 0) { i = ((to - from) * (KEY_SIZE + DC_SIZE) + DC_SIZE); if (i == max_node_size) return 1; return (i / max_node_size + 1); } /* leaf level */ needed_nodes = 1; total_node_size = 0; start_item = from; start_bytes = from_bytes; end_item = vn->vn_nr_item - to - 1; end_bytes = to_bytes; /* go through all items begining from the start_item-th item and ending by the end_item-th item. If start_bytes != -1 we skip first start_bytes item units (entries in case of directory). If end_bytes != -1 we skip end_bytes units of the end_item-th item. */ for (i = start_item; i <= end_item; i ++) { /* get size of current item */ current_item_size = (vi = &vn->vn_vi[i])->vi_item_len; /* do not take in calculation head part (from_bytes) of from-th item */ if (i == start_item && start_bytes != -1) { if (vi->vi_type & VI_TYPE_DIRECTORY) current_item_size -= directory_part_size (vi, 0, start_bytes - 1); else current_item_size -= start_bytes; } /* do not take in calculation tail part of (to-1)-th item */ if (i == end_item && end_bytes != -1) { if (vi->vi_type & VI_TYPE_DIRECTORY) /* first entry, that is not included */ current_item_size -= directory_part_size (vi, vi->vi_entry_count - end_bytes, vi->vi_entry_count - 1); else current_item_size -= end_bytes; } /* if item fits into current node entirely */ if (total_node_size + current_item_size <= max_node_size) { snum012[needed_nodes - 1] ++; total_node_size += current_item_size; continue; } if (current_item_size > max_node_size) /* virtual item length is longer, than max size of item in a node. It is impossible for direct item */ /* we will try to split it */ flow = 1; if (!flow) { /* as we do not split items, take new node and continue */ needed_nodes ++; i --; total_node_size = 0; continue; } if (total_node_size + (int)IH_SIZE >= max_node_size) { /* even minimal item does not fit into current node, take new node and continue */ needed_nodes ++, i--, total_node_size = 0; continue; } if (vi->vi_type & VI_TYPE_STAT_DATA) { /* stat data can not be split */ needed_nodes ++, i--, total_node_size = 0; continue; } /*bytes is free space in filled node*/ bytes = max_node_size - total_node_size - IH_SIZE; if (vi->vi_type & VI_TYPE_DIRECT) { /* body of a direct item can be split by 8 bytes. */ int align = 8 - (vn->vn_vi[i].vi_item_offset - 1) % 8; // reiserfs_warning(stderr,"\nbalancing: cur_free (%d) ", bytes); // reiserfs_warning(stderr,"offset (0x%Lx), move (%d), get offset (0x%Lx)", // vn->vn_vi[i].vi_item_offset, (bytes - align) / 8 * 8, // vn->vn_vi[i].vi_item_offset + ((bytes - align) / 8 * 8)); bytes = (bytes >= align) ? (align + ((bytes - align) / 8 * 8)) : 0; } /* item is of indirect type */ if (vi->vi_type & VI_TYPE_INDIRECT) /* an unformatted node pointer (having size long) is a solid granule of the item. bytes of unformatted node pointers fits into free space of filled node */ bytes -= (bytes) % UNFM_P_SIZE; /* S1bytes or S2bytes. It depends from needed_nodes */ snum012[needed_nodes - 1 + 3] = bytes; /* item is of directory type */ if (vi->vi_type & VI_TYPE_DIRECTORY) { /* calculate, how many entries can be put into current node */ int j; int end_entry; snum012[needed_nodes - 1 + 3] = 0; total_node_size += IH_SIZE; if (start_bytes == -1 || i != start_item) start_bytes = 0; end_entry = vi->vi_entry_count - ((i == end_item && end_bytes != -1) ? end_bytes : 0); for (j = start_bytes; j < end_entry; j ++) { /* j-th entry doesn't fit into current node */ if (total_node_size + vi->vi_entry_sizes[j] > max_node_size) break; snum012[needed_nodes - 1 + 3] ++; bytes += vi->vi_entry_sizes[j]; total_node_size += vi->vi_entry_sizes[j]; } /* "." can not be cut from first directory item */ if (start_bytes == 0 && (vn->vn_vi[i].vi_type & VI_TYPE_FIRST_DIRECTORY_ITEM) && snum012[needed_nodes - 1 + 3] < 2) snum012[needed_nodes - 1 + 3] = 0; } if (snum012[needed_nodes-1+3] <= 0 ) { /* nothing fits into current node, take new node and continue */ needed_nodes ++, i--, total_node_size = 0; continue; } /* something fits into the current node */ if (vi->vi_type & VI_TYPE_DIRECTORY) start_bytes += snum012[needed_nodes - 1 + 3]; else start_bytes = bytes; snum012[needed_nodes - 1] ++; splitted_item_positions[needed_nodes - 1] = i; needed_nodes ++; /* continue from the same item with start_bytes != -1 */ start_item = i; i --; total_node_size = 0; } /* snum012[3] and snum012[4] contain how many bytes (entries) of split item can be in S[0] and S1new. s1bytes and s2bytes are how many bytes (entries) can be in S1new and S2new. Recalculate it */ if (snum012[4] > 0) { /* s2bytes */ /* get number of item that is split between S1new and S2new */ int split_item_num; int bytes_to_r, bytes_to_l; split_item_num = splitted_item_positions[1]; bytes_to_l = ((from == split_item_num && from_bytes != -1) ? from_bytes : 0); bytes_to_r = ((end_item == split_item_num && end_bytes != -1) ? end_bytes : 0); if (vn->vn_vi[split_item_num].vi_type & VI_TYPE_DIRECTORY) { int entries_to_S2new; /* calculate number of entries fit into S2new */ entries_to_S2new = vn->vn_vi[split_item_num].vi_entry_count - snum012[4] - bytes_to_r - bytes_to_l; if (snum012[3] != -1 && snum012[1] == 1) { /* directory split into 3 nodes */ int entries_to_S1new; entries_to_S2new -= snum012[3]; entries_to_S1new = snum012[4]; snum012[3] = entries_to_S1new; snum012[4] = entries_to_S2new; return needed_nodes; } snum012[4] = entries_to_S2new; } else { /* item is not of directory type */ int bytes_to_S2new; bytes_to_S2new = vn->vn_vi[split_item_num].vi_item_len - IH_SIZE - snum012[4] - bytes_to_r - bytes_to_l; snum012[4] = bytes_to_S2new; } } /* now we know S2bytes, calculate S1bytes */ if (snum012[3] > 0) { /* s1bytes */ /* get number of item that is split between S0 and S1new */ int split_item_num; int bytes_to_r, bytes_to_l; split_item_num = splitted_item_positions[0]; bytes_to_l = ((from == split_item_num && from_bytes != -1) ? from_bytes : 0); bytes_to_r = ((end_item == split_item_num && end_bytes != -1) ? end_bytes : 0); if (vn->vn_vi[split_item_num].vi_type & VI_TYPE_DIRECTORY) { /* entries, who go to S1new node */ snum012[3] = vn->vn_vi[split_item_num].vi_entry_count - snum012[3] - bytes_to_r - bytes_to_l; } else /* bytes, who go to S1new node (not including HI_SIZE) */ snum012[3] = vn->vn_vi[split_item_num].vi_item_len - IH_SIZE - snum012[3] - bytes_to_r - bytes_to_l; } return needed_nodes; } /* size of item_num-th item in bytes when regular and in entries when item is directory */ static int item_length (struct tree_balance * tb, int item_num) { struct virtual_node * vn = tb->tb_vn; if (vn->vn_vi[item_num].vi_type & VI_TYPE_DIRECTORY) return vn->vn_vi[item_num].vi_entry_count; return vn->vn_vi[item_num].vi_item_len - IH_SIZE; } /* Set parameters for balancing. * Performs write of results of analysis of balancing into structure tb, * where it will later be used by the functions that actually do the balancing. * Parameters: * tb tree_balance structure; * h current level of the node; * lnum number of items from S[h] that must be shifted to L[h]; * rnum number of items from S[h] that must be shifted to R[h]; * blk_num number of blocks that S[h] will be splitted into; * s012 number of items that fall into splitted nodes. * lbytes number of bytes which flow to the left neighbor from the item that is not * not shifted entirely * rbytes number of bytes which flow to the right neighbor from the item that is not * not shifted entirely * s1bytes number of bytes which flow to the first new node when S[0] splits (this number is contained in s012 array) */ static void set_parameters (struct tree_balance * tb, int h, int lnum, int rnum, int blk_num, short * s012, int lb, int rb) { tb->lnum[h] = lnum; tb->rnum[h] = rnum; tb->blknum[h] = blk_num; if (h == 0) { /* only for leaf level */ if (s012 != NULL) { tb->s0num = * s012 ++, tb->s1num = * s012 ++, tb->s2num = * s012 ++; tb->s1bytes = * s012 ++; tb->s2bytes = * s012; } tb->lbytes = lb; tb->rbytes = rb; } } static void decrement_key (struct key * p_s_key) { int type; type = get_type (p_s_key); switch (type) { case TYPE_STAT_DATA: set_key_objectid (p_s_key, get_key_objectid (p_s_key) - 1); set_type_and_offset (key_format (p_s_key), p_s_key, (loff_t)MAX_FILE_SIZE_V2, TYPE_INDIRECT); return; case TYPE_INDIRECT: case TYPE_DIRECT: case TYPE_DIRENTRY: set_offset (key_format (p_s_key), p_s_key, get_offset (p_s_key) - 1); if (get_offset (p_s_key) == 0) set_type (key_format (p_s_key), p_s_key, TYPE_STAT_DATA); return; } reiserfs_warning (stderr, "vs-8125: decrement_key: item of wrong type found %k", p_s_key); } int are_items_mergeable (struct item_head * left, struct item_head * right, int bsize) { if (comp_keys (&left->ih_key, &right->ih_key) != -1) { reiserfs_panic ("vs-16070: are_items_mergeable: left %k, right %k", &(left->ih_key), &(right->ih_key)); } if (not_of_one_file (&left->ih_key, &right->ih_key)) return 0; if (I_IS_DIRECTORY_ITEM (left)) { return 1; } if ((I_IS_DIRECT_ITEM (left) && I_IS_DIRECT_ITEM (right)) || (I_IS_INDIRECT_ITEM (left) && I_IS_INDIRECT_ITEM (right))) return (get_offset (&left->ih_key) + get_bytes_number (left, bsize) == get_offset (&right->ih_key)) ? 1 : 0; return 0; } /* get left neighbor of the leaf node */ static struct buffer_head * get_left_neighbor (reiserfs_filsys_t * s, struct path * path) { struct key key; struct path path_to_left_neighbor; struct buffer_head * bh; copy_key (&key, B_N_PKEY (PATH_PLAST_BUFFER (path), 0)); decrement_key (&key); init_path (&path_to_left_neighbor); search_by_key (s, &key, &path_to_left_neighbor, DISK_LEAF_NODE_LEVEL); if (PATH_LAST_POSITION (&path_to_left_neighbor) == 0) { pathrelse (&path_to_left_neighbor); return 0; } bh = PATH_PLAST_BUFFER (&path_to_left_neighbor); bh->b_count ++; pathrelse (&path_to_left_neighbor); return bh; } extern struct key MIN_KEY; static struct buffer_head * get_right_neighbor (reiserfs_filsys_t * s, struct path * path) { struct key key; struct key * rkey; struct path path_to_right_neighbor; struct buffer_head * bh; rkey = get_rkey (path, s); if (comp_keys (rkey, &MIN_KEY) == 0) reiserfs_panic ("vs-16080: get_right_neighbor: get_rkey returned min key (path has changed)"); copy_key (&key, rkey); init_path (&path_to_right_neighbor); search_by_key (s, &key, &path_to_right_neighbor, DISK_LEAF_NODE_LEVEL); if (PATH_PLAST_BUFFER (&path_to_right_neighbor) == PATH_PLAST_BUFFER (path)) { pathrelse (&path_to_right_neighbor); return 0; } bh = PATH_PLAST_BUFFER (&path_to_right_neighbor); bh->b_count ++; pathrelse (&path_to_right_neighbor); return bh; } int is_left_mergeable (reiserfs_filsys_t * s, struct path * path) { struct item_head * right; struct buffer_head * bh; int retval; right = B_N_PITEM_HEAD (PATH_PLAST_BUFFER (path), 0); bh = get_left_neighbor (s, path); if (bh == 0) { return 0; } retval = are_items_mergeable (B_N_PITEM_HEAD (bh, B_NR_ITEMS (bh) - 1), right, bh->b_size); brelse (bh); return retval; } int is_right_mergeable (reiserfs_filsys_t * s, struct path * path) { struct item_head * left; struct buffer_head * bh; int retval; left = B_N_PITEM_HEAD (PATH_PLAST_BUFFER (path), B_NR_ITEMS (PATH_PLAST_BUFFER (path)) - 1); bh = get_right_neighbor (s, path); if (bh == 0) { return 0; } retval = are_items_mergeable (left, B_N_PITEM_HEAD (bh, 0), bh->b_size); brelse (bh); return retval; } /* check, does node disappear if we shift tb->lnum[0] items to left neighbor and tb->rnum[0] to the right one. */ static int is_leaf_removable (struct tree_balance * tb) { struct virtual_node * vn = tb->tb_vn; int to_left, to_right; int size; int remain_items; /* number of items, that will be shifted to left (right) neighbor entirely */ to_left = tb->lnum[0] - ((tb->lbytes != -1) ? 1 : 0); to_right = tb->rnum[0] - ((tb->rbytes != -1) ? 1 : 0); remain_items = vn->vn_nr_item; /* how many items remain in S[0] after shiftings to neighbors */ remain_items -= (to_left + to_right); if (remain_items < 1) { /* all content of node can be shifted to neighbors */ set_parameters (tb, 0, to_left, vn->vn_nr_item - to_left, 0, NULL, -1, -1); return 1; } if (remain_items > 1 || tb->lbytes == -1 || tb->rbytes == -1) /* S[0] is not removable */ return 0; /* check, whether we can divide 1 remaining item between neighbors */ /* get size of remaining item (in directory entry count if directory) */ size = item_length (tb, to_left); if (tb->lbytes + tb->rbytes >= size) { set_parameters (tb, 0, to_left + 1, to_right + 1, 0, NULL, tb->lbytes, -1); return 1; } return 0; } /* check whether L, S, R can be joined in one node */ static int are_leaves_removable (struct tree_balance * tb, int lfree, int rfree) { struct virtual_node * vn = tb->tb_vn; int ih_size; struct buffer_head *S0; S0 = PATH_H_PBUFFER (tb->tb_path, 0); ih_size = 0; if (vn->vn_nr_item) { if (vn->vn_vi[0].vi_type & VI_TYPE_LEFT_MERGEABLE) ih_size += IH_SIZE; if (vn->vn_vi[vn->vn_nr_item-1].vi_type & VI_TYPE_RIGHT_MERGEABLE) ih_size += IH_SIZE; } else { /* there was only one item and it will be deleted */ struct item_head * ih; ih = B_N_PITEM_HEAD (S0, 0); if (tb->CFR[0] && !not_of_one_file (&(ih->ih_key), B_N_PDELIM_KEY (tb->CFR[0], tb->rkey[0]))) if (I_IS_DIRECTORY_ITEM(ih)) { /* we can delete any directory item in fsck (if it is unreachable) */ if (get_offset (&ih->ih_key) != DOT_OFFSET) { /* must get left neighbor here to make sure, that left neighbor is of the same directory */ struct buffer_head * left; left = get_left_neighbor (tb->tb_fs, tb->tb_path); if (left) { struct item_head * last; if (B_NR_ITEMS (left) == 0) reiserfs_panic ("vs-8135: are_leaves_removable: " "empty node in the tree"); last = B_N_PITEM_HEAD (left, B_NR_ITEMS (left) - 1); if (!comp_short_keys (&last->ih_key, &ih->ih_key)) ih_size = IH_SIZE; brelse (left); } } } } if ((int)MAX_CHILD_SIZE(S0->b_size) + vn->vn_size <= rfree + lfree + ih_size) { set_parameters (tb, 0, -1, -1, -1, NULL, -1, -1); return 1; } return 0; } /* when we do not split item, lnum and rnum are numbers of entire items */ #define SET_PAR_SHIFT_LEFT \ if (h)\ {\ int to_l;\ \ to_l = (MAX_NR_KEY(Sh)+1 - lpar + vn->vn_nr_item + 1) / 2 -\ (MAX_NR_KEY(Sh) + 1 - lpar);\ \ set_parameters (tb, h, to_l, 0, lnver, NULL, -1, -1);\ }\ else \ {\ if (lset==LEFT_SHIFT_FLOW)\ set_parameters (tb, h, lpar, 0, lnver, snum012+lset,\ tb->lbytes, -1);\ else\ set_parameters (tb, h, lpar - (tb->lbytes!=-1), 0, lnver, snum012+lset,\ -1, -1);\ } #define SET_PAR_SHIFT_RIGHT \ if (h)\ {\ int to_r;\ \ to_r = (MAX_NR_KEY(Sh)+1 - rpar + vn->vn_nr_item + 1) / 2 - (MAX_NR_KEY(Sh) + 1 - rpar);\ \ set_parameters (tb, h, 0, to_r, rnver, NULL, -1, -1);\ }\ else \ {\ if (rset==RIGHT_SHIFT_FLOW)\ set_parameters (tb, h, 0, rpar, rnver, snum012+rset,\ -1, tb->rbytes);\ else\ set_parameters (tb, h, 0, rpar - (tb->rbytes!=-1), rnver, snum012+rset,\ -1, -1);\ } /* Get new buffers for storing new nodes that are created while balancing. * Returns: SCHEDULE_OCCURED - schedule occured while the function worked; * CARRY_ON - schedule didn't occur while the function worked; * NO_DISK_SPACE - no disk space. */ static int get_empty_nodes (struct tree_balance * p_s_tb, int n_h) { struct buffer_head * p_s_new_bh, * p_s_Sh = PATH_H_PBUFFER (p_s_tb->tb_path, n_h); unsigned long * p_n_blocknr, a_n_blocknrs[MAX_AMOUNT_NEEDED] = {0, }; int n_counter, n_number_of_freeblk, n_amount_needed,/* number of needed empty blocks */ n_repeat; reiserfs_filsys_t * fs = p_s_tb->tb_fs; if (n_h == 0 && p_s_tb->insert_size[n_h] == 0x7fff) return CARRY_ON; /* number_of_freeblk is the number of empty blocks which have been acquired for use by the balancing algorithm minus the number of empty blocks used in the previous levels of the analysis, number_of_freeblk = tb->cur_blknum can be non-zero if a schedule occurs after empty blocks are acquired, and the balancing analysis is then restarted, amount_needed is the number needed by this level (n_h) of the balancing analysis. Note that for systems with many processes writing, it would be more layout optimal to calculate the total number needed by all levels and then to run reiserfs_new_blocks to get all of them at once. */ /* Initiate number_of_freeblk to the amount acquired prior to the restart of the analysis or 0 if not restarted, then subtract the amount needed by all of the levels of the tree below n_h. */ /* blknum includes S[n_h], so we subtract 1 in this calculation */ for ( n_counter = 0, n_number_of_freeblk = p_s_tb->cur_blknum; n_counter < n_h; n_counter++ ) n_number_of_freeblk -= ( p_s_tb->blknum[n_counter] ) ? (p_s_tb->blknum[n_counter] - 1) : 0; /* Allocate missing empty blocks. */ /* if p_s_Sh == 0 then we are getting a new root */ n_amount_needed = ( p_s_Sh ) ? (p_s_tb->blknum[n_h] - 1) : 1; /* Amount_needed = the amount that we need more than the amount that we have. */ if ( n_amount_needed > n_number_of_freeblk ) n_amount_needed -= n_number_of_freeblk; else /* If we have enough already then there is nothing to do. */ return CARRY_ON; if ( (n_repeat = reiserfs_new_blocknrs (p_s_tb->tb_fs, a_n_blocknrs, PATH_PLAST_BUFFER(p_s_tb->tb_path)->b_blocknr, n_amount_needed)) != CARRY_ON ) { return n_repeat; /* Out of disk space. */ } /* for each blocknumber we just got, get a buffer and stick it on FEB */ for ( p_n_blocknr = a_n_blocknrs, n_counter = 0; n_counter < n_amount_needed; p_n_blocknr++, n_counter++ ) { p_s_new_bh = getblk (fs->fs_dev, *p_n_blocknr, fs->fs_blocksize); if (p_s_new_bh->b_count > 1) { die ("get_empty_nodes: not free empty buffer"); } /* Put empty buffers into the array. */ p_s_tb->FEB[p_s_tb->cur_blknum++] = p_s_new_bh; } return CARRY_ON; } /* Get free space of the left neighbor, * which is stored in the parent node of the left neighbor. */ static int get_lfree (struct tree_balance * tb, int h) { struct buffer_head * l, * f; int order; if ((f = PATH_H_PPARENT (tb->tb_path, h)) == 0 || (l = tb->FL[h]) == 0) return 0; if (f == l) order = PATH_H_B_ITEM_ORDER (tb->tb_path, h) - 1; else { order = get_blkh_nr_items (B_BLK_HEAD(l)); f = l; } if (get_dc_child_size (B_N_CHILD(f,order)) == 0) { reiserfs_warning (stderr, "get_lfree: block %u block_head %z has bad child pointer %y, order %d\n", l->b_blocknr, l, B_N_CHILD(f,order), order); } return (MAX_CHILD_SIZE(f->b_size) - get_dc_child_size (B_N_CHILD(f,order))); } /* Get free space of the right neighbor, which is stored in the parent node of * the right neighbor. */ static int get_rfree (struct tree_balance * tb, int h) { struct buffer_head * r, * f; int order; if ((f = PATH_H_PPARENT (tb->tb_path, h)) == 0 || (r = tb->FR[h]) == 0) return 0; if (f == r) order = PATH_H_B_ITEM_ORDER (tb->tb_path, h) + 1; else { order = 0; f = r; } return (MAX_CHILD_SIZE(f->b_size) - get_dc_child_size (B_N_CHILD(f,order))); } /* Check whether left neighbor is in memory. */ static int is_left_neighbor_in_cache (struct tree_balance * p_s_tb, int n_h) { struct buffer_head * p_s_father; reiserfs_filsys_t * fs = p_s_tb->tb_fs; unsigned long n_left_neighbor_blocknr; int n_left_neighbor_position; if ( ! p_s_tb->FL[n_h] ) /* Father of the left neighbor does not exist. */ return 0; /* Calculate father of the node to be balanced. */ p_s_father = PATH_H_PBUFFER(p_s_tb->tb_path, n_h + 1); /* Get position of the pointer to the left neighbor into the left father. */ n_left_neighbor_position = ( p_s_father == p_s_tb->FL[n_h] ) ? p_s_tb->lkey[n_h] : get_blkh_nr_items (B_BLK_HEAD(p_s_tb->FL[n_h])); /* Get left neighbor block number. */ n_left_neighbor_blocknr = get_dc_child_blocknr (B_N_CHILD (p_s_tb->FL[n_h], n_left_neighbor_position)); /* Look for the left neighbor in the cache. */ if ( (p_s_father = find_buffer(fs->fs_dev, n_left_neighbor_blocknr, fs->fs_blocksize)) ) return 1; return 0; } #define LEFT_PARENTS 'l' #define RIGHT_PARENTS 'r' void init_path (struct path * path) { path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET; } /* Calculate far left/right parent of the left/right neighbor of the current node, that * is calculate the left/right (FL[h]/FR[h]) neighbor of the parent F[h]. * Calculate left/right common parent of the current node and L[h]/R[h]. * Calculate left/right delimiting key position. * Returns: PATH_INCORRECT - path in the tree is not correct; SCHEDULE_OCCURRED - schedule occured while the function worked; * CARRY_ON - schedule didn't occur while the function worked; */ static int get_far_parent (struct tree_balance * p_s_tb, int n_h, struct buffer_head ** pp_s_father, struct buffer_head ** pp_s_com_father, char c_lr_par) { struct buffer_head * p_s_parent; struct path s_path_to_neighbor_father, * p_s_path = p_s_tb->tb_path; struct key s_lr_father_key; int n_counter, n_position = -1, n_first_last_position = 0, n_path_offset = PATH_H_PATH_OFFSET(p_s_path, n_h); /* Starting from F[n_h] go upwards in the tree, and look for the common ancestor of F[n_h], and its neighbor l/r, that should be obtained. */ n_counter = n_path_offset; for ( ; n_counter > FIRST_PATH_ELEMENT_OFFSET; n_counter-- ) { /* Check whether parent of the current buffer in the path is really parent in the tree. */ if ( ! B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_path, n_counter - 1)) ) reiserfs_panic ("get_far_parent: buffer of path is notin the tree"); /* Check whether position in the parent is correct. */ if ( (n_position = PATH_OFFSET_POSITION(p_s_path, n_counter - 1)) > B_NR_ITEMS(p_s_parent) ) reiserfs_panic ("get_far_parent: incorrect position in the parent"); /* Check whether parent at the path really points to the child. */ if ( get_dc_child_blocknr (B_N_CHILD (p_s_parent, n_position)) != PATH_OFFSET_PBUFFER(p_s_path, n_counter)->b_blocknr ) reiserfs_panic ("get_far_parent: incorrect disk child in the parent"); /* Return delimiting key if position in the parent is not equal to first/last one. */ if ( c_lr_par == RIGHT_PARENTS ) n_first_last_position = get_blkh_nr_items (B_BLK_HEAD(p_s_parent)); if ( n_position != n_first_last_position ) { (*pp_s_com_father = p_s_parent)->b_count++; break; } } /* we are in the root of the tree. */ if ( n_counter == FIRST_PATH_ELEMENT_OFFSET ) { struct reiserfs_super_block * sb; sb = p_s_tb->tb_fs->fs_ondisk_sb; /* Check whether first buffer in the path is the root of the tree. */ if ( PATH_OFFSET_PBUFFER(p_s_tb->tb_path, FIRST_PATH_ELEMENT_OFFSET)->b_blocknr == get_sb_root_block (sb) ) { *pp_s_father = *pp_s_com_father = NULL; return CARRY_ON; } reiserfs_panic ("get_far_parent: root not found in the path"); } if (n_position == -1) reiserfs_panic ("get_far_parent: position is not defined"); /* So, we got common parent of the current node and its left/right neighbor. Now we are geting the parent of the left/right neighbor. */ /* Form key to get parent of the left/right neighbor. */ copy_key(&s_lr_father_key, B_N_PDELIM_KEY(*pp_s_com_father, ( c_lr_par == LEFT_PARENTS ) ? (p_s_tb->lkey[n_h - 1] = n_position - 1) : (p_s_tb->rkey[n_h - 1] = n_position))); if ( c_lr_par == LEFT_PARENTS ) { //reiserfs_warning ("decrememnting key %k\n", &s_lr_father_key); decrement_key(&s_lr_father_key); //reiserfs_warning ("done: %k\n", &s_lr_father_key); } init_path (&s_path_to_neighbor_father); if (search_by_key(p_s_tb->tb_fs, &s_lr_father_key, &s_path_to_neighbor_father, n_h + 1) == IO_ERROR) return IO_ERROR; *pp_s_father = PATH_PLAST_BUFFER(&s_path_to_neighbor_father); s_path_to_neighbor_father.path_length--; pathrelse (&s_path_to_neighbor_father); //decrement_counters_in_path(&s_path_to_neighbor_father); return CARRY_ON; } /* Get parents of neighbors of node in the path(S[n_path_offset]) and common parents of * S[n_path_offset] and L[n_path_offset]/R[n_path_offset]: F[n_path_offset], FL[n_path_offset], * FR[n_path_offset], CFL[n_path_offset], CFR[n_path_offset]. * Calculate numbers of left and right delimiting keys position: lkey[n_path_offset], rkey[n_path_offset]. * Returns: SCHEDULE_OCCURRED - schedule occured while the function worked; * CARRY_ON - schedule didn't occur while the function worked; */ static int get_parents (struct tree_balance * p_s_tb, int n_h) { struct path * p_s_path = p_s_tb->tb_path; int n_position, n_ret_value, n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h); struct buffer_head * p_s_curf, * p_s_curcf; /* Current node is the root of the tree or will be root of the tree */ if ( n_path_offset <= FIRST_PATH_ELEMENT_OFFSET ) { /* The root can not have parents. Release nodes which previously were obtained as parents of the current node neighbors. */ brelse(p_s_tb->FL[n_h]); brelse(p_s_tb->CFL[n_h]); brelse(p_s_tb->FR[n_h]); brelse(p_s_tb->CFR[n_h]); //decrement_bcount(p_s_tb->FL[n_h]); //decrement_bcount(p_s_tb->CFL[n_h]); //decrement_bcount(p_s_tb->FR[n_h]); //decrement_bcount(p_s_tb->CFR[n_h]); p_s_tb->FL[n_h] = p_s_tb->CFL[n_h] = p_s_tb->FR[n_h] = p_s_tb->CFR[n_h] = NULL; return CARRY_ON; } /* Get parent FL[n_path_offset] of L[n_path_offset]. */ if ( (n_position = PATH_OFFSET_POSITION(p_s_path, n_path_offset - 1)) ) { /* Current node is not the first child of its parent. */ (p_s_curf = p_s_curcf = PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1))->b_count += 2; p_s_tb->lkey[n_h] = n_position - 1; } else { /* Calculate current parent of L[n_path_offset], which is the left neighbor of the current node. Calculate current common parent of L[n_path_offset] and the current node. Note that CFL[n_path_offset] not equal FL[n_path_offset] and CFL[n_path_offset] not equal F[n_path_offset]. Calculate lkey[n_path_offset]. */ if ( (n_ret_value = get_far_parent(p_s_tb, n_h + 1, &p_s_curf, &p_s_curcf, LEFT_PARENTS)) != CARRY_ON ) return n_ret_value; /*schedule() occured or path is not correct*/ } brelse(p_s_tb->FL[n_h]); p_s_tb->FL[n_h] = p_s_curf; /* New initialization of FL[n_h]. */ brelse(p_s_tb->CFL[n_h]); p_s_tb->CFL[n_h] = p_s_curcf; /* New initialization of CFL[n_h]. */ /* Get parent FR[n_h] of R[n_h]. */ /* Current node is the last child of F[n_h]. FR[n_h] != F[n_h]. */ if ( n_position == get_blkh_nr_items (B_BLK_HEAD(PATH_H_PBUFFER(p_s_path, n_h + 1))) ) { /* Calculate current parent of R[n_h], which is the right neighbor of F[n_h]. Calculate current common parent of R[n_h] and current node. Note that CFR[n_h] not equal FR[n_path_offset] and CFR[n_h] not equal F[n_h]. */ if ( (n_ret_value = get_far_parent(p_s_tb, n_h + 1, &p_s_curf, &p_s_curcf, RIGHT_PARENTS)) != CARRY_ON ) return n_ret_value; /*schedule() occured while get_far_parent() worked.*/ } else { /* Current node is not the last child of its parent F[n_h]. */ (p_s_curf = p_s_curcf = PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1))->b_count += 2; p_s_tb->rkey[n_h] = n_position; } brelse/*decrement_bcount*/(p_s_tb->FR[n_h]); p_s_tb->FR[n_h] = p_s_curf; /* New initialization of FR[n_path_offset]. */ brelse/*decrement_bcount*/(p_s_tb->CFR[n_h]); p_s_tb->CFR[n_h] = p_s_curcf; /* New initialization of CFR[n_path_offset]. */ return CARRY_ON; /* schedule not occured while get_parents() worked. */ } /* it is possible to remove node as result of shiftings to neighbors even when we insert or paste item. */ static inline int can_node_be_removed (int mode, int lfree, int sfree, int rfree, struct tree_balance * tb, int h) { struct buffer_head * Sh = PATH_H_PBUFFER (tb->tb_path, h); int levbytes = tb->insert_size[h]; struct item_head * r_ih = NULL; if ( tb->CFR[h] ) r_ih = (struct item_head *)B_N_PDELIM_KEY(tb->CFR[h],tb->rkey[h]); if (lfree + rfree + sfree < (int)(MAX_CHILD_SIZE(Sh->b_size) + levbytes /* shifting may merge items which might save space */ - (( ! h && is_left_mergeable (tb->tb_fs, tb->tb_path) == 1 ) ? IH_SIZE : 0) - (( ! h && r_ih && is_right_mergeable (tb->tb_fs, tb->tb_path) == 1 ) ? IH_SIZE : 0) + (( h ) ? KEY_SIZE : 0))) { /* node can not be removed */ if (sfree >= levbytes ) /* new item fits into node S[h] without any shifting */ { if ( ! h ) tb->s0num = B_NR_ITEMS(Sh) + ((mode == M_INSERT ) ? 1 : 0); set_parameters (tb, h, 0, 0, 1, NULL, -1, -1); return NO_BALANCING_NEEDED; } } return !NO_BALANCING_NEEDED; } /* Check whether current node S[h] is balanced when increasing its size by * Inserting or Pasting. * Calculate parameters for balancing for current level h. * Parameters: * tb tree_balance structure; * h current level of the node; * inum item number in S[h]; * mode i - insert, p - paste; * Returns: 1 - schedule occured; * 0 - balancing for higher levels needed; * -1 - no balancing for higher levels needed; * -2 - no disk space. */ /* ip means Inserting or Pasting */ static int ip_check_balance (/*struct reiserfs_transaction_handle *th,*/ struct tree_balance * tb, int h) { struct virtual_node * vn = tb->tb_vn; int levbytes, /* Number of bytes that must be inserted into (value is negative if bytes are deleted) buffer which contains node being balanced. The mnemonic is that the attempted change in node space used level is levbytes bytes. */ n_ret_value; int lfree, sfree, rfree /* free space in L, S and R */; /* nver is short for number of vertices, and lnver is the number if we shift to the left, rnver is the number if we shift to the right, and lrnver is the number if we shift in both directions. The goal is to minimize first the number of vertices, and second, the number of vertices whose contents are changed by shifting, and third the number of uncached vertices whose contents are changed by shifting and must be read from disk. */ int nver, lnver, rnver, lrnver; /* used at leaf level only, S0 = S[0] is the node being balanced, sInum [ I = 0,1,2 ] is the number of items that will remain in node SI after balancing. S1 and S2 are new nodes that might be created. */ /* we perform 8 calls to get_num_ver(). For each call we calculate five parameters. where 4th parameter is s1bytes and 5th - s2bytes */ short snum012[40] = {0,}; /* s0num, s1num, s2num for 8 cases 0,1 - do not shift and do not shift but bottle 2 - shift only whole item to left 3 - shift to left and bottle as much as possible 4,5 - shift to right (whole items and as much as possible 6,7 - shift to both directions (whole items and as much as possible) */ /* Sh is the node whose balance is currently being checked */ struct buffer_head * Sh; /* special mode for insert pointer to the most low internal node */ if (h == 0 && vn->vn_mode == M_INTERNAL) { /* blk_num == 2 is to get pointer inserted to the next level */ set_parameters (tb, h, 0, 0, 2, NULL, -1, -1); return 0; } Sh = PATH_H_PBUFFER (tb->tb_path, h); levbytes = tb->insert_size[h]; /* Calculate balance parameters for creating new root. */ if ( ! Sh ) { if ( ! h ) reiserfs_panic ("vs-8210: ip_check_balance: S[0] can not be 0"); switch ( n_ret_value = get_empty_nodes (tb, h) ) { case CARRY_ON: set_parameters (tb, h, 0, 0, 1, NULL, -1, -1); return NO_BALANCING_NEEDED; /* no balancing for higher levels needed */ case NO_DISK_SPACE: return n_ret_value; default: reiserfs_panic("vs-8215: ip_check_balance: incorrect return value of get_empty_nodes"); } } if ( (n_ret_value = get_parents (tb, h)) != CARRY_ON ) /* get parents of S[h] neighbors. */ return n_ret_value; sfree = get_blkh_free_space (B_BLK_HEAD(Sh)); /* get free space of neighbors */ rfree = get_rfree (tb, h); lfree = get_lfree (tb, h); if (can_node_be_removed (vn->vn_mode, lfree, sfree, rfree, tb, h) == NO_BALANCING_NEEDED) /* and new item fits into node S[h] without any shifting */ return NO_BALANCING_NEEDED; create_virtual_node (tb, h); /* determine maximal number of items we can shift to the left neighbor (in tb structure) and the maximal number of bytes that can flow to the left neighbor from the left most liquid item that cannot be shifted from S[0] entirely (returned value) */ check_left (tb, h, lfree); /* determine maximal number of items we can shift to the right neighbor (in tb structure) and the maximal number of bytes that can flow to the right neighbor from the right most liquid item that cannot be shifted from S[0] entirely (returned value) */ check_right (tb, h, rfree); /* all contents of internal node S[h] can be moved into its neighbors, S[h] will be removed after balancing */ if (h && (tb->rnum[h] + tb->lnum[h] >= vn->vn_nr_item + 1)) { int to_r; /* Since we are working on internal nodes, and our internal nodes have fixed size entries, then we can balance by the number of items rather than the space they consume. In this routine we set the left node equal to the right node, allowing a difference of less than or equal to 1 child pointer. */ to_r = ((MAX_NR_KEY(Sh)<<1)+2-tb->lnum[h]-tb->rnum[h]+vn->vn_nr_item+1)/2 - (MAX_NR_KEY(Sh) + 1 - tb->rnum[h]); set_parameters (tb, h, vn->vn_nr_item + 1 - to_r, to_r, 0, NULL, -1, -1); return CARRY_ON; } /* all contents of S[0] can be moved into its neighbors S[0] will be removed after balancing. */ if (!h && is_leaf_removable (tb)) return CARRY_ON; /* why do we perform this check here rather than earlier?? Answer: we can win 1 node in some cases above. Moreover we checked it above, when we checked, that S[0] is not removable in principle */ if (sfree >= levbytes) { /* new item fits into node S[h] without any shifting */ if ( ! h ) tb->s0num = vn->vn_nr_item; set_parameters (tb, h, 0, 0, 1, NULL, -1, -1); return NO_BALANCING_NEEDED; } { int lpar, rpar, nset, lset, rset, lrset; /* * regular overflowing of the node */ /* get_num_ver works in 2 modes (FLOW & NO_FLOW) lpar, rpar - number of items we can shift to left/right neighbor (including splitting item) nset, lset, rset, lrset - shows, whether flowing items give better packing */ #define FLOW 1 #define NO_FLOW 0 /* do not any splitting */ /* we choose one the following */ #define NOTHING_SHIFT_NO_FLOW 0 #define NOTHING_SHIFT_FLOW 5 #define LEFT_SHIFT_NO_FLOW 10 #define LEFT_SHIFT_FLOW 15 #define RIGHT_SHIFT_NO_FLOW 20 #define RIGHT_SHIFT_FLOW 25 #define LR_SHIFT_NO_FLOW 30 #define LR_SHIFT_FLOW 35 lpar = tb->lnum[h]; rpar = tb->rnum[h]; /* calculate number of blocks S[h] must be split into when nothing is shifted to the neighbors, as well as number of items in each part of the split node (s012 numbers), and number of bytes (s1bytes) of the shared drop which flow to S1 if any */ nset = NOTHING_SHIFT_NO_FLOW; nver = get_num_ver (vn->vn_mode, tb, h, 0, -1, h?vn->vn_nr_item:0, -1, snum012, NO_FLOW); if (!h) { int nver1; /* note, that in this case we try to bottle between S[0] and S1 (S1 - the first new node) */ nver1 = get_num_ver (vn->vn_mode, tb, h, 0, -1, 0, -1, snum012 + NOTHING_SHIFT_FLOW, FLOW); if (nver > nver1) nset = NOTHING_SHIFT_FLOW, nver = nver1; } /* calculate number of blocks S[h] must be split into when l_shift_num first items and l_shift_bytes of the right most liquid item to be shifted are shifted to the left neighbor, as well as number of items in each part of the split node (s012 numbers), and number of bytes (s1bytes) of the shared drop which flow to S1 if any */ lset = LEFT_SHIFT_NO_FLOW; lnver = get_num_ver (vn->vn_mode, tb, h, lpar - (( h || tb->lbytes == -1 ) ? 0 : 1), -1, h ? vn->vn_nr_item:0, -1, snum012 + LEFT_SHIFT_NO_FLOW, NO_FLOW); if (!h) { int lnver1; lnver1 = get_num_ver (vn->vn_mode, tb, h, lpar - ((tb->lbytes != -1) ? 1 : 0), tb->lbytes, 0, -1, snum012 + LEFT_SHIFT_FLOW, FLOW); if (lnver > lnver1) lset = LEFT_SHIFT_FLOW, lnver = lnver1; } /* calculate number of blocks S[h] must be split into when r_shift_num first items and r_shift_bytes of the left most liquid item to be shifted are shifted to the right neighbor, as well as number of items in each part of the splitted node (s012 numbers), and number of bytes (s1bytes) of the shared drop which flow to S1 if any */ rset = RIGHT_SHIFT_NO_FLOW; rnver = get_num_ver (vn->vn_mode, tb, h, 0, -1, h ? (vn->vn_nr_item-rpar) : (rpar - (( tb->rbytes != -1 ) ? 1 : 0)), -1, snum012 + RIGHT_SHIFT_NO_FLOW, NO_FLOW); if (!h) { int rnver1; rnver1 = get_num_ver (vn->vn_mode, tb, h, 0, -1, (rpar - ((tb->rbytes != -1) ? 1 : 0)), tb->rbytes, snum012 + RIGHT_SHIFT_FLOW, FLOW); if (rnver > rnver1) rset = RIGHT_SHIFT_FLOW, rnver = rnver1; } /* calculate number of blocks S[h] must be split into when items are shifted in both directions, as well as number of items in each part of the splitted node (s012 numbers), and number of bytes (s1bytes) of the shared drop which flow to S1 if any */ lrset = LR_SHIFT_NO_FLOW; lrnver = get_num_ver (vn->vn_mode, tb, h, lpar - ((h || tb->lbytes == -1) ? 0 : 1), -1, h ? (vn->vn_nr_item-rpar):(rpar - ((tb->rbytes != -1) ? 1 : 0)), -1, snum012 + LR_SHIFT_NO_FLOW, NO_FLOW); if (!h) { int lrnver1; lrnver1 = get_num_ver (vn->vn_mode, tb, h, lpar - ((tb->lbytes != -1) ? 1 : 0), tb->lbytes, (rpar - ((tb->rbytes != -1) ? 1 : 0)), tb->rbytes, snum012 + LR_SHIFT_FLOW, FLOW); if (lrnver > lrnver1) lrset = LR_SHIFT_FLOW, lrnver = lrnver1; } /* Our general shifting strategy is: 1) to minimized number of new nodes; 2) to minimized number of neighbors involved in shifting; 3) to minimized number of disk reads; */ /* we can win TWO or ONE nodes by shifting in both directions */ if (lrnver < lnver && lrnver < rnver) { if (lrset == LR_SHIFT_FLOW) set_parameters (tb, h, tb->lnum[h], tb->rnum[h], lrnver, snum012 + lrset, tb->lbytes, tb->rbytes); else set_parameters (tb, h, tb->lnum[h] - ((tb->lbytes == -1) ? 0 : 1), tb->rnum[h] - ((tb->rbytes == -1) ? 0 : 1), lrnver, snum012 + lrset, -1, -1); return CARRY_ON; } /* if shifting doesn't lead to better packing then don't shift */ if (nver == lrnver) { set_parameters (tb, h, 0, 0, nver, snum012 + nset, -1, -1); return CARRY_ON; } /* now we know that for better packing shifting in only one direction either to the left or to the right is required */ /* if shifting to the left is better than shifting to the right */ if (lnver < rnver) { SET_PAR_SHIFT_LEFT; return CARRY_ON; } /* if shifting to the right is better than shifting to the left */ if (lnver > rnver) { SET_PAR_SHIFT_RIGHT; return CARRY_ON; } /* now shifting in either direction gives the same number of nodes and we can make use of the cached neighbors */ if (is_left_neighbor_in_cache (tb,h)) { SET_PAR_SHIFT_LEFT; return CARRY_ON; } /* shift to the right independently on whether the right neighbor in cache or not */ SET_PAR_SHIFT_RIGHT; return CARRY_ON; } } /* Check whether current node S[h] is balanced when Decreasing its size by * Deleting or Cutting for INTERNAL node of internal tree. * Calculate parameters for balancing for current level h. * Parameters: * tb tree_balance structure; * h current level of the node; * inum item number in S[h]; * mode i - insert, p - paste; * Returns: 1 - schedule occured; * 0 - balancing for higher levels needed; * -1 - no balancing for higher levels needed; * -2 - no disk space. * * Note: Items of internal nodes have fixed size, so the balance condition for * the internal part of internal tree is as for the B-trees. */ static int dc_check_balance_internal (struct tree_balance * tb, int h) { struct virtual_node * vn = tb->tb_vn; /* Sh is the node whose balance is currently being checked, and Fh is its father. */ struct buffer_head * Sh, * Fh; int n_ret_value; int lfree, rfree /* free space in L and R */; Sh = PATH_H_PBUFFER (tb->tb_path, h); Fh = PATH_H_PPARENT (tb->tb_path, h); /* using tb->insert_size[h], which is negative in this case, create_virtual_node calculates: new_nr_item = number of items node would have if operation is performed without balancing (new_nr_item); */ create_virtual_node (tb, h); if ( ! Fh ) { /* S[h] is the root. */ if ( vn->vn_nr_item > 0 ) { set_parameters (tb, h, 0, 0, 1, NULL, -1, -1); return NO_BALANCING_NEEDED; /* no balancing for higher levels needed */ } /* new_nr_item == 0. * Current root will be deleted resulting in * decrementing the tree height. */ set_parameters (tb, h, 0, 0, 0, NULL, -1, -1); return CARRY_ON; } if ( (n_ret_value = get_parents(tb,h)) != CARRY_ON ) return n_ret_value; /* get free space of neighbors */ rfree = get_rfree (tb, h); lfree = get_lfree (tb, h); /* determine maximal number of items we can fit into neighbors */ check_left (tb, h, lfree); check_right (tb, h, rfree); if ( vn->vn_nr_item >= MIN_NR_KEY(Sh) ) { /* Balance condition for the internal node is valid. In this case we * balance only if it leads to better packing. */ if ( vn->vn_nr_item == MIN_NR_KEY(Sh) ) { /* Here we join S[h] with one of its neighbors, which is * impossible with greater values of new_nr_item. */ if ( tb->lnum[h] >= vn->vn_nr_item + 1 ) { /* All contents of S[h] can be moved to L[h]. */ int n; int order_L; order_L = ((n=PATH_H_B_ITEM_ORDER(tb->tb_path, h))==0) ? B_NR_ITEMS(tb->FL[h]) : n - 1; n = get_dc_child_size (B_N_CHILD(tb->FL[h],order_L)) / (DC_SIZE + KEY_SIZE); set_parameters (tb, h, -n-1, 0, 0, NULL, -1, -1); return CARRY_ON; } if ( tb->rnum[h] >= vn->vn_nr_item + 1 ) { /* All contents of S[h] can be moved to R[h]. */ int n; int order_R; order_R = ((n=PATH_H_B_ITEM_ORDER(tb->tb_path, h))==B_NR_ITEMS(Fh)) ? 0 : n + 1; n = get_dc_child_size (B_N_CHILD(tb->FR[h],order_R)) / (DC_SIZE + KEY_SIZE); set_parameters (tb, h, 0, -n-1, 0, NULL, -1, -1); return CARRY_ON; } } if (tb->rnum[h] + tb->lnum[h] >= vn->vn_nr_item + 1) { /* All contents of S[h] can be moved to the neighbors (L[h] & R[h]). */ int to_r; to_r = ((MAX_NR_KEY(Sh)<<1)+2-tb->lnum[h]-tb->rnum[h]+vn->vn_nr_item+1)/2 - (MAX_NR_KEY(Sh) + 1 - tb->rnum[h]); set_parameters (tb, h, vn->vn_nr_item + 1 - to_r, to_r, 0, NULL, -1, -1); return CARRY_ON; } /* Balancing does not lead to better packing. */ set_parameters (tb, h, 0, 0, 1, NULL, -1, -1); return NO_BALANCING_NEEDED; } /* Current node contain insufficient number of items. Balancing is required. Check whether we can merge S[h] with left neighbor. */ if (tb->lnum[h] >= vn->vn_nr_item + 1) if (is_left_neighbor_in_cache (tb,h) || tb->rnum[h] < vn->vn_nr_item + 1 || !tb->FR[h]) { int n; int order_L; order_L = ((n=PATH_H_B_ITEM_ORDER(tb->tb_path, h))==0) ? B_NR_ITEMS(tb->FL[h]) : n - 1; n = get_dc_child_size (B_N_CHILD(tb->FL[h],order_L)) / (DC_SIZE + KEY_SIZE); set_parameters (tb, h, -n-1, 0, 0, NULL, -1, -1); return CARRY_ON; } /* Check whether we can merge S[h] with right neighbor. */ if (tb->rnum[h] >= vn->vn_nr_item + 1) { int n; int order_R; order_R = ((n=PATH_H_B_ITEM_ORDER(tb->tb_path, h))==B_NR_ITEMS(Fh)) ? 0 : (n + 1); n = get_dc_child_size (B_N_CHILD(tb->FR[h],order_R)) / (DC_SIZE + KEY_SIZE); set_parameters (tb, h, 0, -n-1, 0, NULL, -1, -1); return CARRY_ON; } /* All contents of S[h] can be moved to the neighbors (L[h] & R[h]). */ if (tb->rnum[h] + tb->lnum[h] >= vn->vn_nr_item + 1) { int to_r; to_r = ((MAX_NR_KEY(Sh)<<1)+2-tb->lnum[h]-tb->rnum[h]+vn->vn_nr_item+1)/2 - (MAX_NR_KEY(Sh) + 1 - tb->rnum[h]); set_parameters (tb, h, vn->vn_nr_item + 1 - to_r, to_r, 0, NULL, -1, -1); return CARRY_ON; } /* For internal nodes try to borrow item from a neighbor */ /* Borrow one or two items from caching neighbor */ if (is_left_neighbor_in_cache (tb,h) || !tb->FR[h]) { int from_l; from_l = (MAX_NR_KEY(Sh) + 1 - tb->lnum[h] + vn->vn_nr_item + 1) / 2 - (vn->vn_nr_item + 1); set_parameters (tb, h, -from_l, 0, 1, NULL, -1, -1); return CARRY_ON; } set_parameters (tb, h, 0, -((MAX_NR_KEY(Sh)+1-tb->rnum[h]+vn->vn_nr_item+1)/2-(vn->vn_nr_item+1)), 1, NULL, -1, -1); return CARRY_ON; } /* Check whether current node S[h] is balanced when Decreasing its size by * Deleting or Truncating for LEAF node of internal tree. * Calculate parameters for balancing for current level h. * Parameters: * tb tree_balance structure; * h current level of the node; * inum item number in S[h]; * mode i - insert, p - paste; * Returns: 1 - schedule occured; * 0 - balancing for higher levels needed; * -1 - no balancing for higher levels needed; * -2 - no disk space. */ static int dc_check_balance_leaf (struct tree_balance * tb, int h) { struct virtual_node * vn = tb->tb_vn; /* Number of bytes that must be deleted from (value is negative if bytes are deleted) buffer which contains node being balanced. The mnemonic is that the attempted change in node space used level is levbytes bytes. */ int levbytes; /* the maximal item size */ int n_ret_value; /* F0 is the parent of the node whose balance is currently being checked */ struct buffer_head * F0; int lfree, rfree /* free space in L and R */; F0 = PATH_H_PPARENT (tb->tb_path, 0); levbytes = tb->insert_size[h]; if ( ! F0 ) { /* S[0] is the root now. */ set_parameters (tb, h, 0, 0, 1, NULL, -1, -1); return NO_BALANCING_NEEDED; } if ( (n_ret_value = get_parents(tb,h)) != CARRY_ON ) return n_ret_value; /* get free space of neighbors */ rfree = get_rfree (tb, h); lfree = get_lfree (tb, h); create_virtual_node (tb, h); /* if 3 leaves can be merge to one, set parameters and return */ if (are_leaves_removable (tb, lfree, rfree)) return CARRY_ON; /* determine maximal number of items we can shift to the left/right neighbor and the maximal number of bytes that can flow to the left/right neighbor from the left/right most liquid item that cannot be shifted from S[0] entirely */ check_left (tb, h, lfree); check_right (tb, h, rfree); /* check whether we can merge S with left neighbor. */ if (tb->lnum[0] >= vn->vn_nr_item && tb->lbytes == -1) if (is_left_neighbor_in_cache (tb,h) || ((tb->rnum[0] - ((tb->rbytes == -1) ? 0 : 1)) < vn->vn_nr_item) || /* S can not be merged with R */ !tb->FR[h]) { /* set parameter to merge S[0] with its left neighbor */ set_parameters (tb, h, -1, 0, 0, NULL, -1, -1); return CARRY_ON; } /* check whether we can merge S[0] with right neighbor. */ if (tb->rnum[0] >= vn->vn_nr_item && tb->rbytes == -1) { set_parameters (tb, h, 0, -1, 0, NULL, -1, -1); return CARRY_ON; } /* All contents of S[0] can be moved to the neighbors (L[0] & R[0]). Set parameters and return */ if (is_leaf_removable (tb)) return CARRY_ON; /* Balancing is not required. */ tb->s0num = vn->vn_nr_item; set_parameters (tb, h, 0, 0, 1, NULL, -1, -1); return NO_BALANCING_NEEDED; } /* Check whether current node S[h] is balanced when Decreasing its size by * Deleting or Cutting. * Calculate parameters for balancing for current level h. * Parameters: * tb tree_balance structure; * h current level of the node; * inum item number in S[h]; * mode d - delete, c - cut. * Returns: 1 - schedule occured; * 0 - balancing for higher levels needed; * -1 - no balancing for higher levels needed; * -2 - no disk space. */ static int dc_check_balance (struct tree_balance * tb, int h) { if ( h ) return dc_check_balance_internal (tb, h); else return dc_check_balance_leaf (tb, h); } /* Check whether current node S[h] is balanced. * Calculate parameters for balancing for current level h. * Parameters: * * tb tree_balance structure: * * tb is a large structure that must be read about in the header file * at the same time as this procedure if the reader is to successfully * understand this procedure * * h current level of the node; * inum item number in S[h]; * mode i - insert, p - paste, d - delete, c - cut. * Returns: 1 - schedule occured; * 0 - balancing for higher levels needed; * -1 - no balancing for higher levels needed; * -2 - no disk space. */ static int check_balance (int mode, struct tree_balance * tb, int h, int inum, int pos_in_item, struct item_head * ins_ih) { struct virtual_node * vn; vn = tb->tb_vn = (struct virtual_node *)(tb->vn_buf);// + ROUND_UP(SB_BMAP_NR (tb->tb_fs) * 2 / 8 + 1, 4)); vn->vn_free_ptr = (char *)(tb->tb_vn + 1); vn->vn_mode = mode; vn->vn_affected_item_num = inum; vn->vn_pos_in_item = pos_in_item; vn->vn_ins_ih = ins_ih; if ( tb->insert_size[h] > 0 ) /* Calculate balance parameters when size of node is increasing. */ return ip_check_balance (tb, h); /* Calculate balance parameters when size of node is decreasing. */ return dc_check_balance (tb, h); } /* Check whether parent at the path is the really parent of the current node.*/ static void get_direct_parent (struct tree_balance * p_s_tb, int n_h) { struct buffer_head * p_s_bh; struct path * p_s_path = p_s_tb->tb_path; int n_position, n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h); /* We are in the root or in the new root. */ if ( n_path_offset <= FIRST_PATH_ELEMENT_OFFSET ) { struct reiserfs_super_block * sb; if ( n_path_offset < FIRST_PATH_ELEMENT_OFFSET - 1 ) reiserfs_panic ("PAP-8260: get_direct_parent: illegal offset in the path"); sb = p_s_tb->tb_fs->fs_ondisk_sb; if ( PATH_OFFSET_PBUFFER(p_s_path, FIRST_PATH_ELEMENT_OFFSET)->b_blocknr == get_sb_root_block (sb) ) { /* Root is not changed. */ PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1) = NULL; PATH_OFFSET_POSITION(p_s_path, n_path_offset - 1) = 0; return; } reiserfs_panic ("get_direct_parent: root changed"); } if ( ! B_IS_IN_TREE(p_s_bh = PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1)) ) reiserfs_panic ("get_direct_parent: parent in the path is not in the tree"); if ( (n_position = PATH_OFFSET_POSITION(p_s_path, n_path_offset - 1)) > B_NR_ITEMS(p_s_bh) ) reiserfs_panic ("get_direct_parent: wrong position in the path"); if ( get_dc_child_blocknr (B_N_CHILD(p_s_bh, n_position)) != PATH_OFFSET_PBUFFER(p_s_path, n_path_offset)->b_blocknr ) reiserfs_panic ("get_direct_parent: parent in the path is not parent " "of the current node in the tree"); return ; /* Parent in the path is unlocked and really parent of the current node. */ } /* Using lnum[n_h] and rnum[n_h] we should determine what neighbors * of S[n_h] we * need in order to balance S[n_h], and get them if necessary. * Returns: SCHEDULE_OCCURRED - schedule occured while the function worked; * CARRY_ON - schedule didn't occur while the function worked; */ static int get_neighbors(struct tree_balance * p_s_tb, int n_h) { int n_child_position, n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h + 1); unsigned long n_son_number; reiserfs_filsys_t * fs = p_s_tb->tb_fs; struct buffer_head * p_s_bh; /*struct virtual_node * vn = p_s_tb->tb_vn;*/ if ( p_s_tb->lnum[n_h] ) { /* We need left neighbor to balance S[n_h]. */ p_s_bh = PATH_OFFSET_PBUFFER(p_s_tb->tb_path, n_path_offset); n_child_position = ( p_s_bh == p_s_tb->FL[n_h] ) ? p_s_tb->lkey[n_h] : get_blkh_nr_items (B_BLK_HEAD(p_s_tb->FL[n_h])); n_son_number = get_dc_child_blocknr (B_N_CHILD (p_s_tb->FL[n_h], n_child_position)); p_s_bh = bread(fs->fs_dev, n_son_number, fs->fs_blocksize); if (!p_s_bh) return IO_ERROR; brelse (p_s_tb->L[n_h]); p_s_tb->L[n_h] = p_s_bh; } if ( p_s_tb->rnum[n_h] ) { /* We need right neighbor to balance S[n_path_offset]. */ p_s_bh = PATH_OFFSET_PBUFFER(p_s_tb->tb_path, n_path_offset); n_child_position = ( p_s_bh == p_s_tb->FR[n_h] ) ? p_s_tb->rkey[n_h] + 1 : 0; n_son_number = get_dc_child_blocknr (B_N_CHILD (p_s_tb->FR[n_h], n_child_position)); p_s_bh = bread(fs->fs_dev, n_son_number, fs->fs_blocksize); if (!p_s_bh) return IO_ERROR; brelse (p_s_tb->R[n_h]); p_s_tb->R[n_h] = p_s_bh; } return CARRY_ON; } #if 0 void * reiserfs_kmalloc (size_t size, int flags, struct super_block * s) { void * vp; vp = getmem (size); return vp; } void reiserfs_kfree (/*const */void * vp, size_t size, struct super_block * s) { freemem (vp); kfree (vp); s->u.reiserfs_sb.s_kmallocs -= size; if (s->u.reiserfs_sb.s_kmallocs < 0) reiserfs_warning ("vs-8302: reiserfs_kfree: allocated memory %d\n", s->u.reiserfs_sb.s_kmallocs); } #endif static int get_mem_for_virtual_node (struct tree_balance * tb) { tb->vn_buf = getmem (tb->tb_fs->fs_blocksize); return CARRY_ON; } static void free_virtual_node_mem (struct tree_balance * tb) { freemem (tb->vn_buf); } /* Prepare for balancing, that is * get all necessary parents, and neighbors; * analyze what and where should be moved; * get sufficient number of new nodes; * Balancing will start only after all resources will be collected at a time. * * When ported to SMP kernels, only at the last moment after all needed nodes * are collected in cache, will the resources be locked using the usual * textbook ordered lock acquisition algorithms. Note that ensuring that * this code neither write locks what it does not need to write lock nor locks out of order * will be a pain in the butt that could have been avoided. Grumble grumble. -Hans * * fix is meant in the sense of render unchanging * * Latency might be improved by first gathering a list of what buffers are needed * and then getting as many of them in parallel as possible? -Hans * * Parameters: * op_mode i - insert, d - delete, c - cut (truncate), p - paste (append) * tb tree_balance structure; * inum item number in S[h]; * pos_in_item - comment this if you can * ins_ih & ins_sd are used when inserting * Returns: 1 - schedule occurred while the function worked; * 0 - schedule didn't occur while the function worked; * -1 - if no_disk_space */ int fix_nodes (int n_op_mode, struct tree_balance * p_s_tb, struct item_head * p_s_ins_ih) { int n_pos_in_item = p_s_tb->tb_path->pos_in_item; int n_ret_value, n_h, n_item_num = get_item_pos (p_s_tb->tb_path); /* struct buffer_head * p_s_tbS0 = get_bh (p_s_tb->tb_path);*/ /* struct item_head * ih = get_ih (p_s_tb->tb_path);*/ if (get_mem_for_virtual_node (p_s_tb) != CARRY_ON) reiserfs_panic ("fix_nodes: no memory for virtual node"); /* Starting from the leaf level; for all levels n_h of the tree. */ for ( n_h = 0; n_h < MAX_HEIGHT && p_s_tb->insert_size[n_h]; n_h++ ) { get_direct_parent(p_s_tb, n_h); if ( (n_ret_value = check_balance (/*th,*/ n_op_mode, p_s_tb, n_h, n_item_num, n_pos_in_item, p_s_ins_ih)) != CARRY_ON ) { if ( n_ret_value == NO_BALANCING_NEEDED ) { /* No balancing for higher levels needed. */ if ( (n_ret_value = get_neighbors(p_s_tb, n_h)) != CARRY_ON ) { return n_ret_value; } if ( n_h != MAX_HEIGHT - 1 ) p_s_tb->insert_size[n_h + 1] = 0; /* ok, analysis and resource gathering are complete */ break; } return n_ret_value; } if ( (n_ret_value = get_neighbors(p_s_tb, n_h)) != CARRY_ON ) { return n_ret_value; } if ( (n_ret_value = get_empty_nodes(/*th,*/ p_s_tb, n_h)) != CARRY_ON ) { return n_ret_value; /* No disk space */ } if ( ! PATH_H_PBUFFER(p_s_tb->tb_path, n_h) ) { /* We have a positive insert size but no nodes exist on this level, this means that we are creating a new root. */ if ( n_h < MAX_HEIGHT - 1 ) p_s_tb->insert_size[n_h + 1] = 0; } else if ( ! PATH_H_PBUFFER(p_s_tb->tb_path, n_h + 1) ) { if ( p_s_tb->blknum[n_h] > 1 ) { /* The tree needs to be grown, so this node S[n_h] which is the root node is split into two nodes, and a new node (S[n_h+1]) will be created to become the root node. */ p_s_tb->insert_size[n_h + 1] = (DC_SIZE + KEY_SIZE) * (p_s_tb->blknum[n_h] - 1) + DC_SIZE; } else if ( n_h < MAX_HEIGHT - 1 ) p_s_tb->insert_size[n_h + 1] = 0; } else p_s_tb->insert_size[n_h + 1] = (DC_SIZE + KEY_SIZE) * (p_s_tb->blknum[n_h] - 1); } return CARRY_ON; /* go ahead and balance */ } void unfix_nodes (struct tree_balance * p_s_tb) { struct path * p_s_path = p_s_tb->tb_path; int n_counter; // int i, j; //struct buffer_head * bh; /* Release path buffers. */ pathrelse(p_s_path); for ( n_counter = 0; n_counter < MAX_HEIGHT; n_counter++ ) { /* Release fathers and neighbors. */ brelse(p_s_tb->L[n_counter]); brelse(p_s_tb->R[n_counter]); brelse(p_s_tb->FL[n_counter]); brelse(p_s_tb->FR[n_counter]); brelse(p_s_tb->CFL[n_counter]); brelse(p_s_tb->CFR[n_counter]); } /* Could be optimized. Will be done by PAP someday */ for ( n_counter = 0; n_counter < MAX_FEB_SIZE; n_counter++ ) { if ( p_s_tb->FEB[n_counter] ) { /* release what was not used */ reiserfs_free_block(p_s_tb->tb_fs, p_s_tb->FEB[n_counter]->b_blocknr); bforget(p_s_tb->FEB[n_counter]); /* tree balance bitmap of bitmaps has bit set already */ } /* release used as new nodes including a new root */ brelse (p_s_tb->used[n_counter]); } free_virtual_node_mem (p_s_tb); } reiserfsprogs-3.6.9/reiserfscore/do_balan.c0000664000077100007710000011704107705261642014530 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ /* Now we have all buffers that must be used in balancing of the tree */ /* Further calculations can not cause schedule(), and thus the buffer */ /* tree will be stable until the balancing will be finished */ /* balance the tree according to the analysis made before, */ /* and using buffers obtained after all above. */ /** ** balance_leaf_when_delete ** balance_leaf ** do_balance ** **/ #include "includes.h" /* summary: if deleting something ( tb->insert_size[0] < 0 ) return(balance_leaf_when_delete()); (flag d handled here) else if lnum is larger than 0 we put items into the left node if rnum is larger than 0 we put items into the right node if snum1 is larger than 0 we put items into the new node s1 if snum2 is larger than 0 we put items into the new node s2 Note that all *num* count new items being created. It would be easier to read balance_leaf() if each of these summary lines was a separate procedure rather than being inlined. I think that there are many passages here and in balance_leaf_when_delete() in which two calls to one procedure can replace two passages, and it might save cache space and improve software maintenance costs to do so. Vladimir made the perceptive comment that we should offload most of the decision making in this function into fix_nodes/check_balance, and then create some sort of structure in tb that says what actions should be performed by do_balance. -Hans */ /* Balance leaf node in case of delete or cut: insert_size[0] < 0 * * lnum, rnum can have values >= -1 * -1 means that the neighbor must be joined with S * 0 means that nothing should be done with the neighbor * >0 means to shift entirely or partly the specified number of items to the neighbor */ static int balance_leaf_when_delete (/*struct reiserfs_transaction_handle *th,*/ struct tree_balance * tb, int flag) { struct buffer_head * tbS0 = PATH_PLAST_BUFFER (tb->tb_path); int item_pos = PATH_LAST_POSITION (tb->tb_path); int pos_in_item = tb->tb_path->pos_in_item; struct buffer_info bi; int n; struct item_head * ih; ih = B_N_PITEM_HEAD (tbS0, item_pos); /* Delete or truncate the item */ switch (flag) { case M_DELETE: /* delete item in S[0] */ bi.bi_bh = tbS0; bi.bi_parent = PATH_H_PPARENT (tb->tb_path, 0); bi.bi_position = PATH_H_POSITION (tb->tb_path, 1); leaf_delete_items (tb->tb_fs, &bi, 0, item_pos, 1, -1); if ( ! item_pos ) { // we have removed first item in the node - update left delimiting key if ( B_NR_ITEMS(tbS0) ) { replace_key(tb->tb_fs, tb->CFL[0],tb->lkey[0],tbS0,0); } else { if ( ! PATH_H_POSITION (tb->tb_path, 1) ) replace_key(tb->tb_fs, tb->CFL[0],tb->lkey[0],PATH_H_PPARENT(tb->tb_path, 0),0); } } break; case M_CUT: { /* cut item in S[0] */ bi.bi_bh = tbS0; bi.bi_parent = PATH_H_PPARENT (tb->tb_path, 0); bi.bi_position = PATH_H_POSITION (tb->tb_path, 1); if (I_IS_DIRECTORY_ITEM (ih)) { /* UFS unlink semantics are such that you can only delete one directory entry at a time. */ /* when we cut a directory tb->insert_size[0] means number of entries to be cut (always 1) */ tb->insert_size[0] = -1; leaf_cut_from_buffer (tb->tb_fs, &bi, item_pos, pos_in_item, -tb->insert_size[0]); if ( ! item_pos && ! pos_in_item ) { replace_key(tb->tb_fs, tb->CFL[0],tb->lkey[0],tbS0,0); } } else { leaf_cut_from_buffer (tb->tb_fs, &bi, item_pos, pos_in_item, -tb->insert_size[0]); } break; } default: print_tb(flag, item_pos, pos_in_item, tb,"when_del"); reiserfs_panic ("PAP-12040: balance_leaf_when_delete: unexpectable mode: %s(%d)", (flag == M_PASTE) ? "PASTE" : ((flag == M_INSERT) ? "INSERT" : "UNKNOWN"), flag); } /* the rule is that no shifting occurs unless by shifting a node can be freed */ n = B_NR_ITEMS(tbS0); if ( tb->lnum[0] ) /* L[0] takes part in balancing */ { if ( tb->lnum[0] == -1 ) /* L[0] must be joined with S[0] */ { if ( tb->rnum[0] == -1 ) /* R[0] must be also joined with S[0] */ { if ( tb->FR[0] == PATH_H_PPARENT(tb->tb_path, 0) ) { /* all contents of all the 3 buffers will be in L[0] */ if ( PATH_H_POSITION (tb->tb_path, 1) == 0 && 1 < B_NR_ITEMS(tb->FR[0]) ) replace_key(tb->tb_fs, tb->CFL[0],tb->lkey[0],tb->FR[0],1); leaf_move_items (LEAF_FROM_S_TO_L, tb, n, -1, 0); leaf_move_items (LEAF_FROM_R_TO_L, tb, B_NR_ITEMS(tb->R[0]), -1, 0); reiserfs_invalidate_buffer (tb, tbS0, 1/*do_free_block*/); reiserfs_invalidate_buffer (tb, tb->R[0], 1/*do_free_block*/); return 0; } /* all contents of all the 3 buffers will be in R[0] */ leaf_move_items(LEAF_FROM_S_TO_R, tb, n, -1, 0); leaf_move_items(LEAF_FROM_L_TO_R, tb, B_NR_ITEMS(tb->L[0]), -1, 0); /* right_delimiting_key is correct in R[0] */ replace_key(tb->tb_fs, tb->CFR[0],tb->rkey[0],tb->R[0],0); reiserfs_invalidate_buffer (tb, tbS0, 1/*do_free_block*/); reiserfs_invalidate_buffer (tb, tb->L[0], 1/*do_free_block*/); return -1; } /* all contents of L[0] and S[0] will be in L[0] */ leaf_shift_left(tb, n, -1); reiserfs_invalidate_buffer (tb, tbS0, 1/*do_free_block*/); return 0; } /* a part of contents of S[0] will be in L[0] and the rest part of S[0] will be in R[0] */ leaf_shift_left (tb, tb->lnum[0], tb->lbytes); leaf_shift_right(tb, tb->rnum[0], tb->rbytes); reiserfs_invalidate_buffer (tb, tbS0, 1/*do_free_block*/); return 0; } if ( tb->rnum[0] == -1 ) { /* all contents of R[0] and S[0] will be in R[0] */ leaf_shift_right(tb, n, -1); reiserfs_invalidate_buffer (tb, tbS0, 1/*do_free_block*/); return 0; } return 0; } static int balance_leaf(/*struct reiserfs_transaction_handle *th, */ struct tree_balance * tb, /* see reiserfs_fs.h */ struct item_head * ih, /* item header of inserted item */ const char * body, /* body of inserted item or bytes to paste */ int flag, /* i - insert, d - delete, c - cut, p - paste (see comment to do_balance) */ int zeros_number, /* it is always 0 */ struct item_head * insert_key, /* in our processing of one level we sometimes determine what must be inserted into the next higher level. This insertion consists of a key or two keys and their corresponding pointers */ struct buffer_head ** insert_ptr /* inserted node-ptrs for the next level */ ) { int pos_in_item = tb->tb_path->pos_in_item; /* position in item, in bytes for direct and indirect items, in entries for directories (for which it is an index into the array of directory entry headers.) */ struct buffer_head * tbS0 = PATH_PLAST_BUFFER (tb->tb_path); /* struct buffer_head * tbF0 = PATH_H_PPARENT (tb->tb_path, 0); int S0_b_item_order = PATH_H_B_ITEM_ORDER (tb->tb_path, 0);*/ int item_pos = PATH_LAST_POSITION (tb->tb_path); /* index into the array of item headers in S[0] of the affected item */ struct buffer_info bi; struct buffer_head *S_new[2]; /* new nodes allocated to hold what could not fit into S */ int snum[2]; /* number of items that will be placed into S_new (includes partially shifted items) */ int sbytes[2]; /* if an item is partially shifted into S_new then if it is a directory item it is the number of entries from the item that are shifted into S_new else it is the number of bytes from the item that are shifted into S_new */ int n, i; int ret_val; /* Make balance in case insert_size[0] < 0 */ if ( tb->insert_size[0] < 0 ) return balance_leaf_when_delete (/*th,*/ tb, flag); /* for indirect item pos_in_item is measured in unformatted node pointers. Recalculate to bytes */ if (flag != M_INSERT && I_IS_INDIRECT_ITEM (B_N_PITEM_HEAD (tbS0, item_pos))) pos_in_item *= UNFM_P_SIZE; if ( tb->lnum[0] > 0 ) { /* Shift lnum[0] items from S[0] to the left neighbor L[0] */ if ( item_pos < tb->lnum[0] ) { /* new item or it part falls to L[0], shift it too */ n = B_NR_ITEMS(tb->L[0]); switch (flag) { case M_INSERT: /* insert item into L[0] */ if ( item_pos == tb->lnum[0] - 1 && tb->lbytes != -1 ) { /* part of new item falls into L[0] */ int new_item_len; ret_val = leaf_shift_left (/*th,*/ tb, tb->lnum[0]-1, -1); /* Calculate item length to insert to S[0] */ new_item_len = get_ih_item_len (ih) - tb->lbytes; /* Calculate and check item length to insert to L[0] */ set_ih_item_len (ih, get_ih_item_len (ih) - new_item_len); /* Insert new item into L[0] */ bi.bi_bh = tb->L[0]; bi.bi_parent = tb->FL[0]; bi.bi_position = get_left_neighbor_position (tb, 0); leaf_insert_into_buf (tb->tb_fs, &bi, n + item_pos - ret_val, ih, body, zeros_number > get_ih_item_len (ih) ? get_ih_item_len (ih) : zeros_number); /* Calculate key component, item length and body to insert into S[0] */ //ih->ih_key.k_offset += tb->lbytes; set_offset (key_format (&ih->ih_key), &ih->ih_key, get_offset (&ih->ih_key) + tb->lbytes * (is_indirect_ih(ih) ? tb->tb_fs->fs_blocksize / UNFM_P_SIZE : 1) ); set_ih_item_len (ih, new_item_len); if ( tb->lbytes > zeros_number ) { body += (tb->lbytes - zeros_number); zeros_number = 0; } else zeros_number -= tb->lbytes; } else { /* new item in whole falls into L[0] */ /* Shift lnum[0]-1 items to L[0] */ ret_val = leaf_shift_left(tb, tb->lnum[0]-1, tb->lbytes); /* Insert new item into L[0] */ bi.bi_bh = tb->L[0]; bi.bi_parent = tb->FL[0]; bi.bi_position = get_left_neighbor_position (tb, 0); leaf_insert_into_buf (tb->tb_fs, &bi, n + item_pos - ret_val, ih, body, zeros_number); tb->insert_size[0] = 0; zeros_number = 0; } break; case M_PASTE: /* append item in L[0] */ if ( item_pos == tb->lnum[0] - 1 && tb->lbytes != -1 ) { /* we must shift the part of the appended item */ if ( I_IS_DIRECTORY_ITEM (B_N_PITEM_HEAD (tbS0, item_pos))) { /* directory item */ if ( tb->lbytes > pos_in_item ) { /* new directory entry falls into L[0] */ struct item_head * pasted; int l_pos_in_item = pos_in_item; /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 entries from given directory item */ ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes - 1); if ( ret_val && ! item_pos ) { pasted = B_N_PITEM_HEAD(tb->L[0],B_NR_ITEMS(tb->L[0])-1); l_pos_in_item += get_ih_entry_count(pasted) - (tb->lbytes-1); } /* Append given directory entry to directory item */ bi.bi_bh = tb->L[0]; bi.bi_parent = tb->FL[0]; bi.bi_position = get_left_neighbor_position (tb, 0); leaf_paste_in_buffer (tb->tb_fs, &bi, n + item_pos - ret_val, l_pos_in_item, tb->insert_size[0], body, zeros_number); /* previous string prepared space for pasting new entry, following string pastes this entry */ /* when we have merge directory item, pos_in_item has been changed too */ /* paste new directory entry. 1 is entry number */ leaf_paste_entries (bi.bi_bh, n + item_pos - ret_val, l_pos_in_item, 1, (struct reiserfs_de_head *)body, body + DEH_SIZE, tb->insert_size[0] ); tb->insert_size[0] = 0; } else { /* new directory item doesn't fall into L[0] */ /* Shift lnum[0]-1 items in whole. Shift lbytes directory entries from directory item number lnum[0] */ leaf_shift_left (tb, tb->lnum[0], tb->lbytes); } /* Calculate new position to append in item body */ pos_in_item -= tb->lbytes; } else { /* regular object */ if ( tb->lbytes >= pos_in_item ) { /* appended item will be in L[0] in whole */ int l_n, temp_n; struct key * key; /* this bytes number must be appended to the last item of L[h] */ l_n = tb->lbytes - pos_in_item; /* Calculate new insert_size[0] */ tb->insert_size[0] -= l_n; ret_val = leaf_shift_left(tb, tb->lnum[0], get_ih_item_len (B_N_PITEM_HEAD(tbS0,item_pos))); /* Append to body of item in L[0] */ bi.bi_bh = tb->L[0]; bi.bi_parent = tb->FL[0]; bi.bi_position = get_left_neighbor_position (tb, 0); leaf_paste_in_buffer(tb->tb_fs, &bi,n + item_pos - ret_val, get_ih_item_len (B_N_PITEM_HEAD(tb->L[0],n+item_pos-ret_val)), l_n,body, zeros_number > l_n ? l_n : zeros_number); /* 0-th item in S0 can be only of DIRECT type when l_n != 0*/ //B_N_PKEY (tbS0, 0)->k_offset += l_n;z key = B_N_PKEY (tbS0, 0); temp_n = is_indirect_ih(B_N_PITEM_HEAD (tb->L[0], n + item_pos - ret_val)) ? (int)((l_n / UNFM_P_SIZE) * tb->tb_fs->fs_blocksize) : l_n; set_offset (key_format (key), key, get_offset (key) + temp_n); //B_N_PDELIM_KEY(tb->CFL[0],tb->lkey[0])->k_offset += l_n; key = B_N_PDELIM_KEY(tb->CFL[0],tb->lkey[0]); set_offset (key_format (key), key, get_offset (key) + temp_n); /* Calculate new body, position in item and insert_size[0] */ if ( l_n > zeros_number ) { body += (l_n - zeros_number); zeros_number = 0; } else zeros_number -= l_n; pos_in_item = 0; } else { /* only part of the appended item will be in L[0] */ /* Calculate position in item for append in S[0] */ pos_in_item -= tb->lbytes; /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */ leaf_shift_left(tb,tb->lnum[0],tb->lbytes); } } } else { /* appended item will be in L[0] in whole */ struct item_head * pasted; if ( ! item_pos && is_left_mergeable (tb->tb_fs, tb->tb_path) == 1 ) { /* if we paste into first item of S[0] and it is left mergable */ /* then increment pos_in_item by the size of the last item in L[0] */ pasted = B_N_PITEM_HEAD(tb->L[0],n-1); if ( I_IS_DIRECTORY_ITEM(pasted) ) pos_in_item += get_ih_entry_count (pasted); else pos_in_item += get_ih_item_len (pasted); } /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */ ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes); /* Append to body of item in L[0] */ bi.bi_bh = tb->L[0]; bi.bi_parent = tb->FL[0]; bi.bi_position = get_left_neighbor_position (tb, 0); leaf_paste_in_buffer (tb->tb_fs, &bi, n + item_pos - ret_val, pos_in_item, tb->insert_size[0], body, zeros_number); /* if appended item is directory, paste entry */ pasted = B_N_PITEM_HEAD (tb->L[0], n + item_pos - ret_val); if (I_IS_DIRECTORY_ITEM (pasted)) leaf_paste_entries (bi.bi_bh, n + item_pos - ret_val, pos_in_item, 1, (struct reiserfs_de_head *)body, body + DEH_SIZE, tb->insert_size[0]); /* if appended item is indirect item, put unformatted node into un list */ if (I_IS_INDIRECT_ITEM (pasted)) set_ih_free_space (pasted, 0); tb->insert_size[0] = 0; zeros_number = 0; } break; default: /* cases d and t */ reiserfs_panic ("PAP-12130: balance_leaf: lnum > 0: unexpectable mode: %s(%d)", (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); } } else { /* new item doesn't fall into L[0] */ leaf_shift_left (tb, tb->lnum[0], tb->lbytes); } } /* tb->lnum[0] > 0 */ /* Calculate new item position */ item_pos -= ( tb->lnum[0] - (( tb->lbytes != -1 ) ? 1 : 0)); if ( tb->rnum[0] > 0 ) { /* shift rnum[0] items from S[0] to the right neighbor R[0] */ n = B_NR_ITEMS(tbS0); switch ( flag ) { case M_INSERT: /* insert item */ if ( n - tb->rnum[0] < item_pos ) { /* new item or its part falls to R[0] */ if ( item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1 ) { /* part of new item falls into R[0] */ loff_t old_key_comp, old_len, r_zeros_number; const char * r_body; loff_t multiplyer; leaf_shift_right(tb, tb->rnum[0] - 1, -1); /* Remember key component and item length */ old_key_comp = get_offset (&ih->ih_key); old_len = get_ih_item_len (ih); multiplyer = is_indirect_ih(ih) ? tb->tb_fs->fs_blocksize / UNFM_P_SIZE : 1; /* Calculate key component and item length to insert into R[0] */ //ih->ih_key.k_offset += (old_len - tb->rbytes); set_offset (key_format (&ih->ih_key), &ih->ih_key, old_key_comp + (old_len - tb->rbytes) * multiplyer ); set_ih_item_len (ih, tb->rbytes); /* Insert part of the item into R[0] */ bi.bi_bh = tb->R[0]; bi.bi_parent = tb->FR[0]; bi.bi_position = get_right_neighbor_position (tb, 0); if (old_len - tb->rbytes > zeros_number ) { r_zeros_number = 0; r_body = body + old_len - tb->rbytes - zeros_number; } else { /* zeros_number is always 0 */ r_body = body; r_zeros_number = zeros_number - old_len - tb->rbytes; zeros_number -= r_zeros_number; } leaf_insert_into_buf (tb->tb_fs, &bi, 0, ih, r_body, r_zeros_number); /* Replace right delimiting key by first key in R[0] */ replace_key(tb->tb_fs, tb->CFR[0],tb->rkey[0],tb->R[0],0); /* Calculate key component and item length to insert into S[0] */ //ih->ih_key.k_offset = old_key_comp; set_offset (key_format (&ih->ih_key), &ih->ih_key, old_key_comp); set_ih_item_len (ih, old_len - tb->rbytes); tb->insert_size[0] -= tb->rbytes; } else { /* whole new item falls into R[0] */ /* Shift rnum[0]-1 items to R[0] */ ret_val = leaf_shift_right(tb, tb->rnum[0] - 1, tb->rbytes); /* Insert new item into R[0] */ bi.bi_bh = tb->R[0]; bi.bi_parent = tb->FR[0]; bi.bi_position = get_right_neighbor_position (tb, 0); leaf_insert_into_buf (tb->tb_fs, &bi, item_pos - n + tb->rnum[0] - 1, ih, body, zeros_number); /* If we insert new item in the begin of R[0] change the right delimiting key */ if ( item_pos - n + tb->rnum[0] - 1 == 0 ) { replace_key (tb->tb_fs, tb->CFR[0],tb->rkey[0],tb->R[0],0); } zeros_number = tb->insert_size[0] = 0; } } else { /* new item or part of it doesn't fall into R[0] */ leaf_shift_right (tb, tb->rnum[0], tb->rbytes); } break; case M_PASTE: /* append item */ if ( n - tb->rnum[0] <= item_pos ) { /* pasted item or part of it falls to R[0] */ if ( item_pos == n - tb->rnum[0] && tb->rbytes != -1 ) { /* we must shift the part of the appended item */ if ( I_IS_DIRECTORY_ITEM (B_N_PITEM_HEAD(tbS0, item_pos))) { /* we append to directory item */ int entry_count; entry_count = get_ih_entry_count (B_N_PITEM_HEAD(tbS0, item_pos)); if ( entry_count - tb->rbytes < pos_in_item ) { /* new directory entry falls into R[0] */ int paste_entry_position; /* Shift rnum[0]-1 items in whole. Shift rbytes-1 directory entries from directory item number rnum[0] */ leaf_shift_right (tb, tb->rnum[0], tb->rbytes - 1); /* Paste given directory entry to directory item */ paste_entry_position = pos_in_item - entry_count + tb->rbytes - 1; bi.bi_bh = tb->R[0]; bi.bi_parent = tb->FR[0]; bi.bi_position = get_right_neighbor_position (tb, 0); leaf_paste_in_buffer (tb->tb_fs, &bi, 0, paste_entry_position, tb->insert_size[0],body,zeros_number); /* paste entry */ leaf_paste_entries ( bi.bi_bh, 0, paste_entry_position, 1, (struct reiserfs_de_head *)body, body + DEH_SIZE, tb->insert_size[0] ); if ( paste_entry_position == 0 ) { /* change delimiting keys */ replace_key(tb->tb_fs, tb->CFR[0],tb->rkey[0],tb->R[0],0); } tb->insert_size[0] = 0; pos_in_item++; } else { /* new directory entry doesn't fall into R[0] */ leaf_shift_right (tb, tb->rnum[0],tb->rbytes); } } else { /* regular object */ int n_shift, n_rem, r_zeros_number; const char * r_body; struct key * key; /* Calculate number of bytes which must be shifted from appended item */ if ( (n_shift = tb->rbytes - tb->insert_size[0]) < 0 ) n_shift = 0; leaf_shift_right (tb, tb->rnum[0], n_shift); /* Calculate number of bytes which must remain in body after appending to R[0] */ if ( (n_rem = tb->insert_size[0] - tb->rbytes) < 0 ) n_rem = 0; { unsigned long temp_rem = n_rem; if (is_indirect_key(B_N_PKEY(tb->R[0],0))) temp_rem = (n_rem / UNFM_P_SIZE) * tb->tb_fs->fs_blocksize; //B_N_PKEY(tb->R[0],0)->k_offset += n_rem; key = B_N_PKEY(tb->R[0],0); set_offset (key_format (key), key, get_offset (key) + temp_rem); //B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0])->k_offset += n_rem; key = B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0]); set_offset (key_format (key), key, get_offset (key) + temp_rem); } mark_buffer_dirty (tb->CFR[0]); /* Append part of body into R[0] */ bi.bi_bh = tb->R[0]; bi.bi_parent = tb->FR[0]; bi.bi_position = get_right_neighbor_position (tb, 0); if ( n_rem > zeros_number ) { r_zeros_number = 0; r_body = body + n_rem - zeros_number; } else { r_body = body; r_zeros_number = zeros_number - n_rem; zeros_number -= r_zeros_number; } leaf_paste_in_buffer(tb->tb_fs, &bi, 0, n_shift, tb->insert_size[0] - n_rem, r_body, r_zeros_number); if (I_IS_INDIRECT_ITEM(B_N_PITEM_HEAD(tb->R[0],0))) { set_ih_free_space (B_N_PITEM_HEAD(tb->R[0],0), 0); } tb->insert_size[0] = n_rem; if ( ! n_rem ) pos_in_item ++; } } else { /* pasted item falls into R[0] entirely */ struct item_head * pasted; ret_val = leaf_shift_right (tb, tb->rnum[0], tb->rbytes); /* append item in R[0] */ if ( pos_in_item >= 0 ) { bi.bi_bh = tb->R[0]; bi.bi_parent = tb->FR[0]; bi.bi_position = get_right_neighbor_position (tb, 0); leaf_paste_in_buffer(tb->tb_fs, &bi,item_pos - n + tb->rnum[0], pos_in_item, tb->insert_size[0],body, zeros_number); } /* paste new entry, if item is directory item */ pasted = B_N_PITEM_HEAD(tb->R[0], item_pos - n + tb->rnum[0]); if (I_IS_DIRECTORY_ITEM (pasted) && pos_in_item >= 0 ) { leaf_paste_entries (bi.bi_bh, item_pos - n + tb->rnum[0], pos_in_item, 1, (struct reiserfs_de_head *)body, body + DEH_SIZE, tb->insert_size[0]); if ( ! pos_in_item ) { /* update delimiting keys */ replace_key (tb->tb_fs, tb->CFR[0],tb->rkey[0],tb->R[0],0); } } if (I_IS_INDIRECT_ITEM (pasted)) set_ih_free_space (pasted, 0); zeros_number = tb->insert_size[0] = 0; } } else { /* new item doesn't fall into R[0] */ leaf_shift_right (tb, tb->rnum[0], tb->rbytes); } break; default: /* cases d and t */ reiserfs_panic ("PAP-12175: balance_leaf: rnum > 0: unexpectable mode: %s(%d)", (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); } } /* tb->rnum[0] > 0 */ /* if while adding to a node we discover that it is possible to split it in two, and merge the left part into the left neighbor and the right part into the right neighbor, eliminating the node */ if ( tb->blknum[0] == 0 ) { /* node S[0] is empty now */ /* if insertion was done before 0-th position in R[0], right delimiting key of the tb->L[0]'s and left delimiting key are not set correctly */ if (tb->CFL[0]) { if (!tb->CFR[0]) reiserfs_panic (tb->tb_fs, "vs-12195: balance_leaf: CFR not initialized"); copy_key (B_N_PDELIM_KEY (tb->CFL[0], tb->lkey[0]), B_N_PDELIM_KEY (tb->CFR[0], tb->rkey[0])); mark_buffer_dirty (tb->CFL[0]); } reiserfs_invalidate_buffer(tb,tbS0, 1); return 0; } /* Fill new nodes that appear in place of S[0] */ /* I am told that this copying is because we need an array to enable the looping code. -Hans */ snum[0] = tb->s1num, snum[1] = tb->s2num; sbytes[0] = tb->s1bytes; sbytes[1] = tb->s2bytes; for( i = tb->blknum[0] - 2; i >= 0; i-- ) { /* here we shift from S to S_new nodes */ S_new[i] = get_FEB(tb); /* set block_head's level to leaf level */ set_blkh_level (B_BLK_HEAD (S_new[i]), DISK_LEAF_NODE_LEVEL); n = B_NR_ITEMS(tbS0); switch (flag) { case M_INSERT: /* insert item */ if ( n - snum[i] < item_pos ) { /* new item or it's part falls to first new node S_new[i]*/ if ( item_pos == n - snum[i] + 1 && sbytes[i] != -1 ) { /* part of new item falls into S_new[i] */ int old_key_comp, old_len, r_zeros_number; const char * r_body; loff_t multiplyer; /* Move snum[i]-1 items from S[0] to S_new[i] */ leaf_move_items (LEAF_FROM_S_TO_SNEW, tb, snum[i] - 1, -1, S_new[i]); /* Remember key component and item length */ old_key_comp = get_offset (&ih->ih_key); old_len = get_ih_item_len (ih); multiplyer = is_indirect_ih(ih) ? tb->tb_fs->fs_blocksize / UNFM_P_SIZE : 1; /* Calculate key component and item length to insert into S_new[i] */ //ih->ih_key.k_offset += (old_len - sbytes[i]); set_offset (key_format (&ih->ih_key), &ih->ih_key, old_key_comp + (old_len - sbytes[i]) * multiplyer); set_ih_item_len (ih, sbytes[i]); /* Insert part of the item into S_new[i] before 0-th item */ bi.bi_bh = S_new[i]; bi.bi_parent = 0; bi.bi_position = 0; if ( old_len - sbytes[i] > zeros_number ) { r_zeros_number = 0; r_body = body + (old_len - sbytes[i]) - zeros_number; } else { r_body = body; r_zeros_number = zeros_number - (old_len - sbytes[i]); zeros_number -= r_zeros_number; } leaf_insert_into_buf (tb->tb_fs, &bi, 0, ih, r_body, r_zeros_number); /* Calculate key component and item length to insert into S[i] */ //ih->ih_key.k_offset = old_key_comp; set_offset (key_format (&ih->ih_key), &ih->ih_key, old_key_comp); set_ih_item_len (ih, old_len - sbytes[i]); tb->insert_size[0] -= sbytes[i]; } else /* whole new item falls into S_new[i] */ { /* Shift snum[0] - 1 items to S_new[i] (sbytes[i] of split item) */ leaf_move_items (LEAF_FROM_S_TO_SNEW, tb, snum[i] - 1, sbytes[i], S_new[i]); /* Insert new item into S_new[i] */ bi.bi_bh = S_new[i]; bi.bi_parent = 0; bi.bi_position = 0; leaf_insert_into_buf (tb->tb_fs, &bi, item_pos - n + snum[i] - 1, ih, body, zeros_number); zeros_number = tb->insert_size[0] = 0; } } else /* new item or it part don't falls into S_new[i] */ { leaf_move_items (LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i], S_new[i]); } break; case M_PASTE: /* append item */ if ( n - snum[i] <= item_pos ) /* pasted item or part if it falls to S_new[i] */ { if ( item_pos == n - snum[i] && sbytes[i] != -1 ) { /* we must shift part of the appended item */ struct item_head * aux_ih; if ( I_IS_DIRECTORY_ITEM (aux_ih = B_N_PITEM_HEAD(tbS0,item_pos))) { /* we append to directory item */ int entry_count; entry_count = get_ih_entry_count(aux_ih); if ( entry_count - sbytes[i] < pos_in_item && pos_in_item <= entry_count ) { /* new directory entry falls into S_new[i] */ /* Shift snum[i]-1 items in whole. Shift sbytes[i] directory entries from directory item number snum[i] */ leaf_move_items (LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i]-1, S_new[i]); /* Paste given directory entry to directory item */ bi.bi_bh = S_new[i]; bi.bi_parent = 0; bi.bi_position = 0; leaf_paste_in_buffer (tb->tb_fs, &bi, 0, pos_in_item - entry_count + sbytes[i] - 1, tb->insert_size[0], body,zeros_number); /* paste new directory entry */ leaf_paste_entries ( bi.bi_bh, 0, pos_in_item - entry_count + sbytes[i] - 1, 1, (struct reiserfs_de_head *)body, body + DEH_SIZE, tb->insert_size[0] ); tb->insert_size[0] = 0; pos_in_item++; } else { /* new directory entry doesn't fall into S_new[i] */ leaf_move_items (LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i], S_new[i]); } } else /* regular object */ { int n_shift, n_rem, r_zeros_number; const char * r_body; struct item_head * tmp; /* Calculate number of bytes which must be shifted from appended item */ n_shift = sbytes[i] - tb->insert_size[0]; if ( n_shift < 0 ) n_shift = 0; leaf_move_items (LEAF_FROM_S_TO_SNEW, tb, snum[i], n_shift, S_new[i]); /* Calculate number of bytes which must remain in body after append to S_new[i] */ n_rem = tb->insert_size[0] - sbytes[i]; if ( n_rem < 0 ) n_rem = 0; /* Append part of body into S_new[0] */ bi.bi_bh = S_new[i]; bi.bi_parent = 0; bi.bi_position = 0; if ( n_rem > zeros_number ) { r_zeros_number = 0; r_body = body + n_rem - zeros_number; } else { r_body = body; r_zeros_number = zeros_number - n_rem; zeros_number -= r_zeros_number; } leaf_paste_in_buffer(tb->tb_fs, &bi, 0, n_shift, tb->insert_size[0]-n_rem, r_body,r_zeros_number); tmp = B_N_PITEM_HEAD (S_new[i], 0); if (I_IS_INDIRECT_ITEM(tmp)) { /* if (n_rem) reiserfs_panic ("PAP-12230: balance_leaf: " "invalid action with indirect item"); set_ih_free_space (tmp, 0); */ set_ih_free_space (tmp, 0); set_offset( key_format (&tmp->ih_key), &tmp->ih_key, get_offset(&tmp->ih_key) + (n_rem / UNFM_P_SIZE) * tb->tb_fs->fs_blocksize); } else set_offset (key_format (&tmp->ih_key), &tmp->ih_key, get_offset (&tmp->ih_key) + n_rem); //B_N_PKEY(S_new[i],0)->k_offset += n_rem; // tb->insert_size[0] = n_rem; if ( ! n_rem ) pos_in_item++; } } else /* item falls wholly into S_new[i] */ { struct item_head * pasted; leaf_move_items (LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i], S_new[i]); /* paste into item */ bi.bi_bh = S_new[i]; bi.bi_parent = 0; bi.bi_position = 0; leaf_paste_in_buffer(tb->tb_fs, &bi, item_pos - n + snum[i], pos_in_item, tb->insert_size[0], body, zeros_number); pasted = B_N_PITEM_HEAD(S_new[i], item_pos - n + snum[i]); if (I_IS_DIRECTORY_ITEM (pasted)) { leaf_paste_entries (bi.bi_bh, item_pos - n + snum[i], pos_in_item, 1, (struct reiserfs_de_head *)body, body + DEH_SIZE, tb->insert_size[0]); } /* if we paste to indirect item update ih_free_space */ if (I_IS_INDIRECT_ITEM (pasted)) set_ih_free_space (pasted, 0); zeros_number = tb->insert_size[0] = 0; } } else { /* pasted item doesn't fall into S_new[i] */ leaf_move_items (LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i], S_new[i]); } break; default: /* cases d and t */ reiserfs_panic ("PAP-12245: balance_leaf: blknum > 2: unexpectable mode: %s(%d)", (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); } memcpy (insert_key + i,B_N_PKEY(S_new[i],0),KEY_SIZE); insert_ptr[i] = S_new[i]; } /* if the affected item was not wholly shifted then we perform all necessary operations on that part or whole of the affected item which remains in S */ if ( 0 <= item_pos && item_pos < tb->s0num ) { /* if we must insert or append into buffer S[0] */ switch (flag) { case M_INSERT: /* insert item into S[0] */ bi.bi_bh = tbS0; bi.bi_parent = PATH_H_PPARENT (tb->tb_path, 0); bi.bi_position = PATH_H_POSITION (tb->tb_path, 1); leaf_insert_into_buf (tb->tb_fs, &bi, item_pos, ih, body, zeros_number); /* If we insert the first key change the delimiting key */ if( item_pos == 0 ) { if (tb->CFL[0]) /* can be 0 in reiserfsck */ replace_key (tb->tb_fs, tb->CFL[0], tb->lkey[0],tbS0,0); } break; case M_PASTE: { /* append item in S[0] */ struct item_head * pasted; pasted = B_N_PITEM_HEAD (tbS0, item_pos); /* when directory, may be new entry already pasted */ if (I_IS_DIRECTORY_ITEM (pasted)) { if ( pos_in_item >= 0 && pos_in_item <= get_ih_entry_count (pasted) ) { /* prepare space */ bi.bi_bh = tbS0; bi.bi_parent = PATH_H_PPARENT (tb->tb_path, 0); bi.bi_position = PATH_H_POSITION (tb->tb_path, 1); leaf_paste_in_buffer(tb->tb_fs, &bi, item_pos, pos_in_item, tb->insert_size[0], body, zeros_number); /* paste entry */ leaf_paste_entries (bi.bi_bh, item_pos, pos_in_item, 1, (struct reiserfs_de_head *)body, body + DEH_SIZE, tb->insert_size[0]); if ( ! item_pos && ! pos_in_item ) { if (tb->CFL[0]) // can be 0 in reiserfsck replace_key(tb->tb_fs, tb->CFL[0], tb->lkey[0],tbS0,0); } tb->insert_size[0] = 0; } } else { /* regular object */ if ( pos_in_item == get_ih_item_len (pasted) ) { bi.bi_bh = tbS0; bi.bi_parent = PATH_H_PPARENT (tb->tb_path, 0); bi.bi_position = PATH_H_POSITION (tb->tb_path, 1); leaf_paste_in_buffer (tb->tb_fs, &bi, item_pos, pos_in_item, tb->insert_size[0], body, zeros_number); if (I_IS_INDIRECT_ITEM (pasted)) { set_ih_free_space (pasted, 0); } tb->insert_size[0] = 0; } } } /* case M_PASTE: */ } } return 0; } /* Leaf level of the tree is balanced (end of balance_leaf) */ void make_empty_leaf (struct buffer_head * bh) { set_blkh_nr_items (B_BLK_HEAD (bh), 0); set_blkh_free_space (B_BLK_HEAD (bh), MAX_FREE_SPACE (bh->b_size)); set_blkh_level (B_BLK_HEAD (bh), DISK_LEAF_NODE_LEVEL); } /* Make empty node */ void make_empty_node (struct buffer_info * bi) { make_empty_leaf (bi->bi_bh); if (bi->bi_parent) set_dc_child_size (B_N_CHILD (bi->bi_parent, bi->bi_position), 0); } /* Get first empty buffer */ struct buffer_head * get_FEB (struct tree_balance * tb) { int i; struct buffer_head * first_b; struct buffer_info bi; for (i = 0; i < MAX_FEB_SIZE; i ++) if (tb->FEB[i] != 0) break; if (i == MAX_FEB_SIZE) reiserfs_panic("vs-12300: get_FEB: FEB list is empty"); bi.bi_bh = first_b = tb->FEB[i]; bi.bi_parent = 0; bi.bi_position = 0; make_empty_node (&bi); misc_set_bit(BH_Uptodate, &first_b->b_state); tb->FEB[i] = 0; tb->used[i] = first_b; return(first_b); } /* Replace n_dest'th key in buffer dest by n_src'th key of buffer src.*/ void replace_key (reiserfs_filsys_t * fs, struct buffer_head * dest, int n_dest, struct buffer_head * src, int n_src) { if (dest) { if (is_leaf_node (src)) /* source buffer contains leaf node */ memcpy (B_N_PDELIM_KEY(dest,n_dest), B_N_PITEM_HEAD(src,n_src), KEY_SIZE); else memcpy (B_N_PDELIM_KEY(dest,n_dest), B_N_PDELIM_KEY(src,n_src), KEY_SIZE); mark_buffer_dirty(dest); } } void reiserfs_invalidate_buffer (struct tree_balance * tb, struct buffer_head * bh, int do_free_block) { set_blkh_level (B_BLK_HEAD (bh), FREE_LEVEL); misc_clear_bit(BH_Dirty, &bh->b_state); if (do_free_block) { struct buffer_head * to_be_forgotten; to_be_forgotten = find_buffer (bh->b_dev, bh->b_blocknr, bh->b_size); if (to_be_forgotten) { to_be_forgotten->b_count ++; bforget (to_be_forgotten); } reiserfs_free_block (tb->tb_fs, bh->b_blocknr); } } int get_left_neighbor_position ( struct tree_balance * tb, int h ) { int Sh_position = PATH_H_POSITION (tb->tb_path, h + 1); if (Sh_position == 0) return B_NR_ITEMS (tb->FL[h]); else return Sh_position - 1; } int get_right_neighbor_position (struct tree_balance * tb, int h) { int Sh_position = PATH_H_POSITION (tb->tb_path, h + 1); if (Sh_position == B_NR_ITEMS (PATH_H_PPARENT (tb->tb_path, h))) return 0; else return Sh_position + 1; } /* Now we have all of the buffers that must be used in balancing of the tree. We rely on the assumption that schedule() will not occur while do_balance works. ( Only interrupt handlers are acceptable.) We balance the tree according to the analysis made before this, using buffers already obtained. For SMP support it will someday be necessary to add ordered locking of tb. */ /* Some interesting rules of balancing: we delete a maximum of two nodes per level per balancing: we never delete R, when we delete two of three nodes L, S, R then we move them into R. we only delete L if we are deleting two nodes, if we delete only one node we delete S if we shift leaves then we shift as much as we can: this is a deliberate policy of extremism in node packing which results in higher average utilization after repeated random balance operations at the cost of more memory copies and more balancing as a result of small insertions to full nodes. if we shift internal nodes we try to evenly balance the node utilization, with consequent less balancing at the cost of lower utilization. one could argue that the policy for directories in leaves should be that of internal nodes, but we will wait until another day to evaluate this.... It would be nice to someday measure and prove these assumptions as to what is optimal.... */ void do_balance (struct tree_balance * tb, /* tree_balance structure */ struct item_head * ih, /* item header of inserted item */ const char * body, /* body of inserted item or bytes to paste */ int flag, /* i - insert, d - delete c - cut, p - paste Cut means delete part of an item (includes removing an entry from a directory). Delete means delete whole item. Insert means add a new item into the tree. Paste means to append to the end of an existing file or to insert a directory entry. */ int zeros_num) { //int pos_in_item = tb->tb_path->pos_in_item; int child_pos, /* position of a child node in its parent */ h; /* level of the tree being processed */ struct item_head insert_key[2]; /* in our processing of one level we sometimes determine what must be inserted into the next higher level. This insertion consists of a key or two keys and their corresponding pointers */ struct buffer_head *insert_ptr[2]; /* inserted node-ptrs for the next level */ /* if we have no real work to do */ if ( ! tb->insert_size[0] ) { unfix_nodes(/*th,*/ tb); return; } if (flag == M_INTERNAL) { insert_ptr[0] = (struct buffer_head *)body; /* we must prepare insert_key */ if (PATH_H_B_ITEM_ORDER (tb->tb_path, 0)/*LAST_POSITION (tb->tb_path)*//*item_pos*/ == -1) { /* get delimiting key from buffer in tree */ copy_key (&insert_key[0].ih_key, B_N_PKEY (PATH_PLAST_BUFFER (tb->tb_path), 0)); /*insert_ptr[0]->b_item_order = 0;*/ } else { /* get delimiting key from new buffer */ copy_key (&insert_key[0].ih_key, B_N_PKEY((struct buffer_head *)body,0)); /*insert_ptr[0]->b_item_order = item_pos;*/ } /* and insert_ptr instead of balance_leaf */ child_pos = PATH_H_B_ITEM_ORDER (tb->tb_path, 0)/*item_pos*/; } else /* balance leaf returns 0 except if combining L R and S into one node. see balance_internal() for explanation of this line of code.*/ child_pos = PATH_H_B_ITEM_ORDER (tb->tb_path, 0) + balance_leaf (/*th,*/ tb/*, pos_in_item*/, ih, body, flag, zeros_num, insert_key, insert_ptr); /* Balance internal level of the tree. */ for ( h = 1; h < MAX_HEIGHT && tb->insert_size[h]; h++ ) child_pos = balance_internal (/*th,*/ tb, h, child_pos, insert_key, insert_ptr); /* Release all (except for S[0]) non NULL buffers fixed by fix_nodes() */ unfix_nodes(/*th,*/ tb); } reiserfsprogs-3.6.9/install-sh0000775000077100007710000001273607665645672012161 #!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 reiserfsprogs-3.6.9/missing0000755000077100007710000002403607634203260011521 #! /bin/sh # Common stub for a few missing GNU programs while installing. # Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch]" ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing 0.4 - GNU automake" ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; aclocal*) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. You can get \`$1Help2man' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then # We have makeinfo, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` fi touch $file ;; tar) shift if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 fi # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequirements for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 reiserfsprogs-3.6.9/mkinstalldirs0000775000077100007710000000132407665645672012752 #! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.1.1.1 2000/08/03 10:35:16 vs Exp $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here reiserfsprogs-3.6.9/Makefile.am0000664000077100007710000000031707705261642012163 SUBDIRS = include lib reiserfscore fsck debugreiserfs resize_reiserfs mkreiserfs tune tests noinst_DATA = reiserfsprogs.spec EXTRA_DIST = CREDITS version.h dist-hook: cp -f reiserfsprogs.spec $(distdir) reiserfsprogs-3.6.9/Makefile.in0000644000077100007710000003654007705315225012176 # Makefile.in generated by automake 1.7.2 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__quote = @am__quote@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ SUBDIRS = include lib reiserfscore fsck debugreiserfs resize_reiserfs mkreiserfs tune tests noinst_DATA = reiserfsprogs.spec EXTRA_DIST = CREDITS version.h subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = DATA = $(noinst_DATA) RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ ps-recursive install-info-recursive uninstall-info-recursive \ all-recursive install-data-recursive install-exec-recursive \ installdirs-recursive install-recursive uninstall-recursive \ check-recursive installcheck-recursive DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \ Makefile.in NEWS aclocal.m4 configure configure.in depcomp \ install-sh missing mkinstalldirs DIST_SUBDIRS = $(SUBDIRS) all: all-recursive .SUFFIXES: am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe) $(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): configure.in cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @set fnord $$MAKEFLAGS; amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $$MAKEFLAGS; amf=$$2; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = . distdir = $(PACKAGE)-$(VERSION) am__remove_distdir = \ { test ! -d $(distdir) \ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr $(distdir); }; } GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print distdir: $(DISTFILES) $(am__remove_distdir) mkdir $(distdir) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" \ distdir=../$(distdir)/$$subdir \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist-gzip: distdir $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist dist-all: distdir $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist $(am__remove_distdir) GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/=build mkdir $(distdir)/=inst chmod a-w $(distdir) dc_install_base=`$(am__cd) $(distdir)/=inst && pwd` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && cd $(distdir)/=build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && $(mkinstalldirs) "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist-gzip \ && rm -f $(distdir).tar.gz \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @echo "$(distdir).tar.gz is ready for distribution" | \ sed 'h;s/./=/g;p;x;p;x' distuninstallcheck: cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: info: info-recursive info-am: install-data-am: install-exec-am: install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf autom4te.cache maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \ clean-generic clean-recursive ctags ctags-recursive dist \ dist-all dist-gzip distcheck distclean distclean-generic \ distclean-recursive distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am dvi-recursive info info-am \ info-recursive install install-am install-data install-data-am \ install-data-recursive install-exec install-exec-am \ install-exec-recursive install-info install-info-am \ install-info-recursive install-man install-recursive \ install-strip installcheck installcheck-am installdirs \ installdirs-am installdirs-recursive maintainer-clean \ maintainer-clean-generic maintainer-clean-recursive mostlyclean \ mostlyclean-generic mostlyclean-recursive pdf pdf-am \ pdf-recursive ps ps-am ps-recursive tags tags-recursive \ uninstall uninstall-am uninstall-info-am \ uninstall-info-recursive uninstall-recursive dist-hook: cp -f reiserfsprogs.spec $(distdir) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: reiserfsprogs-3.6.9/debugreiserfs/0000777000077100007710000000000007705315453013041 5reiserfsprogs-3.6.9/debugreiserfs/unpack.c0000664000077100007710000003715007705261642014412 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "debugreiserfs.h" #include #define print_usage_and_exit() die ("Usage: %s [-v] [-b filename] device\n\ -v prints blocks number of every block unpacked\n\ -b filename makes unpack to save bitmap of blocks unpacked\n\ -j filename makes unpack to store journal in specified file\n", argv[0]); /* when super block gets unpacked for the first time - create a bitmap and mark in it what have been unpacked. Save that bitmap at the end */ reiserfs_bitmap_t * what_unpacked = 0; int leaves, full; int verbose = 0; int Default_journal = 1; static void unpack_offset (struct packed_item * pi, struct item_head * ih, int blocksize) { if (get_pi_mask(pi) & OFFSET_BITS_64) { __u64 v64; if (get_ih_key_format (ih) != KEY_FORMAT_2) die ("unpack_offset: key format is not set or wrong"); fread_le64 (&v64); set_offset (KEY_FORMAT_2, &ih->ih_key, v64); return; } if (get_pi_mask(pi) & OFFSET_BITS_32) { __u32 v32; fread_le32 (&v32); set_offset (get_ih_key_format (ih), &ih->ih_key, v32); return; } if ((get_pi_mask(pi) & DIR_ID) == 0 && (get_pi_mask(pi) & OBJECT_ID) == 0) { /* offset was not sent, as it can be calculated looking at the previous item */ if (is_stat_data_ih (ih - 1)) set_offset (get_ih_key_format (ih), &ih->ih_key, 1); if (is_indirect_ih (ih - 1)) set_offset (get_ih_key_format (ih), &ih->ih_key, get_offset (&(ih - 1)->ih_key) + get_bytes_number (ih - 1, blocksize)); } // offset is 0 return; } static void unpack_type (struct packed_item * pi, struct item_head * ih) { set_type (get_ih_key_format (ih), &ih->ih_key, get_pi_type(pi)); if (type_unknown (&ih->ih_key)) reiserfs_panic ("unpack_type: unknown type %d unpacked for %H\n", get_pi_type(pi), ih); } /* direntry item comes in the following format: for each entry mask - 8 bits entry length - 16 bits entry itself deh_objectid - 32 bits maybe deh_dir_id (32 bits) maybe gencounter (16) maybe deh_state (16) */ static void unpack_direntry (struct packed_item * pi, struct buffer_head * bh, struct item_head * ih, hashf_t hash_func) { __u16 entry_count, namelen, gen_counter, entry_len; __u8 mask; int i; struct reiserfs_de_head * deh; int location; char * item; /* if (!hash_func) die ("unpack_direntry: hash function is not set");*/ if (!(get_pi_mask(pi) & IH_FREE_SPACE)) die ("ih_entry_count must be packed for directory items"); entry_count = get_ih_entry_count (ih); /* if (!entry_count) reiserfs_panic ("unpack_direntry: entry count should be set already");*/ item = bh->b_data + get_ih_location (ih); deh = (struct reiserfs_de_head *)item; location = get_pi_item_len(pi); for (i = 0; i < entry_count; i ++, deh ++) { fread8 (&mask); fread_le16 (&entry_len); location -= entry_len; set_deh_location (deh, location); fread (item + location, entry_len, 1, stdin); /* find name length */ if (*(item + location + entry_len - 1)) namelen = entry_len; else namelen = strlen (item + location); fread32 (&deh->deh2_objectid); if (mask & HAS_DIR_ID) fread32 (&deh->deh2_dir_id); else set_deh_dirid (deh, get_key_objectid (&ih->ih_key)); if (*(item + location) == '.' && namelen == 1) /* old or new "." */ set_deh_offset (deh, DOT_OFFSET); else if (*(item + location) == '.' && *(item + location + 1) == '.' && namelen == 2) /* old or new ".." */ set_deh_offset (deh, DOT_DOT_OFFSET); else if (hash_func) set_deh_offset (deh, GET_HASH_VALUE (hash_func (item + location, namelen))); if (mask & HAS_GEN_COUNTER) { fread_le16 (&gen_counter); set_deh_offset (deh, get_deh_offset (deh) | gen_counter); } if (mask & HAS_STATE) fread16 (&deh->deh2_state); else set_deh_state (deh, (1 << DEH_Visible2)); } return; } /* struct packed_item is already unpacked */ static void unpack_stat_data (struct packed_item * pi, struct buffer_head * bh, struct item_head * ih) { if (!(get_pi_mask(pi) & IH_FREE_SPACE)) { /* ih_free_space was not packed - set default */ set_ih_entry_count (ih, 0xffff); } if (get_ih_key_format (ih) == KEY_FORMAT_1) { /* stat data comes in the following format: if this is old stat data: mode - 16 bits nlink - 16 bits size - 32 bits blocks/rdev - 32 bits maybe first_direct byte 32 bits */ struct stat_data_v1 * sd; sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih); memset (sd, 0, sizeof (sd)); fread16 (&sd->sd_mode); fread16 (&sd->sd_nlink); fread32 (&sd->sd_size); fread32 (&sd->u.sd_blocks); if (get_pi_mask(pi) & WITH_SD_FIRST_DIRECT_BYTE) { fread32 (&sd->sd_first_direct_byte); } else { sd->sd_first_direct_byte = 0xffffffff; } } else { /* for new stat data mode - 16 bits nlink in either 16 or 32 bits size in either 32 or 64 bits blocks - 32 bits */ struct stat_data * sd; sd = (struct stat_data *)B_I_PITEM (bh, ih); memset (sd, 0, sizeof (sd)); fread16 (&sd->sd_mode); if (get_pi_mask(pi) & NLINK_BITS_32) { fread32 (&sd->sd_nlink); } else { __u16 nlink16; fread16 (&nlink16); set_sd_v2_nlink (sd, le16_to_cpu(nlink16)); } if (get_pi_mask(pi) & SIZE_BITS_64) { fread64 (&sd->sd_size); } else { __u32 size32; /* We need the endian conversions since sd->sd_size is 64 bit */ fread_le32 (&size32); set_sd_v2_size (sd, size32 ); } fread32 (&sd->sd_blocks); } return; } /* indirect item comes either in packed form or as is. ih_free_space can go first */ static void unpack_indirect (struct packed_item * pi, struct buffer_head * bh, struct item_head * ih) { __u32 * ind_item, * end; int i; __u16 v16; if (!(get_pi_mask(pi) & IH_FREE_SPACE)) { /* ih_free_space was not packed - set default */ set_ih_entry_count (ih, 0); } ind_item = (__u32 *)B_I_PITEM (bh, ih); if (get_pi_mask(pi) & SAFE_LINK) { *ind_item = cpu_to_le32(get_key_dirid(&ih->ih_key)); set_key_dirid(&ih->ih_key, (__u32)-1); return; } if (get_pi_mask(pi) & WHOLE_INDIRECT) { fread (ind_item, get_pi_item_len(pi), 1, stdin); return; } end = ind_item + I_UNFM_NUM (ih); while (ind_item < end) { __u32 base; fread32 (ind_item); fread_le16 (&v16); base = le32_to_cpu(ind_item[0]); for (i = 1; i < v16; i ++) { if (ind_item[0] != 0) ind_item [i] = cpu_to_le32(base + i); else ind_item [i] = 0; } ind_item += i; } return; } // FIXME: we have no way to preserve symlinks static void unpack_direct (struct packed_item * pi, struct buffer_head * bh, struct item_head * ih) { __u32 * d_item = (__u32 *)B_I_PITEM (bh, ih); if (!(get_pi_mask(pi) & IH_FREE_SPACE)) /* ih_free_space was not packed - set default */ set_ih_entry_count (ih, 0xffff); if (get_pi_mask(pi) & SAFE_LINK) { *d_item = cpu_to_le32(get_key_dirid(&ih->ih_key)); set_key_dirid(&ih->ih_key, (__u32)-1); } else { memset (d_item, 'a', get_pi_item_len(pi)); } return; } static void unpack_leaf (int dev, hashf_t hash_func, __u16 blocksize) { static int unpacked_leaves = 0; struct buffer_head * bh; struct packed_item pi; struct item_head * ih; int i; __u16 v16; __u32 v32; /* block number */ fread_le32 (&v32); /* item number */ fread_le16 (&v16); if (verbose) reiserfs_warning (stderr, "leaf %d: %d items\n", v32, v16); bh = getblk (dev, v32, blocksize); if (!bh) die ("unpack_leaf: getblk failed"); set_blkh_nr_items (B_BLK_HEAD (bh), v16); set_blkh_level (B_BLK_HEAD (bh), DISK_LEAF_NODE_LEVEL); set_blkh_free_space (B_BLK_HEAD (bh), MAX_FREE_SPACE (bh->b_size)); ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) { #if 0 fread32 (&v32); if (v32 != ITEM_START_MAGIC) die ("unpack_leaf: no start item magic found: block %lu, item %i", bh->b_blocknr, i); #endif fread (&pi, sizeof (struct packed_item), 1, stdin); /* dir_id - if it is there */ if (get_pi_mask(&pi) & DIR_ID) { fread32 (&v32); set_key_dirid (&ih->ih_key, le32_to_cpu(v32)); } else { if (!i) die ("unpack_leaf: dir_id is not set"); set_key_dirid (&ih->ih_key, get_key_dirid (&(ih - 1)->ih_key)); } /* object_id - if it is there */ if (get_pi_mask(&pi) & OBJECT_ID) { fread32 (&v32); set_key_objectid (&ih->ih_key, le32_to_cpu(v32)); } else { if (!i) die ("unpack_leaf: object_id is not set"); set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key)); } // we need to set item format before offset unpacking set_ih_key_format (ih, (get_pi_mask(&pi) & NEW_FORMAT) ? KEY_FORMAT_2 : KEY_FORMAT_1); // offset unpack_offset (&pi, ih, bh->b_size); /* type */ unpack_type (&pi, ih); /* ih_free_space and ih_format */ if (get_pi_mask(&pi) & IH_FREE_SPACE) { fread16 (&v16); set_ih_entry_count (ih, le16_to_cpu(v16)); } if (get_pi_mask(&pi) & IH_FORMAT) fread16 (&ih->ih_format); /* item length and item location */ set_ih_item_len (ih, get_pi_item_len(&pi)); set_ih_location (ih, (i ? get_ih_location (ih - 1) : bh->b_size) - get_pi_item_len(&pi)); // item itself if (is_direct_ih (ih)) { unpack_direct (&pi, bh, ih); } else if (is_indirect_ih (ih)) { unpack_indirect (&pi, bh, ih); } else if (is_direntry_ih (ih)) { unpack_direntry (&pi, bh, ih, hash_func); } else if (is_stat_data_ih (ih)) { unpack_stat_data (&pi, bh, ih); } set_blkh_free_space (B_BLK_HEAD (bh), get_blkh_free_space (B_BLK_HEAD (bh)) - (IH_SIZE + get_ih_item_len (ih))); #if 0 fread32 (&v32); if (v32 != ITEM_END_MAGIC) die ("unpack_leaf: no end item magic found: block %lu, item %i", bh->b_blocknr, i); if (verbose) reiserfs_warning (stderr, "%d: %H\n", i, ih); #endif } fread_le16 (&v16); if (v16 != LEAF_END_MAGIC) die ("unpack_leaf: wrong end signature found - %x, block %lu", v16, bh->b_blocknr); mark_buffer_uptodate (bh, 1); mark_buffer_dirty (bh); bwrite (bh); /* if (!not_data_block (bh->b_blocknr)) data_blocks_unpacked ++; */ brelse (bh); if (what_unpacked) reiserfs_bitmap_set_bit (what_unpacked, bh->b_blocknr); /*unpacked ++;*/ if (!(++ unpacked_leaves % 10)) fprintf (stderr, "#"); } static void unpack_full_block (int dev, int blocksize) { static int full_blocks_unpacked = 0; __u32 block; struct buffer_head * bh; fread_le32 (&block); if (verbose) fprintf (stderr, "full #%d\n", block); bh = getblk (dev, block, blocksize); if (!bh) die ("unpack_full_block: getblk failed"); fread (bh->b_data, bh->b_size, 1, stdin); if (who_is_this (bh->b_data, bh->b_size) == THE_SUPER && !what_unpacked) { unsigned long blocks; struct buffer_head * tmp; blocks = get_sb_block_count ((struct reiserfs_super_block *)(bh->b_data)); fprintf (stderr, "There were %lu blocks on the device\n", blocks); what_unpacked = reiserfs_create_bitmap (blocks); /* make file as long as filesystem is */ tmp = getblk (dev, blocks - 1, blocksize); mark_buffer_dirty (tmp); mark_buffer_uptodate (tmp, 0); bwrite (tmp); brelse (tmp); } mark_buffer_uptodate (bh, 1); mark_buffer_dirty (bh); bwrite (bh); /* if (!not_data_block (bh->b_blocknr)) data_blocks_unpacked ++; */ brelse (bh); if (what_unpacked) reiserfs_bitmap_set_bit (what_unpacked, block); /*unpacked ++;*/ if (!(++ full_blocks_unpacked % 50)) fprintf (stderr, "."); } /* just skip bitmaps of unformatted nodes */ static void unpack_unformatted_bitmap (int dev, int blocksize) { __u16 bmap_num; __u32 block_count; int i; char * buf; fread_le16 (&bmap_num); fread_le32 (&block_count); buf = malloc (blocksize); if (!buf) reiserfs_panic ("unpack_unformatted_bitmap: malloc failed: %m"); for (i = 0; i < bmap_num; i ++) { if (fread (buf, blocksize, 1, stdin) != 1) reiserfs_panic ("unpack_unformatted_bitmap: " "could not read bitmap #%d: %m", i); } free (buf); } // read packed reiserfs partition metadata from stdin void unpack_partition (int fd, int jfd) { __u32 magic32, position; __u16 magic16; __u16 blocksize; int dev = fd; fread_le32 (&magic32); if (magic32 != REISERFS_SUPER_MAGIC) die ("unpack_partition: reiserfs magic number (0x%x) not found - %x\n", REISERFS_SUPER_MAGIC, magic32); fread_le16 (&blocksize); if (verbose) fprintf (stderr, "Blocksize %d\n", blocksize); while (!feof (stdin)) { char c[2]; fread (c, 1, 1, stdin); switch (c[0]) { case '.': if (verbose) fprintf (stderr, "\".\" skipped\n"); continue; case '1': fread (c, 1, 1, stdin); /* that was 100%, read in first 0 */ case '2': case '4': case '6': case '8': fread (c, 1, 1, stdin); case '0': fread (c + 1, 1, 1, stdin); /* read % */ if (c[0] != '0' || c[1] != '%') die ("0%% expected\n"); if (verbose) fprintf (stderr, "0%% skipped\n"); continue; } fread (c + 1, 1, 1, stdin); magic16 = le16_to_cpu(*(__u16 *)c); /*fread16 (&magic16);*/ switch (magic16 & 0xff) { case LEAF_START_MAGIC: leaves ++; unpack_leaf (dev, code2func (magic16 >> 8), blocksize); break; case SEPARATED_JOURNAL_START_MAGIC: if (Default_journal) die ("file name for separated journal has to be specified"); dev = jfd; break; case SEPARATED_JOURNAL_END_MAGIC: dev = fd; break; case FULL_BLOCK_START_MAGIC: full ++; unpack_full_block (dev, blocksize); break; case UNFORMATTED_BITMAP_START_MAGIC: fprintf (stderr, "\nBitmap of unformatted - ignored\n"); unpack_unformatted_bitmap (dev, blocksize); break; case END_MAGIC: goto out; default: position = ftell(stdin); if (position == ~0ul) die ("unpack_partition: bad magic found - %x", magic16 & 0xff); else die ("unpack_partition: bad magic found - %x, position %lu", magic16 & 0xff, ftell(stdin)); } } out: fprintf (stderr, "Unpacked %d leaves, %d full blocks\n", leaves, full); /* fclose (block_list);*/ } int main (int argc, char ** argv) { int fd, fdj = -2; int c; char * j_filename; char * filename = ".bitmap"; struct rlimit lim = {0xffffffff, 0xffffffff}; print_banner ("unpack"); /* with this 2.4.0-test9's file_write does not send SIGXFSZ */ if (setrlimit (RLIMIT_FSIZE, &lim)) { fprintf (stderr, "sertlimit failed: %m\n"); } while ((c = getopt (argc, argv, "vb:j:")) != EOF) { switch (c) { case 'v': verbose = 1; break; case 'b': asprintf (&filename, "%s", optarg); break; case 'j': Default_journal = 0; asprintf (&j_filename, "%s", optarg); break; } } if (optind != argc - 1) /* only one non-option argument is permitted */ print_usage_and_exit(); if (is_mounted (argv[optind])) reiserfs_panic ("%s seems mounted, umount it first\n", argv[optind]); fd = open (argv[optind], O_RDWR | O_LARGEFILE); if (fd == -1) { perror ("open failed"); return 0; } if (!Default_journal) { fdj = open (j_filename, O_RDWR | O_LARGEFILE); if (fdj == -1) { perror ("open failed"); return 0; } } unpack_partition (fd, fdj); if (what_unpacked && filename) { FILE * file = open_file(filename, "w+"); reiserfs_bitmap_save (file, what_unpacked); close_file(file); } close (fd); if (!Default_journal) close (fdj); return 0; } reiserfsprogs-3.6.9/debugreiserfs/recover.c0000664000077100007710000002351707705261642014600 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "debugreiserfs.h" #if 0 /* this reads stdin and recover file of given key: */ /* the input has to be in the follwong format: K dirid objectid N name B blocknumber .. then recover_file will read every block, look there specified file and put it into */ void do_recover (reiserfs_filsys_t fs) { char name [100]; char * line = 0; int n = 0; int fd; struct key key = {0, 0, }; struct buffer_head * bh; struct item_head * ih; unsigned long block; char code; loff_t recovered = 0; int i, j; reiserfs_bitmap_t bitmap; int used, not_used; bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs)); reiserfs_fetch_disk_bitmap (bitmap, fs); /* we check how many blocks recoverd items point to are free or used */ used = 0; not_used = 0; fd = 0; while (getline (&line, &n, stdin) != -1) { if (line [0] == '#' || line [0] == '\n') continue; switch (line [0]) { case 'K': /* get a key of file which is to be recovered */ if (sscanf (line, "%c %u %u\n", &code, &key.k_dir_id, &key.k_objectid) != 3) { die ("recover_file: wrong input K format"); } printf ("Recovering file (%u, %u)\n", key.k_dir_id, key.k_objectid); break; case 'N': /* get a file name */ recovered = 0; if (sscanf (line, "%c %s\n", &code, name) != 2) { die ("recover_file: wrong input N format"); } fd = open (name, O_RDWR | O_CREAT | O_EXCL, 0644); if (fd == -1) die ("recover_file: could not create file %s: %s", name,strerror (errno)); printf ("Recovering file %s..\n", name); break; case 'B': if (!fd) die ("recover_file: file name is not specified"); if (sscanf (line, "%c %lu\n", &code, &block) != 2) { die ("recover_file: wrong input B format"); } bh = bread (fs->s_dev, block, fs->s_blocksize); if (!bh) { printf ("reading block %lu failed\n", block); continue; } printf ("working with block %lu..\n", block); ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < node_item_number (bh); i ++, ih ++) { __u32 * indirect; struct buffer_head * tmp_bh; if (!is_indirect_ih (ih) || key.k_dir_id != ih->ih_key.k_dir_id || key.k_objectid != ih->ih_key.k_objectid) continue; indirect = (__u32 *)B_I_PITEM (bh, ih); for (j = 0; j < I_UNFM_NUM (ih); j ++) { block = le32_to_cpu (indirect [j]); if (!block) continue; tmp_bh = bread (fs->s_dev, block, fs->s_blocksize); if (!tmp_bh) { printf ("reading block %Lu failed\n", (loff_t)block * fs->s_blocksize); continue; } if (lseek64 (fd, get_offset (&ih->ih_key) + j * fs->s_blocksize - 1, SEEK_SET) == (loff_t)-1) { printf ("llseek failed to pos %Ld\n", (loff_t)block * fs->s_blocksize); brelse (tmp_bh); continue; } if (reiserfs_bitmap_test_bit (bitmap, block)) used ++; else not_used ++; /*printf ("block of file %Ld gets block %lu\n", (get_offset (&ih->ih_key) - 1) / fs->s_blocksize + j, block);*/ if (write (fd, tmp_bh->b_data, tmp_bh->b_size) != tmp_bh->b_size) { printf ("write failed to pos %Ld\n", (loff_t)block * fs->s_blocksize); brelse (tmp_bh); continue; } recovered += fs->s_blocksize; brelse (tmp_bh); } } brelse (bh); break; } } printf ("recover_file: %Ld bytes recovered of file %s, key %u %u, %d blocks are free and %d are used\n", recovered, name, key.k_dir_id, key.k_objectid, not_used, used); } #endif /* read a file containing map of one or more files and either recover them or just print info */ /* static void read_map (FILE * fp) { int i; __u32 v32; char * buf; __u32 ids [4]; int do_recover = 0; buf = 0; while (1) { if (fread (&v32, sizeof (v32), 1, fp) != 1) break; if (v32 != MAP_MAGIC) reiserfs_panic ("read_map: no magic found"); // device name length and name itself fread (&v32, sizeof (v32), 1, fp); buf = realloc (buf, v32); if (!buf) reiserfs_panic ("realloc failed"); fread (buf, v32, 1, fp); reiserfs_warning (stdout, "\"%s\": ", buf); // file name length and name itself fread (&v32, sizeof (v32), 1, fp); buf = realloc (buf, v32); if (!buf) reiserfs_panic ("realloc failed"); fread (buf, v32, 1, fp); // read directory key and poined object key fread (ids, sizeof (ids), 1, fp); reiserfs_warning (stdout, "[%K]:\"%s\"-->[%K]\n", &ids[0], buf, &ids[2]); //do_recover = user_confirmed (stdout, "recover? (Y):", "Y\n"); //if (do_recover) // reiserfs_warning (stderr, "recovering not ready\n"); // how many data blocks are there fread (&v32, sizeof (v32), 1, fp); if (v32) { buf = realloc (buf, v32 * 4); if (!buf) reiserfs_panic ("realloc failed (%u)", v32); // read list of data block numbers fread (buf, 4, v32, fp); if (!do_recover) { for (i = 0; i < v32; i ++) reiserfs_warning (stdout, "%d ", ((__u32 *)buf)[i]); reiserfs_warning (stdout, "\n"); } } // main tail length fread (&v32, sizeof (v32), 1, fp); if (v32) { // there is tail buf = realloc (buf, v32); if (!buf) reiserfs_panic ("realloc failed"); fread (buf, v32, 1, fp); if (!do_recover) reiserfs_warning (stdout, "%d bytes long tail\n", v32); } else { if (!do_recover) reiserfs_warning (stdout, "No tail\n"); } if (fread (&v32, sizeof (v32), 1, fp) != 1) break; if (v32 != MAP_END_MAGIC) reiserfs_panic ("read_map: no magic found"); } free (buf); } void do_recover (reiserfs_filsys_t * fs) { FILE * fp; if (map_file (fs)) { fp = fopen (map_file (fs), "r"); if (fp == 0) { reiserfs_warning (stderr, "do_recover: fopen failed: %m"); return; } } else { reiserfs_warning (stderr, "Reading file map from stdin..\n"); fflush (stderr); fp = stdin; } read_map (fp); if (fp != stdin) fclose (fp); } */ #include static long int get_answer(long int max) { char *answer, *tmp; size_t n = 0; long int result = 0; do { printf("Which should be left?: "); getline (&answer, &n, stdin); result = strtol (answer, &tmp, 0); if ((errno != ERANGE) && (result < max) && (result >= 0) && (answer != tmp)) break; } while (1); return result; } static void recover_items(FILE *fp, reiserfs_filsys_t * fs, FILE *target_file) { struct buffer_head *bh, *bh_pointed; struct item_head *ih; struct saved_item item, *cur; int size = sizeof(struct saved_item) - sizeof(struct saved_item *); struct saved_item *map = NULL; __u32 map_size = 0; int start = 0; unsigned int i, j; __u64 offset = 0, length; long int result = 0; unsigned long unfm_ptr; while (fread(&item, size, 1, fp) == 1) { map_size += sizeof(struct saved_item); map = realloc(map, map_size); memcpy((void *)map + map_size - sizeof(struct saved_item), &item, size); } for (i = 1, cur = map + 1; i <= map_size / sizeof(struct saved_item); i++, cur++) { bh = bread (fs->fs_dev, (cur - 1)->si_block, fs->fs_blocksize); if (!bh) { reiserfs_warning (fp, "bread failed\n"); continue; } if (i == map_size / sizeof(struct saved_item)) { if (start != -1) { reiserfs_print_item(stdout, bh, B_N_PITEM_HEAD (bh, (cur - 1)->si_item_num)); result = get_answer(i - start) + start; } else { result = i - 1; } start = -1; } else if (is_direntry_ih(&(cur - 1)->si_ih)) { brelse(bh); continue; } else { length = get_bytes_number(&(cur - 1)->si_ih, fs->fs_blocksize); if (offset < get_offset(&(cur - 1)->si_ih.ih_key) + get_bytes_number(&(cur - 1)->si_ih, fs->fs_blocksize)) offset = get_offset(&(cur - 1)->si_ih.ih_key) + (length ? length - 1 : 0); if (offset >= get_offset(&cur->si_ih.ih_key)) { /* Problem interval */ if (start == -1) start = i - 1; printf("Problem item %d:\n", i - start - 1); reiserfs_print_item(stdout, bh, B_N_PITEM_HEAD (bh, (cur - 1)->si_item_num)); } else if (start != -1) { /* problem interval finished */ printf("Problem item %d:\n", i - start - 1); reiserfs_print_item(stdout, bh, B_N_PITEM_HEAD (bh, (cur - 1)->si_item_num)); result = get_answer((long int)i - start) + start; start = -1; } else { result = i - 1; } } brelse(bh); if (start != -1) continue; printf("write %ld\n", result); bh = bread (fs->fs_dev, (map + result)->si_block, fs->fs_blocksize); if (!bh) { reiserfs_warning (fp, "bread failed\n"); continue; } fseek(target_file, get_offset(&(map + result)->si_ih.ih_key) - 1, SEEK_SET); ih = B_N_PITEM_HEAD (bh, (map + result)->si_item_num); if (is_direct_ih(ih)) { fwrite(B_I_PITEM(bh, ih), (map + result)->si_ih.ih2_item_len, 1, target_file); } else if (is_indirect_ih(ih)) { for (j = 0; j < I_UNFM_NUM (ih); j ++) { unfm_ptr = le32_to_cpu (((__u32 *)B_I_PITEM(bh, ih))[j]); if (!unfm_ptr) { fseek(target_file, fs->fs_blocksize, SEEK_CUR); continue; } bh_pointed = bread (fs->fs_dev, unfm_ptr, fs->fs_blocksize); if (!bh_pointed) { reiserfs_warning (fp, "bread failed\n"); continue; } fwrite(bh_pointed->b_data, fs->fs_blocksize, 1, target_file); brelse(bh_pointed); } } brelse(bh); } free(map); } void do_recover(reiserfs_filsys_t * fs) { FILE *fp, *recovery; if (map_file (fs)) { fp = fopen (map_file (fs), "r"); if (fp == 0) { reiserfs_warning (stderr, "fopen failed: %m\n"); return; } } else { reiserfs_warning (stderr, "Reading file map from stdin..\n"); fflush (stderr); fp = stdin; } if (!(recovery = fopen(recovery_file(fs), "w+"))) { reiserfs_warning (stderr, "fopen failed: %m\n"); return; } recover_items(fp, fs, recovery); if (fp != stdin) fclose (fp); fclose(recovery); } reiserfsprogs-3.6.9/debugreiserfs/Makefile.am0000664000077100007710000000045107705261642015013 sbin_PROGRAMS = debugreiserfs unpack debugreiserfs_SOURCES = debugreiserfs.c pack.c stat.c corruption.c scan.c recover.c unpack_SOURCES = unpack.c pack.c debugreiserfs.h man_MANS = debugreiserfs.8 EXTRA_DIST = $(man_MANS) LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a reiserfsprogs-3.6.9/debugreiserfs/Makefile.in0000644000077100007710000003466007705315225015030 # Makefile.in generated by automake 1.7.2 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__quote = @am__quote@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ sbin_PROGRAMS = debugreiserfs unpack debugreiserfs_SOURCES = debugreiserfs.c pack.c stat.c corruption.c scan.c recover.c unpack_SOURCES = unpack.c pack.c debugreiserfs.h man_MANS = debugreiserfs.8 EXTRA_DIST = $(man_MANS) LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a subdir = debugreiserfs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = sbin_PROGRAMS = debugreiserfs$(EXEEXT) unpack$(EXEEXT) PROGRAMS = $(sbin_PROGRAMS) am_debugreiserfs_OBJECTS = debugreiserfs.$(OBJEXT) pack.$(OBJEXT) \ stat.$(OBJEXT) corruption.$(OBJEXT) scan.$(OBJEXT) \ recover.$(OBJEXT) debugreiserfs_OBJECTS = $(am_debugreiserfs_OBJECTS) debugreiserfs_LDADD = $(LDADD) debugreiserfs_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \ $(top_srcdir)/reiserfscore/libcore.a debugreiserfs_LDFLAGS = am_unpack_OBJECTS = unpack.$(OBJEXT) pack.$(OBJEXT) unpack_OBJECTS = $(am_unpack_OBJECTS) unpack_LDADD = $(LDADD) unpack_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \ $(top_srcdir)/reiserfscore/libcore.a unpack_LDFLAGS = DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/corruption.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/debugreiserfs.Po ./$(DEPDIR)/pack.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/recover.Po ./$(DEPDIR)/scan.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/stat.Po ./$(DEPDIR)/unpack.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(debugreiserfs_SOURCES) $(unpack_SOURCES) NROFF = nroff MANS = $(man_MANS) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(debugreiserfs_SOURCES) $(unpack_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu debugreiserfs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(sbindir) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f || exit 1; \ else :; fi; \ done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ rm -f $(DESTDIR)$(sbindir)/$$f; \ done clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) debugreiserfs$(EXEEXT): $(debugreiserfs_OBJECTS) $(debugreiserfs_DEPENDENCIES) @rm -f debugreiserfs$(EXEEXT) $(LINK) $(debugreiserfs_LDFLAGS) $(debugreiserfs_OBJECTS) $(debugreiserfs_LDADD) $(LIBS) unpack$(EXEEXT): $(unpack_OBJECTS) $(unpack_DEPENDENCIES) @rm -f unpack$(EXEEXT) $(LINK) $(unpack_LDFLAGS) $(unpack_OBJECTS) $(unpack_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/corruption.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debugreiserfs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recover.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unpack.Po@am__quote@ distclean-depend: -rm -rf ./$(DEPDIR) .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: man8dir = $(mandir)/man8 install-man8: $(man8_MANS) $(man_MANS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(man8dir) @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.8*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ *) ext='8' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ done uninstall-man8: @$(NORMAL_UNINSTALL) @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.8*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ *) ext='8' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ rm -f $(DESTDIR)$(man8dir)/$$inst; \ done ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) installdirs: $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(man8dir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-man install-exec-am: install-sbinPROGRAMS install-info: install-info-am install-man: install-man8 installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am uninstall-man uninstall-sbinPROGRAMS uninstall-man: uninstall-man8 .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-sbinPROGRAMS ctags distclean distclean-compile \ distclean-depend distclean-generic distclean-tags distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-man8 install-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-info-am uninstall-man \ uninstall-man8 uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: reiserfsprogs-3.6.9/debugreiserfs/pack.c0000664000077100007710000004452307705261642014051 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "debugreiserfs.h" /* counters for each kind of blocks */ int packed, packed_leaves, full_blocks, having_ih_array, /* blocks with broken block head */ bad_leaves, /* failed to compress */ internals, descs, others; reiserfs_bitmap_t * what_to_pack; /* these are to calculate compression */ unsigned long sent_bytes; /* how many bytes sent to stdout */ unsigned long had_to_be_sent; /* how many bytes were to be sent */ inline void set_pi_type( struct packed_item *pi, __u32 val ) { set_bit_field_XX (32, pi, val, 0, 2); } inline __u32 get_pi_type( const struct packed_item *pi ) { get_bit_field_XX (32, pi, 0, 2); } inline void set_pi_mask( struct packed_item *pi, __u32 val ) { set_bit_field_XX (32, pi, val, 2, 18); } __u32 get_pi_mask( const struct packed_item *pi ) { get_bit_field_XX (32, pi, 2, 18); } inline void set_pi_item_len( struct packed_item *pi, __u32 val ) { set_bit_field_XX (32, pi, val, 20, 12); } inline __u32 get_pi_item_len( const struct packed_item *pi ) { get_bit_field_XX (32, pi, 20, 12); } static void pack_ih (struct packed_item * pi, struct item_head * ih) { __u32 v32; __u16 v16; /* send packed item head first */ fwrite (pi, sizeof (*pi), 1, stdout); sent_bytes += sizeof (*pi); /* sen key components which are to be sent */ if (get_pi_mask(pi) & DIR_ID) { v32 = get_key_dirid (&ih->ih_key); fwrite_le32 (&v32); } if (get_pi_mask(pi) & OBJECT_ID) { v32 = get_key_objectid (&ih->ih_key); fwrite_le32 (&v32); } if (get_pi_mask(pi) & OFFSET_BITS_64) { __u64 offset; offset = get_offset (&ih->ih_key); fwrite_le64 (&offset); } if (get_pi_mask(pi) & OFFSET_BITS_32) { __u32 offset; offset = get_offset (&ih->ih_key); fwrite_le32 (&offset); } if (get_pi_mask(pi) & IH_FREE_SPACE) { v16 = get_ih_entry_count (ih); fwrite_le16 (&v16); } if (get_pi_mask(pi) & IH_FORMAT) { /* fixme */ fwrite16 (&ih->ih_format); } } static void pack_direct (struct packed_item * pi, struct buffer_head * bh, struct item_head * ih) { if (get_ih_free_space (ih) != 0xffff) /* ih_free_space has unexpected value */ set_pi_mask (pi, get_pi_mask (pi) | IH_FREE_SPACE); if (get_pi_mask(pi) & SAFE_LINK) set_key_dirid(&ih->ih_key, le32_to_cpu(*(__u32 *)B_I_PITEM (bh, ih)) ); /* send key components which are to be sent */ pack_ih (pi, ih); } /* if there is at least one extent longer than 2 - it is worth packing */ static int should_pack_indirect (__u32 * ind_item, int unfm_num) { int i, len; for (i = 1, len = 1; i < unfm_num; i ++) { if ((ind_item [i] == 0 && ind_item [i - 1] == 0) || /* hole continues */ le32_to_cpu (ind_item [i]) == le32_to_cpu (ind_item [i - 1]) + 1) { /* subsequent blocks */ len ++; if (len > 2) return 1; } else { /* sequence of blocks or hole broke */ len = 1; } } return 0; } /* indirect item can be either packed using "extents" (when it is worth doing) or be stored as is. Size of item in packed form is not stored. Unpacking will stop when full item length is reached */ static void pack_indirect (struct packed_item * pi, struct buffer_head * bh, struct item_head * ih) { unsigned int i; __u32 * ind_item; __u16 len; if (get_ih_entry_count (ih)) set_pi_mask (pi, get_pi_mask (pi) | IH_FREE_SPACE); ind_item = (__u32 *)B_I_PITEM (bh, ih); if (!should_pack_indirect (ind_item, I_UNFM_NUM (ih))) set_pi_mask (pi, get_pi_mask (pi) | WHOLE_INDIRECT); if (get_pi_mask(pi) & SAFE_LINK) set_key_dirid(&ih->ih_key, le32_to_cpu(*ind_item) ); pack_ih (pi, ih); if (get_pi_mask(pi) & SAFE_LINK) return; if (get_pi_mask(pi) & WHOLE_INDIRECT) { fwrite (ind_item, get_ih_item_len (ih), 1, stdout); sent_bytes += get_ih_item_len (ih); return; } fwrite32 (&ind_item [0]); for (i = 1, len = 1; i < I_UNFM_NUM (ih); i ++) { if ((ind_item [i] == 0 && ind_item [i - 1] == 0) || /* hole continues */ ind_item [i] == ind_item[ i - 1] + 1) { /* subsequent blocks */ len ++; } else { fwrite_le16 (&len); fwrite32 (&ind_item[i]); len = 1; } } fwrite_le16 (&len); return; } /* directory item is packed: entry count - 16 bits for each entry mask (8 bits) - it shows whether there are any of (deh_dir_id, gen counter, deh_state) entry length 16 bits entry itself deh_objectid - 32 bits maybe deh_dir_id (32 bits) maybe gencounter (16) maybe deh_state (16) */ static void pack_direntry (reiserfs_filsys_t * fs, struct packed_item * pi, struct buffer_head * bh, struct item_head * ih) { int i; struct reiserfs_de_head * deh; struct packed_dir_entry pe; __u16 entry_count, gen_counter; set_pi_mask (pi, get_pi_mask (pi) | IH_ENTRY_COUNT); /* send item_head components which are to be sent */ pack_ih (pi, ih); /* entry count is sent unconditionally */ entry_count = get_ih_entry_count (ih); deh = B_I_DEH (bh, ih); for (i = 0; i < entry_count; i ++, deh ++) { pe.entrylen = entry_length (ih, deh, i); pe.mask = 0; if (get_deh_dirid (deh) != get_key_objectid (&ih->ih_key)) /* entry points to name of another directory, store deh_dir_id */ pe.mask |= HAS_DIR_ID; gen_counter = GET_GENERATION_NUMBER (get_deh_offset (deh)); if (gen_counter != 0) /* store generation counter if it is != 0 */ pe.mask |= HAS_GEN_COUNTER; if (get_deh_state (deh) != 4) /* something unusual in deh_state. Store it */ pe.mask |= HAS_STATE; fwrite8 (&pe.mask); fwrite_le16 (&pe.entrylen); fwrite (name_in_entry (deh, i), pe.entrylen, 1, stdout); sent_bytes += pe.entrylen; fwrite32 (&(deh->deh2_objectid)); if (pe.mask & HAS_DIR_ID) fwrite32 (&deh->deh2_dir_id); if (pe.mask & HAS_GEN_COUNTER) fwrite_le16 (&gen_counter); if (pe.mask & HAS_STATE) fwrite16 (&deh->deh2_state); } } static void pack_stat_data (struct packed_item * pi, struct buffer_head * bh, struct item_head * ih) { if (get_ih_free_space (ih) != 0xffff) /* ih_free_space has unexpected value */ set_pi_mask (pi, get_pi_mask (pi) | IH_FREE_SPACE); if (stat_data_v1 (ih)) { /* for old stat data: we take mode - 16 bits nlink - 16 bits size - 32 bits blocks/rdev - 32 bits maybe first_direct byte 32 bits */ struct stat_data_v1 * sd_v1; sd_v1 = (struct stat_data_v1 *)B_I_PITEM (bh, ih); if (sd_v1->sd_first_direct_byte != 0xffffffff) /* ok if -1 */ set_pi_mask (pi, get_pi_mask (pi) | WITH_SD_FIRST_DIRECT_BYTE); pack_ih (pi, ih); fwrite16 (&sd_v1->sd_mode); fwrite16 (&sd_v1->sd_nlink); fwrite32 (&sd_v1->sd_size); fwrite32 (&sd_v1->u.sd_blocks); if (get_pi_mask(pi) & WITH_SD_FIRST_DIRECT_BYTE) fwrite32 (&sd_v1->sd_first_direct_byte); } else { /* for new stat data mode - 16 bits nlink in either 16 or 32 bits size in either 32 or 64 bits blocks - 32 bits */ struct stat_data * sd; /* these will maintain disk-order values */ __u16 nlink16; __u32 nlink32, size32; __u64 size64; sd = (struct stat_data *)B_I_PITEM (bh, ih); if (sd_v2_nlink (sd) > 0xffff) { set_pi_mask (pi, get_pi_mask (pi) | NLINK_BITS_32); nlink32 = sd->sd_nlink; } else { /* This is required to deal with big endian systems */ nlink16 = cpu_to_le16 ((__u16)sd_v2_nlink (sd)); } if (sd_v2_size (sd) > 0xffffffff) { set_pi_mask (pi, get_pi_mask (pi) | SIZE_BITS_64); size64 = sd->sd_size; } else { /* This is required to deal with big endian systems */ size32 = cpu_to_le32 ((__u32)sd_v2_size (sd)); } pack_ih (pi, ih); fwrite16 (&sd->sd_mode); if (get_pi_mask (pi) & NLINK_BITS_32) { fwrite32 (&nlink32); } else { fwrite16 (&nlink16); } if (get_pi_mask (pi) & SIZE_BITS_64) { fwrite64 (&size64); } else { fwrite32 (&size32); } fwrite32 (&sd->sd_blocks); } } static void pack_full_block (reiserfs_filsys_t * fs, struct buffer_head * bh) { __u16 magic; __u32 block; magic = FULL_BLOCK_START_MAGIC; fwrite_le16 (&magic); block = bh->b_blocknr; fwrite_le32 (&block); fwrite (bh->b_data, fs->fs_blocksize, 1, stdout); sent_bytes += fs->fs_blocksize; had_to_be_sent += fs->fs_blocksize; full_blocks ++; } #if 0 /* unformatted node pointer is considered bad when it points either to blocks of journal, bitmap blocks, super block or is transparently out of range of disk block numbers */ static int check_unfm_ptr (reiserfs_filsys_t * fs, __u32 block) { if (block >= SB_BLOCK_COUNT (fs)) return 1; if (not_data_block (fs, block)) return 1; return 0; } #endif /* we only pack leaves which do not have any corruptions */ static int can_pack_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh) { int i; struct item_head * ih; ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) { if (is_it_bad_item (fs, ih, B_I_PITEM (bh, ih), 0/*check_unfm_ptr*/, 1/*bad dir*/)) return 0; } return 1; } /* pack leaf only if all its items are correct: keys are correct, direntries are hashed properly and hash function is defined, indirect items are correct, stat data ?, */ static void pack_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh) { int i; struct item_head * ih; struct packed_item pi; __u16 v16; if (!can_pack_leaf (fs, bh)) { /* something looks suspicious in this leaf - pack whole block */ bad_leaves ++; pack_full_block (fs, bh); return; } /* start magic in low 8 bits, hash code in high 8 bits */ v16 = (LEAF_START_MAGIC | (func2code (fs->fs_hash_function) << 8)); fwrite_le16 (&v16); /* block number */ fwrite_le32 (&bh->b_blocknr); /* item number */ v16 = get_blkh_nr_items (B_BLK_HEAD (bh)); fwrite_le16 (&v16); ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < v16; i ++, ih ++) { #if 0 v32 = ITEM_START_MAGIC; fwrite32 (&v32); #endif set_pi_mask (&pi, 0); set_pi_item_len (&pi, get_ih_item_len (ih)); set_pi_type (&pi, get_type (&ih->ih_key)); // format if (get_ih_key_format (ih) == KEY_FORMAT_2) set_pi_mask( &pi, get_pi_mask(&pi) | NEW_FORMAT ); // k_dir_id if (!i || (i && get_key_dirid (&ih->ih_key) != get_key_dirid (&(ih - 1)->ih_key))) { /* if item is first in the leaf or if previous item has different k_dir_id - store it */ set_pi_mask (&pi, get_pi_mask (&pi) | DIR_ID); } // k_object_id if (!i || (i && get_key_objectid (&ih->ih_key) != get_key_objectid (&(ih - 1)->ih_key))) { /* if item is first in the leaf or if previous item has different k_objectid - store it */ set_pi_mask (&pi, get_pi_mask (&pi) | OBJECT_ID); } /* store offset if it is != 0 in 32 or 64 bits */ if (get_offset (&ih->ih_key)) { int send_offset = 1; if ((get_pi_mask (&pi) & DIR_ID) == 0 && (get_pi_mask (&pi) & OBJECT_ID) == 0) { /* previous item is of the same object, so try to avoid sending k_offset */ if ((is_stat_data_ih (ih - 1) && get_offset (&ih->ih_key) == 1) || (is_indirect_ih (ih - 1) && is_direct_ih (ih) && get_offset (&(ih - 1)->ih_key) + get_bytes_number (ih - 1, fs->fs_blocksize) == get_offset (&ih->ih_key))) /* unpack can calculate offset itself */ send_offset = 0; } if (send_offset) { if (get_offset (&ih->ih_key) > 0xffffffffULL) set_pi_mask (&pi, get_pi_mask (&pi) | OFFSET_BITS_64); else set_pi_mask (&pi, get_pi_mask (&pi) | OFFSET_BITS_32); } } /* ih key format is correct, check fsck_need field */ if (get_ih_flags (ih)) set_pi_mask (&pi, get_pi_mask (&pi) | IH_FORMAT); if ((get_key_dirid (&ih->ih_key) == (__u32)-1) && (get_ih_item_len (ih) == 4)) set_pi_mask (&pi, get_pi_mask (&pi) | SAFE_LINK); if (is_direct_ih (ih)) { pack_direct (&pi, bh, ih); } else if (is_indirect_ih (ih)) pack_indirect (&pi, bh, ih); else if (is_direntry_ih (ih)) pack_direntry (fs, &pi, bh, ih); else if (is_stat_data_ih (ih)) pack_stat_data (&pi, bh, ih); else die ("pack_leaf: unknown item found"); #if 0 v32 = ITEM_END_MAGIC; fwrite32 (&v32); #endif } v16 = LEAF_END_MAGIC; fwrite_le16 (&v16); had_to_be_sent += fs->fs_blocksize; packed_leaves ++; return; } static int can_pack_internal (reiserfs_filsys_t * fs, struct buffer_head * bh) { return 0; } /* pack internal node as a full block */ static void pack_internal (reiserfs_filsys_t * fs, struct buffer_head * bh) { internals ++; if (!can_pack_internal (fs, bh)) { pack_full_block (fs, bh); return; } reiserfs_panic ("pack_internal: packing code is not ready"); } /* packed blocks are marked free in the bitmap*/ static void send_block (reiserfs_filsys_t * fs, struct buffer_head * bh, int send_unknown) { int type; packed ++; type = who_is_this (bh->b_data, bh->b_size); switch (type) { case THE_LEAF: pack_leaf (fs, bh); break; case HAS_IH_ARRAY: having_ih_array ++; // fprintf (stderr, "BROKEN BLOCK HEAD %lu\n", bh->b_blocknr); pack_full_block (fs, bh); break; case THE_INTERNAL: pack_internal (fs, bh); break; default: if (send_unknown) pack_full_block (fs, bh); else packed --; break; } /* do not send one block twice */ reiserfs_bitmap_clear_bit (what_to_pack, bh->b_blocknr); } /* super block, journal, bitmaps */ static void pack_frozen_data (reiserfs_filsys_t * fs) { struct buffer_head * bh; unsigned long block; __u16 magic16; int sent_journal_start_magic = 0; unsigned int i; if (is_reiserfs_jr_magic_string(fs->fs_ondisk_sb) && get_jp_journal_dev(sb_jp(fs->fs_ondisk_sb)) && !journal_device_name(fs)) { if (!user_confirmed (stderr, "\n File system has non-standard journal " "that hasn't been specified.\n" "Continue packing without journal? [N/Yes] (note need to type Yes):", "Yes\n")) exit (0); } /* super block */ reiserfs_warning (stderr, "super block..");fflush (stderr); send_block (fs, fs->fs_super_bh, 1/*send block even if its format is not determined */); reiserfs_warning (stderr, "ok\nbitmaps..(%d).. ", get_sb_bmap_nr (fs->fs_ondisk_sb)); fflush (stderr); /* bitmaps */ block = fs->fs_super_bh->b_blocknr + 1; for (i = 0; i < get_sb_bmap_nr (fs->fs_ondisk_sb); i ++) { bh = bread (fs->fs_dev, block, fs->fs_blocksize); if (!bh) { fprintf (stderr, "pack_frozen_data: bread failed: %lu\n", block); continue; } send_block (fs, bh, 1); if (spread_bitmaps (fs)) block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8); else block ++; brelse (bh); } /* journal */ if (get_jp_journal_dev (sb_jp (fs->fs_ondisk_sb))) { /* non-standard journal is on a separate device */ if (journal_device_name (fs) && !reiserfs_journal_opened (fs)) die ("Specified journal is not available. Specify it correctly or " "don't specify at all"); else if (!journal_device_name(fs)) /* non-standard journal was not specified (that confirmed by user) - skipped packing journal */ return; else { magic16 = SEPARATED_JOURNAL_START_MAGIC; fwrite_le16 (&magic16); sent_journal_start_magic = 1; } } block = get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb)); reiserfs_warning (stderr, "ok\njournal (from %lu to %lu)..", block, block + get_jp_journal_size (sb_jp (fs->fs_ondisk_sb))); fflush (stderr); for (i = 0; i <= get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)); i ++) { bh = bread (fs->fs_journal_dev, block + i, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "could not read %lu, skipped\n", i); continue; } send_block (fs, bh, 1); brelse (bh); } if (sent_journal_start_magic) { magic16 = SEPARATED_JOURNAL_END_MAGIC; fwrite_le16 (&magic16); } reiserfs_warning (stderr, "ok\n");fflush (stderr); reiserfs_warning (stderr, "Super block, bitmaps, journal - %d blocks - done, %d blocks left\n", packed, reiserfs_bitmap_ones (what_to_pack)); } /* pack all "not data blocks" and correct leaf */ void pack_partition (reiserfs_filsys_t * fs) { struct buffer_head * bh; __u32 magic32; __u16 blocksize; __u16 magic16; unsigned long done = 0, total; unsigned int i; magic32 = REISERFS_SUPER_MAGIC; fwrite_le32 (&magic32); blocksize = fs->fs_blocksize; fwrite_le16 (&blocksize); /* will get information about what is to be packed. Bits corresponding to packed blocks will be cleared */ what_to_pack = input_bitmap(fs); /* super block, journal, bitmaps */ pack_frozen_data (fs); /* what's left */ total = reiserfs_bitmap_ones (what_to_pack); for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { if (!reiserfs_bitmap_test_bit (what_to_pack, i)) continue; print_how_far (stderr, &done, total, 1, be_quiet (fs)); bh = bread (fs->fs_dev, i, blocksize); if (!bh) { reiserfs_warning (stderr, "could not read block %lu\n", i); continue; } send_block (fs, bh, 0/*do not send block of not determined format */); brelse (bh); } magic16 = END_MAGIC; fwrite_le16 (&magic16); fprintf (stderr, "\nPacked %d blocks:\n" "\tcompessed %d\n" "\tfull blocks %d\n" "\t\tleaves with broken block head %d\n" "\t\tcorrupted leaves %d\n" "\t\tinternals %d\n" "\t\tdescriptors %d\n", packed, packed_leaves, full_blocks, having_ih_array, bad_leaves, internals, descs); fprintf (stderr, "data packed with ratio %.2f\n", (double)sent_bytes / had_to_be_sent); } void pack_one_block (reiserfs_filsys_t * fs, unsigned long block) { __u32 magic32; __u16 magic16; struct buffer_head * bh; // reiserfs magic magic32 = REISERFS_SUPER_MAGIC; fwrite_le32 (&magic32); // blocksize fwrite_le16 (&fs->fs_blocksize); bh = bread (fs->fs_dev, block, fs->fs_blocksize); if (!bh) return; if (who_is_this (bh->b_data, bh->b_size) == THE_LEAF) pack_leaf (fs, bh); else pack_full_block (fs, bh); brelse (bh); // end magic magic16 = END_MAGIC; fwrite_le16 (&magic16); fprintf (stderr, "Done\n"); } reiserfsprogs-3.6.9/debugreiserfs/scan.c0000664000077100007710000006126607705261642014062 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "debugreiserfs.h" #include #include #include #define obstack_chunk_alloc malloc #define obstack_chunk_free free /* -n pattern scans the area (on-disk bitmap, or all the device or extern bitmap) and looks for every name matching the pattern. All those names get stored in 'name_store' and are indexed by name (name_index) and by a key they point to (key_index) */ struct obstack name_store; struct obstack item_store; int saved_names; int saved_items; int skipped_names; void * key_index; void * name_index; regex_t pattern; struct saved_name { unsigned int dirid; /* pointed object */ unsigned int objectid; struct saved_name * first_name; /* pointer to name which points to the same object and contains list of file items */ unsigned int parent_dirid; /* parent directory */ unsigned int parent_objectid; unsigned long block; /* where we saw the name for the first time */ unsigned short count; /* how many times the name appeared */ void * items; struct saved_name * name_next; /* list of identical names */ unsigned short name_len; char name[1]; }; /* attach item to every name in the list */ static void store_item (struct saved_name * name, struct buffer_head * bh, struct item_head * ih) { struct saved_item * new; void * vp; struct saved_item * item_in; new = obstack_alloc (&item_store, sizeof (struct saved_item)); new->si_ih = *ih; new->si_block = bh->b_blocknr; new->si_item_num = ih - B_N_PITEM_HEAD (bh, 0); new->si_next = 0; vp = tfind (new, &name->items, comp_keys); if (vp) { item_in = *(void **)vp; /* add item to the end of list of items having this key */ while (1) { if (!item_in->si_next) { item_in->si_next = new; break; } item_in = item_in->si_next; } } else tsearch (new, &name->items, comp_keys); saved_items ++; } static int comp_names (const void * p1, const void * p2) { struct saved_name * name1, * name2; name1 = (struct saved_name *)p1; name2 = (struct saved_name *)p2; return strcmp (name1->name, name2->name); } static int comp_pointed (const void * p1, const void * p2) { struct saved_name * name1, * name2; name1 = (struct saved_name *)p1; name2 = (struct saved_name *)p2; return comp_short_keys (&name1->dirid, &name2->dirid); } /* we consider name found only if it points to the same object and from the same directory */ static int name_found (struct saved_name * name, struct saved_name ** name_in) { void * vp; struct saved_name * cur; vp = tfind (name, &name_index, comp_names); if (!vp) { *name_in = 0; return 0; } *name_in = *(void **)vp; /* check every name in the list */ cur = *name_in; while (cur) { if (!not_of_one_file (&name->dirid, &cur->dirid) && !not_of_one_file (&name->parent_dirid, &cur->parent_dirid)) { cur->count ++; return 1; } cur = cur->name_next; } return 0; } /* add key name is pointing to to the index of keys. If there was already name pointing to this key - add pointer to that name */ static void add_key (struct saved_name * name) { void * vp; vp = tfind (name, &key_index, comp_pointed); if (vp) { /* */ name->first_name = *(void **)vp; } else { tsearch (name, &key_index, comp_pointed); } } static void add_name (struct saved_name * name, struct saved_name * name_in) { if (name_in) { /* add name to the end of list of identical names */ while (1) { if (!name_in->name_next) { name_in->name_next = name; break; } name_in = name_in->name_next; } } else { /* add name into name index */ tsearch (name, &name_index, comp_names); } } /* take each name matching to a given pattern, */ static void scan_for_name (struct buffer_head * bh) { int i, j, i_num; struct item_head * ih; struct reiserfs_de_head * deh; int namelen; char * name; struct saved_name * new, *name_in; char ch; int retval; int min_entry_size = 1; int ih_entry_count = 0; ih = B_N_PITEM_HEAD (bh, 0); i_num = leaf_item_number_estimate(bh); for (i = 0; i < i_num; i ++, ih ++) { if (!is_direntry_ih (ih)) continue; if (is_it_bad_item (fs, ih, B_I_PITEM (bh, ih), 0, 1)) continue; deh = B_I_DEH (bh, ih); if ( (get_ih_entry_count (ih) > (get_ih_item_len(ih) / (DEH_SIZE + min_entry_size))) || (get_ih_entry_count (ih) == 0)) ih_entry_count = get_ih_item_len(ih) / (DEH_SIZE + min_entry_size); else ih_entry_count = get_ih_entry_count (ih); for (j = 0; j < ih_entry_count; j ++, deh ++) { name = name_in_entry (deh, j); namelen = name_in_entry_length (ih, deh, j); ch = name[namelen]; name[namelen] = 0; retval = regexec (&pattern, name, 0, NULL, 0); name[namelen] = ch; if (retval != 0) continue; /* name matching given pattern found */ new = obstack_alloc (&name_store, sizeof (struct saved_name) + namelen); /* pointed object */ new->dirid = get_deh_dirid (deh); new->objectid = get_deh_objectid (deh); /* pointer to first name which points the same key */ new->first_name = 0; /* where this name is from */ new->parent_dirid = get_key_dirid (&ih->ih_key); new->parent_objectid = get_key_objectid (&ih->ih_key); new->block = bh->b_blocknr; new->count = 1; new->items = 0; /* name */ new->name_len = namelen; memcpy (new->name, name, namelen); new->name [namelen] = 0; new->name_next = 0; /* reiserfs_warning (stdout, "\n(%K):%s-->(%K) - ", &new->parent_dirid, new->name, &new->dirid); */ if (name_found (new, &name_in)) { /* there was already exactly this name */ obstack_free (&name_store, new); continue; } saved_names ++; add_name (new, name_in); add_key (new); } /* for each entry */ } /* for each item */ return; } /* take every item, look for its key in the key index, if it is found - store item in the sorted list of items of a file */ static void scan_items (struct buffer_head * bh) { int i, i_num; struct item_head * ih; struct saved_name * name_in_store; void * res; ih = B_N_PITEM_HEAD (bh, 0); i_num = leaf_item_number_estimate(bh); for (i = 0; i < i_num; i ++, ih ++) { res = tfind (&ih->ih_key, &key_index, comp_pointed); if (!res) /* there were no names pointing to this key */ continue; /* name pointing to this key found */ name_in_store = *(struct saved_name **)res; store_item (name_in_store, bh, ih); } } /* FIXME: does not work for long files */ struct version { int flag; /* direct or indirect */ int len; __u32 from; int count; void * data; }; struct tail { __u32 offset; int len; char * data; }; struct file_map { int head_len; /* number of unfm pointers */ void * head; int tail_nr; /* number of tails found */ struct tail * tails; int version_nr; void * versions; /* list of range versions */ }; struct file_map map; static int have_to_append (struct item_head * ih) { loff_t off = get_offset (&ih->ih_key); if (is_indirect_ih (ih)) { if (map.head_len * fs->fs_blocksize + 1 <= off) return 1; return 0; } else if (is_direct_ih (ih)) { int i; __u32 tail_start; tail_start = (off & ~(fs->fs_blocksize - 1)) + 1; // find correct tail first for (i = 0; i < map.tail_nr; i ++) { if (map.tails[i].offset == tail_start) { if (map.tails[i].offset + map.tails[i].len <= off) return 1; return 0; } } // there was no this tail yet return 1; } return 0; } static void do_append (struct item_head * ih, void * data) { int i; int padd; unsigned long long off = get_offset (&ih->ih_key); if (is_indirect_ih (ih)) { padd = (off - 1) / fs->fs_blocksize - map.head_len; map.head = realloc (map.head, (map.head_len + padd + I_UNFM_NUM (ih)) * 4); if (!map.head) reiserfs_panic ("realloc failed"); memset ((char *)map.head + map.head_len * 4, 0, padd * 4); memcpy ((char *)map.head + (map.head_len + padd) * 4, data, get_ih_item_len (ih)); map.head_len += (padd + I_UNFM_NUM (ih)); } else if (is_direct_ih (ih)) { unsigned int tail_start, skip; // find correct tail first tail_start = (off & ~(fs->fs_blocksize - 1)) + 1; skip = (off - 1) & (fs->fs_blocksize - 1); for (i = 0; i < map.tail_nr; i ++) { if (map.tails[i].offset == tail_start) { map.tails[i].data = realloc (map.tails[i].data, off - tail_start + get_ih_item_len (ih)); if (!map.tails[i].data) reiserfs_panic ("realloc failed"); padd = skip - map.tails[i].len; memset (map.tails[i].data + map.tails[i].len, 0, padd); memcpy (map.tails[i].data + map.tails[i].len + padd, data, get_ih_item_len (ih)); map.tails[i].len += (padd + get_ih_item_len (ih)); return; } } // allocate memory for new tail map.tails = realloc (map.tails, (map.tail_nr + 1) * sizeof (struct tail)); if (!map.tails) reiserfs_panic ("realloc failed"); map.tails[map.tail_nr].offset = off; map.tails[map.tail_nr].len = skip + get_ih_item_len (ih); map.tails[map.tail_nr].data = malloc (map.tails[map.tail_nr].len); memset (map.tails[map.tail_nr].data, 0, skip); memcpy (map.tails[map.tail_nr].data + skip, data, get_ih_item_len (ih)); map.tail_nr ++; } } // map contains static void do_overwrite (struct item_head * ih, void * data) { unsigned long long off, skip; int to_compare, to_append; struct item_head tmp_ih; char * p; off = get_offset (&ih->ih_key); if (is_indirect_ih (ih)) { skip = (off - 1) / fs->fs_blocksize; to_compare = (map.head_len - skip > I_UNFM_NUM (ih)) ? I_UNFM_NUM (ih) : (map.head_len - skip); to_append = I_UNFM_NUM (ih) - to_compare; p = (char *)map.head + skip * 4; if (memcmp (p, data, to_compare * 4)) reiserfs_warning (stderr, "overwrite (indirect): %H contains different data\n", ih); if (to_append) { tmp_ih = *ih; set_ih_item_len (&tmp_ih, get_ih_item_len (ih) - to_compare * 4); set_offset (key_format (&ih->ih_key), &tmp_ih.ih_key, off + to_compare * fs->fs_blocksize); do_append (&tmp_ih, (char *)data + to_compare * 4); } } else if (is_direct_ih (ih)) { unsigned int tail_start; int i; // find correct tail first tail_start = (off & ~(fs->fs_blocksize - 1)) + 1; for (i = 0; i < map.tail_nr; i ++) { if (map.tails[i].offset == tail_start) { // ih is a part of this tail skip = (off - 1) & (fs->fs_blocksize - 1); to_compare = (map.tails[i].len - skip > get_ih_item_len (ih) ? get_ih_item_len (ih) : map.tails[i].len - skip); to_append = get_ih_item_len (ih) - to_compare; p = (char *)map.tails[i].data + skip; if (memcmp (p, data, to_compare)) reiserfs_warning (stderr, "overwrite (direct): %H contains different data\n", ih); if (to_append) { tmp_ih = *ih; set_ih_item_len (&tmp_ih, get_ih_item_len (ih) - to_compare); set_offset (key_format (&ih->ih_key), &tmp_ih.ih_key, off + to_compare); do_append (&tmp_ih, (char *)data + to_compare); } return; } } reiserfs_panic ("no appropriate tail found"); } } static void map_one_item (struct saved_item * item) { struct buffer_head * bh; struct item_head * ih; void * data; // read the block containing the item bh = bread (fs->fs_dev, item->si_block, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "bread failed\n"); return; } ih = B_N_PITEM_HEAD (bh, item->si_item_num); data = B_I_PITEM (bh, ih); if (memcmp (&item->si_ih, ih, sizeof (*ih))) reiserfs_panic ("wrong item"); if (have_to_append (ih)) { do_append (ih, data); } else do_overwrite (ih, data); brelse (bh); } // flush map which is in variable map static void flush_map (reiserfs_filsys_t * fs, struct key * dir, char * name, struct key * key) { int i; FILE * fp; __u32 v32; if (!map_file (fs)) asprintf (&map_file (fs), "%s", ".map"); //reiserfs_warning (stderr, "Saving maps into %s\n", map_file (fs)); fp = fopen (map_file (fs), "a"); if (fp == 0) { reiserfs_warning (stderr, "flush_map: fopen failed: %m"); return; } v32 = MAP_MAGIC; fwrite (&v32, sizeof (v32), 1, fp); // device name v32 = strlen (device_name (fs)) + 1; fwrite (&v32, sizeof (v32), 1, fp); fwrite (device_name (fs), v32, 1, fp); // name length and the name itself v32 = strlen (name) + 1; fwrite (&v32, sizeof (v32), 1, fp); fwrite (name, v32, 1, fp); // short key of a directory fwrite (dir, SHORT_KEY_SIZE, 1, fp); // short key of file fwrite (key, SHORT_KEY_SIZE, 1, fp); // list of data block pointers fwrite (&map.head_len, sizeof (map.head_len), 1, fp); fwrite (map.head, map.head_len * 4, 1, fp); // find correct tail first for (i = 0; i < map.tail_nr; i ++) { if (map.tails [i].offset == map.head_len * fs->fs_blocksize) { // tail length and the tail itself fwrite (&map.tails [i].len, sizeof (map.tails [i].len), 1, fp); fwrite (map.tails [i].data, map.tails [i].len, 1, fp); break; } } if (i == map.tail_nr) { // no tail v32 = 0; fwrite (&v32, sizeof (v32), 1, fp); } v32 = MAP_END_MAGIC; fwrite (&v32, sizeof (v32), 1, fp); fclose (fp); } // write map of file to a map file /* static void map_item_list (const void *nodep, VISIT value, int level) { struct saved_item * item, * longest; int bytes, max_bytes; if (value != leaf && value != postorder) return; item = *(struct saved_item **)nodep; // 1. find the longest item max_bytes = get_bytes_number (&item->si_ih, fs->fs_blocksize); longest = item; while (item->si_next) { item = item->si_next; bytes = get_bytes_number (&item->si_ih, fs->fs_blocksize); if (bytes > max_bytes) { longest = item; max_bytes = bytes; } } map_one_item (longest); // map other items item = *(struct saved_item **)nodep; while (item) { if (item != longest) map_one_item (item); item = item->si_next; } } static void make_file_map (const void *nodep, VISIT value, int level) { struct saved_name * name; static int nr = 0; name = *(struct saved_name **)nodep; if (value == leaf || value == postorder) { while (name) { reiserfs_warning (stdout, "%d - (%d): [%K]:\"%s\":\n", ++nr, name->count, &name->parent_dirid, name->name); if (name->items) { // initialize the map memset (&map, 0, sizeof (struct file_map)); // make a map of file twalk (name->items, map_item_list); // write map to a file flush_map (fs, (struct key *)&name->parent_dirid, name->name, (struct key *)&name->dirid); } else if (name->first_name) reiserfs_warning (stdout, "[%K]:\"%s\" has item list\n", &name->first_name->parent_dirid, name->first_name->name); else { reiserfs_warning (stdout, "No items of the file [%K] found\n", &name->dirid); } name = name->name_next; } } } */ static void print_items(FILE *fp, reiserfs_filsys_t * fs) { struct buffer_head *bh; struct item_head *ih; struct saved_item item; int size = sizeof(struct saved_item) - sizeof(struct saved_item *); while (fread(&item, size, 1, fp) == 1) { bh = bread (fs->fs_dev, item.si_block, fs->fs_blocksize); if (!bh) { reiserfs_warning (fp, "bread failed\n"); continue; } ih = B_N_PITEM_HEAD (bh, item.si_item_num); reiserfs_print_item(stdout, bh, ih); brelse(bh); } } void print_map(reiserfs_filsys_t * fs) { FILE * fp; if (map_file (fs)) { fp = fopen (map_file (fs), "r"); if (fp == 0) { reiserfs_warning (stderr, "fopen failed: %m\n"); return; } } else { reiserfs_warning (stderr, "Reading file map from stdin..\n"); fflush (stderr); fp = stdin; } print_items(fp, fs); if (fp != stdin) { fclose (fp); fp = NULL; } } static FILE *fp = 0; FILE * log_to; static void save_items(const void *nodep, VISIT value, int level) { struct saved_item *item; if (value != leaf && value != postorder) return; item = *(struct saved_item **)nodep; while (item) { fwrite(item, sizeof(struct saved_item) - sizeof(struct saved_item *), 1, fp); item = item->si_next; } } static void make_map(const void *nodep, VISIT value, int level) { struct saved_name * name; char *file_name = 0; static int nr = 0; name = *(struct saved_name **)nodep; if (value == leaf || value == postorder) { while (name) { asprintf(&file_name, "%s.%d", map_file(fs), ++nr); reiserfs_warning (log_to, "%d - (%d): [%K]:\"%s\": stored in the %s\n", nr, name->count, &name->parent_dirid, name->name, file_name); if (fp == 0) { fp = fopen (file_name, "w+"); if (!fp) reiserfs_panic ("could open %s: %m", file_name); } if (name->items) twalk (name->items, save_items); name = name->name_next; fclose(fp); fp = NULL; free(file_name); } } } /* store map if it is a regular file */ static void locate_file (reiserfs_filsys_t * fs, struct key * key) { INITIALIZE_PATH (path); struct key * next_key; int retval; do { retval = reiserfs_search_by_key_4 (fs, key, &path); if (retval != ITEM_FOUND) break; if (!is_stat_data_key (key) && !is_direntry_key (key)) { struct saved_item si; si.si_block = get_bh (&path)->b_blocknr; si.si_item_num = get_item_pos (&path); si.si_ih = *get_ih (&path); map_one_item (&si); } /*reiserfs_warning (stdout, "\t"); reiserfs_print_item (stdout, get_bh (&path), get_ih (&path));*/ next_key = reiserfs_next_key (&path); if (!next_key || not_of_one_file (next_key, key)) break; *key = *next_key; pathrelse (&path); } while (1); pathrelse (&path); } /* read stdin and look for specified name in the specified directory */ static void look_for_name (reiserfs_filsys_t * fs) { INITIALIZE_PATH (path); char * name, * objectid, * dirid; size_t n; struct key key = {0, }; reiserfs_warning (stderr, "Enter dirid objectid \"name\" or press ^D to quit\n"); while (1) { reiserfs_warning (stderr, ">"); n = 0; dirid = 0; if (getdelim (&dirid, &n, ' ', stdin) == -1) break; if (!strcmp (dirid, "\n")) break; set_key_dirid (&key, atol (dirid)); n = 0; objectid = 0; if (getdelim (&objectid, &n, ' ', stdin) == -1) break; set_key_objectid (&key, atol (objectid)); n = 0; name = 0; if (getdelim (&name, &n, '\n', stdin) == -1) break; name [strlen (name) - 1] = 0; reiserfs_warning (stdout, "looking for file \"%s\" in (%K) - ", name, &key); if (reiserfs_locate_entry (fs, &key, name, &path)) { struct key fkey = {0, }; struct reiserfs_de_head * deh; reiserfs_warning (stdout, "name is found in block %lu (item %d, entry %d)\n", get_bh (&path)->b_blocknr, get_item_pos (&path), path.pos_in_item); deh = B_I_DEH (get_bh (&path), get_ih (&path)) + path.pos_in_item; set_key_dirid (&fkey, get_deh_dirid (deh)); set_key_objectid (&fkey, get_deh_objectid (deh)); pathrelse (&path); /* look for file and print its layout */ memset (&map, 0, sizeof (struct file_map)); locate_file (fs, &fkey); flush_map (fs, &key, name, &fkey); } else { reiserfs_warning (stdout, "name not found\n"); } free (dirid); free (objectid); free (name); } } static void scan_for_key (struct buffer_head * bh, struct key * key) { int i, j, i_num; struct item_head * ih; struct reiserfs_de_head * deh; int min_entry_size = 1; int ih_entry_count = 0; ih = B_N_PITEM_HEAD (bh, 0); i_num = leaf_item_number_estimate(bh); for (i = 0; i < i_num; i ++, ih ++) { if ((get_key_dirid(&ih->ih_key) == get_key_dirid(key) || get_key_dirid(key) == ~0ul) && (get_key_objectid(&ih->ih_key) == get_key_objectid(key) || get_key_objectid(key) == ~0ul)) { reiserfs_warning(log_to, "%d-th item of block %lu is item of file %K: %H\n", i, bh->b_blocknr, key, ih); } if (!is_direntry_ih (ih)) continue; deh = B_I_DEH (bh, ih); if ( (get_ih_entry_count (ih) > (get_ih_item_len(ih) / (DEH_SIZE + min_entry_size))) || (get_ih_entry_count (ih) == 0)) ih_entry_count = get_ih_item_len(ih) / (DEH_SIZE + min_entry_size); else ih_entry_count = get_ih_entry_count (ih); for (j = 0; j < ih_entry_count; j ++, deh ++) { if ((get_deh_dirid (deh) == get_key_dirid (key) || (int)get_key_dirid (key) == -1) && (get_deh_objectid (deh) == get_key_objectid (key) || (int)get_key_objectid (key) == -1)) { reiserfs_warning (log_to, "dir item %d (%H) of block %lu has " "entry (%d-th) %.*s pointing to %K\n", i, ih, bh->b_blocknr, j, name_in_entry_length (ih, deh, j), name_in_entry (deh, j), key); } } } return; } void do_scan (reiserfs_filsys_t * fs) { unsigned long i; struct buffer_head * bh; int type; char * answer = 0; size_t n = 0; struct key key = {0, 0, }; unsigned long done, total; if (debug_mode (fs) == DO_LOOK_FOR_NAME) { /* look for a file in using tree algorithms */ look_for_name (fs); return; } /* scan area of disk and store all names matching the pattern */ /* initialize storage and two indexes */ obstack_init (&name_store); obstack_init (&item_store); key_index = 0; name_index = 0; total = reiserfs_bitmap_ones (input_bitmap (fs)); log_to = fopen ("scan.log", "w+"); printf ("Log file 'scan.log' is opened\n"); if (debug_mode (fs) == DO_SCAN_FOR_NAME) { if (regcomp (&pattern, name_pattern (fs), 0)) { printf ("regcomp failed"); return; } printf ("Looking for names matching %s\n", name_pattern (fs)); set_key_dirid (&key, 1); } else { printf ("What key do you want to find: dirid?"); getline (&answer, &n, stdin); set_key_dirid (&key, atoi (answer)); printf ("objectid?"); getline (&answer, &n, stdin); set_key_objectid (&key, atoi (answer)); reiserfs_warning (stderr, "looking for (%K)\n", &key); } done = 0; for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { if (!reiserfs_bitmap_test_bit (input_bitmap (fs), i)) continue; bh = bread (fs->fs_dev, i, fs->fs_blocksize); if (!bh) { printf ("could not read block %lu\n", i); continue; } type = who_is_this (bh->b_data, bh->b_size); switch (type) { case THE_JDESC: if (!get_key_dirid (&key)) printf ("block %lu is journal descriptor\n", i); reiserfs_bitmap_clear_bit (input_bitmap (fs), i); break; case THE_SUPER: if (!get_key_dirid (&key)) printf ("block %lu is reiserfs super block\n", i); reiserfs_bitmap_clear_bit (input_bitmap (fs), i); break; case THE_INTERNAL: if (!get_key_dirid (&key)) printf ("block %lu is reiserfs internal node\n", i); reiserfs_bitmap_clear_bit (input_bitmap (fs), i); break; case THE_LEAF: case HAS_IH_ARRAY: if (debug_mode (fs) == DO_SCAN_FOR_NAME) { scan_for_name (bh); } else if (get_key_dirid (&key)) { scan_for_key (bh, &key); } else { printf ("block %lu is reiserfs leaf node\n", i); } break; default: reiserfs_bitmap_clear_bit (input_bitmap (fs), i); break; } brelse (bh); print_how_far (stderr, &done, total, 1, be_quiet (fs)); } fprintf (stderr, "\n"); if (debug_mode (fs) == DO_SCAN_FOR_NAME) fprintf (stderr, "There were found %d names matching the pattern \"%s\", %d names skipped\n", saved_names, name_pattern (fs), skipped_names); fflush (stderr); if (debug_mode (fs) != DO_SCAN_FOR_NAME) return; /* step 2: */ done = 0; total = reiserfs_bitmap_ones (input_bitmap (fs)); printf ("%ld bits set in bitmap\n", total); for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { int type; if (!reiserfs_bitmap_test_bit (input_bitmap (fs), i)) continue; bh = bread (fs->fs_dev, i, fs->fs_blocksize); if (!bh) { printf ("could not read block %lu\n", i); continue; } type = who_is_this (bh->b_data, bh->b_size); if (type != THE_LEAF && type != HAS_IH_ARRAY) { brelse (bh); continue; } scan_items (bh); brelse (bh); print_how_far (stderr, &done, total, 1, be_quiet (fs)); } fprintf (stderr, "\nThere were %d items saved\n", saved_items); /* ok, print what we found */ /*twalk (name_index, print_file);*/ /* create map for every file in */ twalk (name_index, make_map); /* print names of files we have map of in a file 'file.list' */ /*twalk (name_index, print_name);*/ } reiserfsprogs-3.6.9/debugreiserfs/stat.c0000664000077100007710000001521307665645672014116 /* * Copyright 2002-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "debugreiserfs.h" #include #include #define obstack_chunk_alloc malloc #define obstack_chunk_free free /* try to find blocks which contain only items which are */ /* read blocks marked in debug_bitmap and collect statistic of it: number of stat data */ struct { unsigned long all; unsigned long items [5]; unsigned long unique_keys; /* keys of stat datas */ unsigned long unique_entry_keys; /* keys which appear in directory entries */ unsigned long names; /* dir entries but "." and ".." */ unsigned long dir_blocks; /* block containing only one directory item */ unsigned long unique_items; unsigned long leaves; unsigned long blocks_to_skip; } fs_stat; /* store unique item heads */ struct obstack items; /* tree sorting item heades by comp_items_1 */ void * items_tree; static int comp_items_1 (const void * p1, const void * p2) { int retval; struct item_head * ih1, * ih2; /* if (*(int *)p1 != *(int *)p2) retval = 1; else retval = 0; */ retval = comp_keys (p1, p2); /*retval = comp_short_keys (p1, p2);*/ if (retval) return retval; ih1 = (struct item_head *)p1; ih2 = (struct item_head *)p2; if (get_ih_item_len (ih1) < get_ih_item_len (ih2)) return -1; if (get_ih_item_len (ih1) > get_ih_item_len (ih2)) return 1; if (get_ih_entry_count (ih1) < get_ih_entry_count (ih2)) return -1; if (get_ih_entry_count (ih1) > get_ih_entry_count (ih2)) return 1; return 0; } /* static void print_node (const void *nodep, VISIT value, int level) { int i; if (value == leaf) { for (i = 0; i < level; i ++) reiserfs_warning (stdout, "\t"); reiserfs_warning (stdout, "%H\n", *(struct item_head **)nodep); return; } if (value == postorder) { for (i = 0; i < level; i ++) reiserfs_warning (stdout, "\t"); reiserfs_warning (stdout, "%H\n", *(struct item_head **)nodep); } } */ static int is_unique_item (struct obstack * ostack, void ** tree, void * ih) { void * res; void * key1; key1 = obstack_copy (ostack, ih, IH_SIZE); res = tsearch (key1, tree, comp_items_1); if (!res) reiserfs_panic ("Too many keys found"); /* twalk (*tree, print_node);*/ /* reiserfs_warning (stderr, "\n\n");*/ if (*(void **)res != key1) { /* key is in tree already, remove it from obstack */ /*reiserfs_warning (stdout, "%H is skipped\n", ih);fflush (stdout);*/ obstack_free (ostack, key1); return 0; } /*reiserfs_warning (stdout, "%k is added\n", ih);fflush (stdout);*/ return 1; } static void stat1_the_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh) { int i, i_num; struct item_head * ih; int is_there_unique_item; ih = B_N_PITEM_HEAD (bh, 0); is_there_unique_item = 0; i_num = leaf_item_number_estimate(bh); for (i = 0; i < i_num; i ++, ih ++) { /* count all items */ fs_stat.all ++; if (is_unique_item (&items, &items_tree, ih)) { /* this is item we have not seen yet */ fs_stat.unique_items ++; is_there_unique_item ++; } } if (!is_there_unique_item) { /* the node contains only items we have seen already. so we will skip it */ fs_stat.blocks_to_skip ++; reiserfs_bitmap_clear_bit (input_bitmap (fs), bh->b_blocknr); } else { ih = B_N_PITEM_HEAD (bh, 0); /* node contains at least one unique item. We will put it in, count items of each type */ for (i = 0; i < i_num; i ++, ih ++) { fs_stat.items [get_type (&ih->ih_key)] ++; } } } /* static void stat2_the_leaf (struct buffer_head * bh) { int i; struct item_head * ih; ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < node_item_number (bh); i ++, ih ++) { } } */ void do_stat (reiserfs_filsys_t * fs) { unsigned long i; unsigned long done, total; struct buffer_head * bh; int type; FILE * fp; obstack_init (&items); items_tree = 0; /* bh = bread (fs->s_dev, 8211, fs->s_blocksize); stat1_the_leaf (fs, bh); return; */ /* pass 0 of stating */ total = reiserfs_bitmap_ones (input_bitmap (fs)); done = 0; for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { if (!reiserfs_bitmap_test_bit (input_bitmap (fs), i)) continue; print_how_far (stderr, &done, total, 1, be_quiet (fs)); bh = bread (fs->fs_dev, i, fs->fs_blocksize); if (!bh) { printf ("could not read block %lu\n", i); continue; } type = who_is_this (bh->b_data, bh->b_size); if (type != THE_LEAF && type != HAS_IH_ARRAY) { reiserfs_bitmap_clear_bit (input_bitmap (fs), i); brelse (bh); continue; } fs_stat.leaves ++; stat1_the_leaf (fs, bh); brelse (bh); } reiserfs_warning (stderr, "\nThere were %lu leaves\n" "\ttotal number of items %lu there\n" "\tblocks containing at least one unique item %lu\n" "\tblocks which can be skipped %lu\n" "\t\tstat data %lu\n" "\t\tindirect %lu\n" "\t\tdirect %lu\n" "\t\tdirectory items %lu\n" "\tunique items %lu\n", /* "\tnames there (but \".\" and \"..\") %lu\n" "\tpointing to unique keys %lu\n" "other items %lu\n" "blocks containing only 1 dir item %lu\n", */ fs_stat.leaves, fs_stat.all, fs_stat.leaves - fs_stat.blocks_to_skip, fs_stat.blocks_to_skip, fs_stat.items [TYPE_STAT_DATA], fs_stat.items [TYPE_INDIRECT], fs_stat.items [TYPE_DIRECT], fs_stat.items [TYPE_DIRENTRY], fs_stat.unique_items); /* fs_stat.names, fs_stat.unique_keys, fs_stat.items [4], fs_stat.dir_blocks); */ if (!input_bitmap_file_name(fs)) return; fp = fopen (input_bitmap_file_name(fs), "w"); if (!fp) reiserfs_panic ("stat: could not open %s to save bitmap: %m\n", input_bitmap_file_name(fs)); reiserfs_warning (stderr, "Updated bitmap contains %d blocks marked\n", reiserfs_bitmap_ones (input_bitmap (fs))); reiserfs_bitmap_save (fp, input_bitmap (fs)); fclose (fp); return; /* pass 2 of stating */ reiserfs_warning (stderr, "Looking for blocks containing only keys not pointed by any of entries\n"); total = reiserfs_bitmap_ones (input_bitmap (fs)); done = 0; for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { if (!reiserfs_bitmap_test_bit (input_bitmap (fs), i)) continue; print_how_far (stderr, &done, total, 1, be_quiet (fs)); bh = bread (fs->fs_dev, i, fs->fs_blocksize); if (!bh) { printf ("could not read block %lu\n", i); continue; } /*stat2_the_leaf (bh);*/ } } reiserfsprogs-3.6.9/debugreiserfs/corruption.c0000664000077100007710000011071007705261642015327 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "debugreiserfs.h" extern struct reiserfs_fsstat g_stat_info; int do_one_ih_corrupt (struct item_head * ih, unsigned int nr_bytes); int do_one_ih_random_corrupt (struct item_head * ih); void do_one_corruption_in_one_block (reiserfs_filsys_t * fs, struct buffer_head * bh, char * corruption_command); int corrupt_block_header (struct block_head * blkh, unsigned int offset, unsigned int bytes ); void do_one_block_random_corrupt (struct buffer_head * bh); static int str2int (char * str, int * res) { int val; char * tmp; val = (int) strtol (str, &tmp, 0); if (tmp == str) /* could not convert string into a number */ return 0; *res = val; return 1; } static int get_rand (double min, double max) { /* srand (time (0)); */ int ret; ret = (int)(min + (int)((max - min + 1) * rand() / (RAND_MAX + 1.0))); if ((ret < min) || (ret > max)) die ("get_rand failed: min %d, max %d, returned %d\n", (int)min, (int)max, ret); return ret; } static void edit_journal_params (struct journal_params * jp) { char * str; size_t n; int num; printf ("Journal parameters:\n"); printf ("\tDevice: current: %x: new:", get_jp_journal_dev (jp)); getline (&str, &n, stdin); if (str2int (str, &num)) set_jp_journal_dev (jp, num); printf ("\tFirst block: current: %d: new:", get_jp_journal_1st_block (jp)); getline (&str, &n, stdin); if (str2int (str, &num)) set_jp_journal_1st_block (jp, num); printf ("\tSize: current: %d: new:", get_jp_journal_size (jp)); getline (&str, &n, stdin); if (str2int (str, &num)) set_jp_journal_size (jp, num); printf ("\tMagic number: current: %d: new:", get_jp_journal_magic (jp)); getline (&str, &n, stdin); if (str2int (str, &num)) set_jp_journal_magic (jp, num); printf ("\tMax transaction size: current: %d: new:", get_jp_journal_max_trans_len (jp)); getline (&str, &n, stdin); if (str2int (str, &num)) set_jp_journal_max_trans_len (jp, num); printf ("\tMax batch size: current: %d: new:", get_jp_journal_max_batch (jp)); getline (&str, &n, stdin); if (str2int (str, &num)) set_jp_journal_max_batch (jp, num); printf ("\tMax commit age: current: %d: new:", get_jp_journal_max_commit_age (jp)); getline (&str, &n, stdin); if (str2int (str, &num)) set_jp_journal_max_commit_age (jp, num); } /* this allows to edit all super block fields */ static void edit_super_block (reiserfs_filsys_t * fs) { char * str; size_t n; int num; str = 0; n = 0; /* bs_block_count */ printf ("\tBlock count: current: %u: new:", get_sb_block_count (fs->fs_ondisk_sb)); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_block_count (fs->fs_ondisk_sb, num); /* sb_free_blocks */ printf ("\tFree block count: current: %u: new:", get_sb_free_blocks (fs->fs_ondisk_sb)); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_free_blocks (fs->fs_ondisk_sb, num); /* sb_root_block */ printf ("\tRoot block: current: %u: new:", get_sb_root_block (fs->fs_ondisk_sb)); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_root_block (fs->fs_ondisk_sb, num); /* sb_journal */ edit_journal_params (sb_jp (fs->fs_ondisk_sb)); /* sb_blocksize */ printf ("\tBlocksize: current: %u: new:", get_sb_block_size (fs->fs_ondisk_sb)); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_block_size (fs->fs_ondisk_sb, num); /* sb_oid_maxsize */ printf ("\tMax objectid size: current: %u: new:", get_sb_oid_maxsize (fs->fs_ondisk_sb)); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_oid_maxsize (fs->fs_ondisk_sb, num); /* sb_oid_cursize */ printf ("\tCur objectid size: current: %u: new:", get_sb_oid_cursize (fs->fs_ondisk_sb)); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_oid_cursize (fs->fs_ondisk_sb, num); /* sb_state */ printf ("\tUmount state: current: %u: new:", get_sb_umount_state (fs->fs_ondisk_sb)); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_umount_state (fs->fs_ondisk_sb, num); /* char s_magic [10]; */ printf ("\tMagic: current: \"%s\": new:", fs->fs_ondisk_sb->s_v1.s_magic); getline (&str, &n, stdin); if (strcmp (str, "\n")) strncpy (fs->fs_ondisk_sb->s_v1.s_magic, str, n > 10 ? 10 : n); /* __u16 sb_fsck_state; */ printf ("\tFielsystem state: current: %u: new:", get_sb_fs_state (fs->fs_ondisk_sb)); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_fs_state (fs->fs_ondisk_sb, num); /* __u32 sb_hash_function_code; */ printf ("\tHash code: current: %u: new (tea %d, r5 %d, rupasov %d):", get_sb_hash_code (fs->fs_ondisk_sb), TEA_HASH, R5_HASH, YURA_HASH); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_hash_code (fs->fs_ondisk_sb, num); /* __u16 sb_tree_height; */ printf ("\tTree height: current: %u: new:", get_sb_tree_height (fs->fs_ondisk_sb)); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_tree_height (fs->fs_ondisk_sb, num); /* __u16 sb_bmap_nr; */ printf ("\tNumber of bitmaps: current: %u: new:", get_sb_bmap_nr (fs->fs_ondisk_sb)); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_bmap_nr (fs->fs_ondisk_sb, num); /* __u16 sb_version; */ printf ("\tFilesystem format: current: %u: new:", le16_to_cpu (fs->fs_ondisk_sb->s_v1.sb_version)); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_version (fs->fs_ondisk_sb, num); /* __u16 sb_reserved_for_journal; */ printf ("\tSpace reserved for journal: current: %u: new:", get_sb_reserved_for_journal (fs->fs_ondisk_sb)); getline (&str, &n, stdin); if (str2int (str, &num)) set_sb_reserved_for_journal (fs->fs_ondisk_sb, num); print_block (stdout, fs, fs->fs_super_bh); if (user_confirmed (stderr, "Is this ok ? [N/Yes]: ", "Yes\n")) { mark_buffer_dirty (fs->fs_super_bh); bwrite (fs->fs_super_bh); } } static void corrupt_clobber_hash (char * name, struct item_head * ih, struct reiserfs_de_head * deh) { printf ("\tCorrupting deh_offset of entry \"%s\" of [%u %u]\n", name, get_key_dirid (&ih->ih_key), get_key_objectid (&ih->ih_key)); set_deh_offset (deh, 700); } /* this reads list of desired corruptions from stdin and perform the corruptions. Format of that list: A hash_code C name objectid - 'C'ut entry 'name' from directory item with 'objectid' H name objectid - clobber 'H'hash of entry 'name' of directory 'objectid' I item_num pos_in_item make pos_in_item-th slot of indirect item to point out of device O item_num - destroy item 'O'rder - make 'item_num'-th to have key bigger than 'item_num' + 1-th item D item_num - 'D'elete item_num-th item S item_num value - change file size (item_num-th item must be stat data) F item_num value - change sd_first_direct_byte of stat data J item_num objectid E name objectid new - change entry's deh_objectid to new P - print the block B offset bytes_to_corrupt - corrupt bytes_to_corrupt bytes in block header, start from offset */ void do_corrupt_one_block (reiserfs_filsys_t * fs, char * fline) { struct buffer_head * bh; char * line = 0; size_t n = 0; unsigned long block; block = certain_block (fs); printf ("block = %lu\n", block); if (block == fs->fs_super_bh->b_blocknr) { edit_super_block (fs); return; } if (!fs->fs_bitmap2) { struct buffer_head * bm_bh; unsigned long bm_block; if (spread_bitmaps (fs)) bm_block = ( block / (fs->fs_blocksize * 8) ) ? (block / (fs->fs_blocksize * 8)) * (fs->fs_blocksize * 8) : fs->fs_super_bh->b_blocknr + 1; else bm_block = fs->fs_super_bh->b_blocknr + 1 + (block / (fs->fs_blocksize * 8)); bm_bh = bread (fs->fs_dev, bm_block, fs->fs_blocksize); if (bm_bh) { if ( misc_test_bit((block % (fs->fs_blocksize * 8)), bm_bh->b_data) ) fprintf (stderr, "%lu is used in ondisk bitmap\n", block); else fprintf (stderr, "%lu is free in ondisk bitmap\n", block); brelse (bm_bh); } } else { if (reiserfs_bitmap_test_bit (fs->fs_bitmap2, block)) fprintf (stderr, "%lu is used in ondisk bitmap\n", block); else fprintf (stderr, "%lu is free in ondisk bitmap\n", block); } /* READ block */ bh = bread (fs->fs_dev, block, fs->fs_blocksize); if (!bh) { printf ("corrupt_one_block: bread fialed\n"); return; } if (who_is_this (bh->b_data, fs->fs_blocksize) != THE_LEAF) { printf ("Can not corrupt not a leaf node\n"); brelse (bh); return; } printf ("Corrupting block %lu..\n", bh->b_blocknr); if (data(fs)->log_file_name) { printf ("Log file : %s\n", data(fs)->log_file_name); } else { printf ("No Log file specified\n"); } if (fline != NULL) { do_one_corruption_in_one_block (fs, bh, fline); if ((data(fs)->log_file_name) && (data(fs)->log)) { fprintf (data(fs)->log, "%lu\n", block); fprintf (data(fs)->log, "%s\n", fline); } } else { /* Get list of corruptions from stdin */ while (getline (&line, &n, stdin) != -1) { if ( line [0] == '\n' ) { free (line); line = 0; n = 0; break; } do_one_corruption_in_one_block (fs, bh, line); if ((data(fs)->log_file_name) && (data(fs)->log)) { fprintf (data(fs)->log, "%lu\n", block); fprintf (data(fs)->log, "%s\n", line); } free (line); line = 0; n = 0; } } printf ("Done\n"); bwrite(bh); brelse (bh); return; } void do_one_corruption_in_one_block (reiserfs_filsys_t * fs, struct buffer_head * bh, char * corruption_command) { int i, j; struct item_head * ih; int item_num; int item_numbers; int bytes_to_corrupt; char code, name [100]; __u32 objectid, new_objectid; int value; int hash_code; unsigned int pos_in_item; int type, format; printf ("corruption_command : %s", corruption_command); switch (corruption_command [0]) { case '#': case '\n': break; case '?': printf ("A hash_code - reset hAsh code in super block\n" "T item_num type (0, 1, 2, 3) format (0, 1)\n" "C name objectid - Cut entry 'name' from directory item with 'objectid'\n" "H name objectid - clobber Hash of entry 'name' of directory 'objectid'\n" "I item_num pos_in_item make pos_in_tem-th slot of Indirect item to point out of device\n" "O item_num - destroy item Order - make 'item_num'-th to have key bigger than 'item_num' + 1-th item\n" "D item_num - Delete item_num-th item\n" "S item_num value - change file Size (item_num-th item must be stat data)\n" "F item_num value - change sd_First_direct_byte of stat data\n" "J item_num objectid - set 'obJectid' of 'item_num'-th item\n" "E name objectid objectid - set deh_objectid of an entry to objectid\n" "N item_numbers bytes_to_corrupt - corrupt bytes_to_corrupt in number of bytes in item_numbers items\n" "B offset bytes_to_corrupt - corrupt bytes_to_corrupt in block_header, start corruption from offset\n"); break; case 'P': print_block (stderr, fs, bh, 3, -1, -1); break; case 'A': /* corrupt hash record in super block */ if (sscanf (corruption_command, "%c %d\n", &code, &hash_code) != 2) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } reiserfs_warning (stderr, "Changing %s to %s\n", code2name (get_sb_hash_code (fs->fs_ondisk_sb)), code2name (hash_code)); set_sb_hash_code (fs->fs_ondisk_sb, hash_code); break; case 'C': /* cut entry */ case 'H': /* make hash wrong */ if (sscanf (corruption_command, "%c %s %u\n", &code, name, &objectid) != 3) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) { struct reiserfs_de_head * deh; /* look for property objectid */ if (get_key_objectid (&ih->ih_key) != objectid || !is_direntry_ih (ih)) continue; deh = B_I_DEH (bh, ih); for (j = 0; j < get_ih_entry_count (ih); j ++, deh ++) { /* look for proper entry */ if (name_in_entry_length (ih, deh, j) == (int)strlen (name) && !strncmp (name, name_in_entry (deh, j), strlen (name))) break; } if (j == get_ih_entry_count (ih)) { printf ("Can't find entry %s\n", name); exit (1); } switch (code) { case 'H' : /* clobber hash */ corrupt_clobber_hash (name, ih, deh); break; case 'C' : /* cut entry */ cut_entry (fs, bh, i, j, 1); break; default: printf ("Unknown command found\n"); } } if (!B_IS_IN_TREE (bh)) { printf ("NOTE: block is deleted from the tree\n"); exit (0); } break; case 'E': /* set objectid : used to simulate objectid sharing problem */ if (sscanf (corruption_command, "%c %s %u %d\n", &code, name, &objectid, &new_objectid) != 4) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) { struct reiserfs_de_head * deh; /* look for property objectid */ if (get_key_objectid (&ih->ih_key) != objectid || !is_direntry_ih (ih)) continue; deh = B_I_DEH (bh, ih); set_deh_objectid (deh, new_objectid); break; } break; case 'T': /* set type of item */ if (sscanf (corruption_command, "%c %d %d %d\n", &code, &item_num, &type, &format) != 4) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } if (item_num > get_blkh_nr_items (B_BLK_HEAD (bh))) { printf ("Wrong format \'%c\', wrong item_num \n", corruption_command [0]); return; } ih = B_N_PITEM_HEAD (bh, item_num); set_ih_key_format (ih, format); set_type (format, &ih->ih_key, type); break; case 'J': /* set objectid : used to simulate objectid sharing problem */ if (sscanf (corruption_command, "%c %d %d\n", &code, &item_num, &objectid) != 3) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } if (item_num > get_blkh_nr_items (B_BLK_HEAD (bh))) { printf ("Wrong format \'%c\', wrong item_num \n", corruption_command [0]); return; } ih = B_N_PITEM_HEAD (bh, item_num); set_key_objectid (&ih->ih_key, objectid); break; case 'I': /* break unformatted node pointer */ if (sscanf (corruption_command, "%c %d %u\n", &code, &item_num, &pos_in_item) != 3) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } if (item_num > get_blkh_nr_items (B_BLK_HEAD (bh))) { printf ("Wrong format \'%c\', wrong item_num \n", corruption_command [0]); return; } ih = B_N_PITEM_HEAD (bh, item_num); if (!is_indirect_ih (ih) || pos_in_item >= I_UNFM_NUM (ih)) { reiserfs_warning (stderr, "Not an indirect item or there is " "not so many unfm ptrs in it\n"); return; } * ((__u32 *)B_I_PITEM (bh, ih) + pos_in_item) = get_sb_block_count (fs->fs_ondisk_sb) + 100; break; case 'D': /* delete item */ if (sscanf (corruption_command, "%c %d\n", &code, &item_num) != 2) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } if (item_num > get_blkh_nr_items (B_BLK_HEAD (bh))) { printf ("Wrong format \'%c\', wrong item_num \n", corruption_command [0]); return; } delete_item (fs, bh, item_num); break; case 'O': /* make item out of order */ { struct key * key; if (sscanf (corruption_command, "%c %d\n", &code, &item_num) != 2) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } if (item_num > get_blkh_nr_items (B_BLK_HEAD (bh))) { printf ("Wrong format \'%c\', wrong item_num \n", corruption_command [0]); return; } /* destroy item order */ if (item_num == get_blkh_nr_items (B_BLK_HEAD (bh)) - 1) { printf ("can not destroy order\n"); return; } ih = B_N_PITEM_HEAD (bh, item_num); key = &(ih + 1)->ih_key; set_key_dirid (&ih->ih_key, get_key_dirid (key) + 1); break; } case 'S': /* corrupt st_size */ { /* fixme: old stat data only */ struct stat_data_v1 * sd; if (sscanf (corruption_command, "%c %d %d\n", &code, &item_num, &value) != 3) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } if (item_num > get_blkh_nr_items (B_BLK_HEAD (bh))) { printf ("Wrong format \'%c\', wrong item_num \n", corruption_command [0]); return; } ih = B_N_PITEM_HEAD (bh, item_num); sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih); reiserfs_warning (stderr, "Changing sd_size of %k from %d to %d\n", &ih->ih_key, sd_v1_size(sd), value); set_sd_v1_size( sd, value ); break; } case 'F': /* st_first_direct_byte */ { /* fixme: old stat data only */ struct stat_data_v1 * sd; if (sscanf (corruption_command, "%c %d %d\n", &code, &item_num, &value) != 3) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } if (item_num > get_blkh_nr_items (B_BLK_HEAD (bh))) { printf ("Wrong format \'%c\', wrong item_num \n", corruption_command [0]); return; } ih = B_N_PITEM_HEAD (bh, item_num); sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih); reiserfs_warning (stderr, "Changing sd_first_direct_byte of %k from %d to %d\n", &ih->ih_key, sd_v1_first_direct_byte(sd), value); set_sd_v1_first_direct_byte( sd, value ); break; } case 'N': /* corrupt N number of items */ if (sscanf (corruption_command, "%c %d %d\n", &code, &item_numbers, &bytes_to_corrupt) != 3) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } if (item_numbers > get_blkh_nr_items (B_BLK_HEAD (bh))) { printf ("Wrong item_numbers %d expected not more then %d\n", item_numbers, get_blkh_nr_items (B_BLK_HEAD (bh))); return; } for (i = 0; i < item_numbers; i++) { printf ("Do corruptions : %d item header; \n", i ); ih = B_N_PITEM_HEAD (bh, i); do_one_ih_corrupt (ih, bytes_to_corrupt); printf ("Ok\n"); } break; case 'B' : { struct block_head * blkh; unsigned int offset; if (sscanf (corruption_command, "%c %d %d\n", &code, &offset, &bytes_to_corrupt) != 3) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } blkh = B_BLK_HEAD (bh); corrupt_block_header (blkh, offset, bytes_to_corrupt); break; } default: printf ("Unknown command found\n"); } mark_buffer_dirty (bh); return; } /* corrupt first nr_bytes bytes in item header */ int do_one_ih_corrupt (struct item_head * ih, unsigned int nr_bytes) { if (nr_bytes > IH_SIZE) { printf ("Bad byte number %u expected not more then %d\n", nr_bytes, IH_SIZE); exit (1); } if (memset ((char *)ih, 0, nr_bytes) != ih ) { perror ("do_one_ih_corrupt: memset failed"); exit (1); } if ((data(fs)->log_file_name) && (data(fs)->log)) fprintf (data(fs)->log, "\tfirst %u bytes corrupted\n", nr_bytes); printf ("\tfirst %u bytes corrupted\n", nr_bytes); return 0; } /* item header random corruption */ int do_one_ih_random_corrupt (struct item_head * ih) { unsigned int i; unsigned int from; unsigned int count; from = get_rand (0, IH_SIZE - 1); count = get_rand (1, IH_SIZE); if (from + count > IH_SIZE) count = IH_SIZE - from; for (i = from; i < from + count; i ++) ((char *)ih)[i] = get_rand(0, 255); if ((data(fs)->log_file_name) && (data(fs)->log)) fprintf (data(fs)->log, "\tfrom %u ( %u )\n", from, count); printf ("\tfrom %u ( %u )\n", from, count); return 0; } /* Corrupt n bytes in block header */ int corrupt_block_header (struct block_head * blkh, unsigned int offset, unsigned int bytes ) { if ((offset + bytes) > BLKH_SIZE) { printf ("Bad offset number: %u or bad bytes number: %u, the suumary value expected not more then %d\n", offset, bytes, BLKH_SIZE ); exit (1); } if (memset ((char *)blkh, 0, bytes) != blkh ) { perror ("corrupt_block_head: memset failed"); exit (1); } printf ("offset : %u, corrupt %u bytes\n", offset, bytes); return 0; } /* corrupt random number of bytes within block header started from random offset */ void do_one_blkh_random_corrupt (struct buffer_head * bh) { struct block_head * blkh; unsigned int from; unsigned int count; int i; from = get_rand (0, BLKH_SIZE - 1); count = get_rand (1, BLKH_SIZE); blkh = B_BLK_HEAD (bh); if (from + count > BLKH_SIZE) count = BLKH_SIZE - from; for (i = from; i < from + count; i ++) ((char *)blkh)[i] = get_rand(0, 255); if ((data(fs)->log_file_name) && (data(fs)->log)) { fprintf (data(fs)->log, "# : %lu # ", bh->b_blocknr); fprintf (data(fs)->log, "from %u (%u)\n", from, count); } printf ("# : %lu # ", bh->b_blocknr); printf ("from %u (%u)\n", from, count); } void do_leaves_corruption (reiserfs_filsys_t * fs, unsigned long nr_leaves_cr) { struct buffer_head * bh; unsigned long nr_leaves = 0; unsigned int i, should_be_corrupted; srand (time (0)); printf ("%lu leaves will be corrupted\n", nr_leaves_cr); if ((data(fs)->log_file_name) && (data(fs)->log)) { fprintf (data(fs)->log, "Block headers in %lu leaves will be corrupted\n", nr_leaves_cr); } if (reiserfs_open_ondisk_bitmap (fs) < 0) reiserfs_panic ("Could not open ondisk bitmap"); for (i = 0; (i < get_sb_block_count (fs->fs_ondisk_sb)) && nr_leaves < nr_leaves_cr; i ++) { if (!reiserfs_bitmap_test_bit (fs->fs_bitmap2, i)) continue; bh = bread (fs->fs_dev, i, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "could not read block %lu\n", i); continue; } if (who_is_this (bh->b_data, bh->b_size) != THE_LEAF) { brelse (bh); continue; } if ((!is_leaf_node (bh)) || (block_of_journal (fs, i))) { brelse (bh); continue; } should_be_corrupted = (unsigned int) get_rand ((double)0, (double)1); if (should_be_corrupted == 0) { brelse (bh); continue; } do_one_blkh_random_corrupt (bh); /* do_one_block_random_corrupt (bh); */ mark_buffer_dirty (bh); bwrite(bh); brelse (bh); nr_leaves ++; } if ((data(fs)->log_file_name) && (data(fs)->log)) { fprintf (data(fs)->log, "%lu leaves WERE corrupted\n", nr_leaves); } printf ("%lu leaves WERE corrupted\n", nr_leaves); reiserfs_close_ondisk_bitmap (fs); return; } void do_one_block_random_corrupt (struct buffer_head * bh) { unsigned int from = get_rand (0, bh->b_size - 1); unsigned int count = get_rand (1, bh->b_size); int i; if (from + count > bh->b_size) count = bh->b_size - from; for (i = from; i < from + count; i ++) ((char *)bh->b_data)[i] = get_rand(0, 255); if ((data(fs)->log_file_name) && (data(fs)->log)) { fprintf (data(fs)->log, "# block %lu: ", bh->b_blocknr); fprintf (data(fs)->log, "from %u ( %u )\n", from, count); } printf ("# block %lu: ", bh->b_blocknr); printf ("from %u ( %u )\n", from, count); } void do_bitmap_corruption (reiserfs_filsys_t * fs) { unsigned long first = fs->fs_super_bh->b_blocknr + 1; unsigned long nr_bitmap_to_corrupt; unsigned long block; struct buffer_head * bh; int i; nr_bitmap_to_corrupt = (unsigned long)get_rand (1, get_sb_bmap_nr (fs->fs_ondisk_sb) - 1); if ((data(fs)->log_file_name) && (data(fs)->log)) { fprintf (data(fs)->log, "%lu bitmaps will be corrupted\n", nr_bitmap_to_corrupt); } printf ("%lu bitmaps will be corrupted\n", nr_bitmap_to_corrupt); for (i = 0; i < nr_bitmap_to_corrupt; i ++ ) { block = ( i == 0 ) ? first : fs->fs_blocksize * 8 * i; bh = bread (fs->fs_dev, block, fs->fs_blocksize); if (!bh) { printf ("do_bitmap_corruption: bread failed for bitmap %d: %lu\n", i, block); exit (1); } do_one_block_random_corrupt (bh); mark_buffer_dirty (bh); bwrite(bh); brelse (bh); } } /* corrupt the random number of item headers in random number of leaves */ void do_ih_random_corrupt (reiserfs_filsys_t * fs, unsigned long nr_leaves_cr) { unsigned int nr_ih_cr; int i, j; struct buffer_head * bh; struct item_head * ih; unsigned long nr_leaves = 0; unsigned int should_be_corrupted = 0; srand (time (0)); printf ("item headers in %lu leaves will be corrupted\n", nr_leaves_cr); if ((data(fs)->log_file_name) && (data(fs)->log)) { fprintf (data(fs)->log, "item headers in %lu leaves will be corrupted\n", nr_leaves_cr); } if (reiserfs_open_ondisk_bitmap (fs) < 0) reiserfs_panic ("Could not open ondisk bitmap"); for (i = 0; (i < get_sb_block_count (fs->fs_ondisk_sb)) && nr_leaves < nr_leaves_cr; i ++) { if (!reiserfs_bitmap_test_bit (fs->fs_bitmap2, i)) continue; bh = bread (fs->fs_dev, i, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "could not read block %lu\n", i); continue; } if (who_is_this (bh->b_data, bh->b_size) != THE_LEAF) { brelse (bh); continue; } if ((!is_leaf_node (bh)) || (block_of_journal (fs, i))) { brelse (bh); continue; } should_be_corrupted = (unsigned int) get_rand ((double)0, (double)1); if (should_be_corrupted == 0) { brelse (bh); continue; } nr_ih_cr = get_rand (1, get_blkh_nr_items (B_BLK_HEAD (bh))); for (j = 0; j < nr_ih_cr; j ++ ) { should_be_corrupted = (unsigned int) get_rand ((double)0, (double)1); if (should_be_corrupted == 0) continue; if ((data(fs)->log_file_name) && (data(fs)->log)) fprintf (data(fs)->log, "# block %lu , item header %d\n", bh->b_blocknr, j); printf ("# block %lu , item header %d\n", bh->b_blocknr, j); ih = B_N_PITEM_HEAD (bh, j); do_one_ih_random_corrupt (ih); } mark_buffer_dirty (bh); bwrite(bh); brelse (bh); nr_leaves ++ ; } if ((data(fs)->log_file_name) && (data(fs)->log)) fprintf (data(fs)->log, "item headers in %lu leaves WERE corrupted\n", nr_leaves); printf ("item headers in %lu leaves WERE corrupted\n", nr_leaves); reiserfs_close_ondisk_bitmap (fs); } /* corrupt item */ void do_one_item_random_corrupt (struct buffer_head * bh, struct item_head * ih) { unsigned int i; unsigned int from; unsigned int count; char * p; p = (char *)B_I_PITEM(bh, ih); from = get_rand (0, get_ih_item_len(ih) - 1); count = get_rand (1, get_ih_item_len(ih)); if (from + count > get_ih_item_len(ih)) count = get_ih_item_len(ih) - from; for (i = from; i < from + count; i ++) ((char *)p)[i] = get_rand(0, 255); if ((data(fs)->log_file_name) && (data(fs)->log)) fprintf (data(fs)->log, "item body \tfrom %u ( %u )\n", from, count); printf ("item body \tfrom %u ( %u )\n", from, count); return ; } /* corrupt the random number of directory items in random number of leaves */ void do_dir_random_corrupt (reiserfs_filsys_t * fs, unsigned long nr_leaves_cr) { unsigned int nr_ih_cr; int i, j; struct buffer_head * bh; struct item_head * ih; unsigned long nr_leaves = 0; unsigned int should_be_corrupted = 0; srand (time (0)); printf ("DIR items in %lu leaves will be corrupted\n", nr_leaves_cr); if ((data(fs)->log_file_name) && (data(fs)->log)) { fprintf (data(fs)->log, "DIR items in %lu leaves will be corrupted\n", nr_leaves_cr); } if (reiserfs_open_ondisk_bitmap (fs) < 0) reiserfs_panic ("Could not open ondisk bitmap"); for (i = 0; (i < get_sb_block_count (fs->fs_ondisk_sb)) && nr_leaves < nr_leaves_cr; i ++) { if (!reiserfs_bitmap_test_bit (fs->fs_bitmap2, i)) continue; bh = bread (fs->fs_dev, i, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "could not read block %lu\n", i); continue; } if (who_is_this (bh->b_data, bh->b_size) != THE_LEAF) { brelse (bh); continue; } if ((!is_leaf_node (bh)) || (block_of_journal (fs, i))) { brelse (bh); continue; } should_be_corrupted = (unsigned int) get_rand ((double)0, (double)1); if (should_be_corrupted == 0) { brelse (bh); continue; } /* get next item, look is it a DIR */ nr_ih_cr = get_rand (1, get_blkh_nr_items (B_BLK_HEAD (bh))); for (j = 0; j < nr_ih_cr; j ++ ) { should_be_corrupted = (unsigned int) get_rand ((double)0, (double)1); if (should_be_corrupted == 0) continue; if ((data(fs)->log_file_name) && (data(fs)->log)) fprintf (data(fs)->log, "# block %lu , item %d\n", bh->b_blocknr, j); printf ("# block %lu , item %d\n", bh->b_blocknr, j); ih = B_N_PITEM_HEAD (bh, j); if (get_type (&ih->ih_key) != TYPE_DIRENTRY) continue; do_one_item_random_corrupt (bh, ih); } mark_buffer_dirty (bh); bwrite(bh); brelse (bh); nr_leaves ++ ; } if ((data(fs)->log_file_name) && (data(fs)->log)) fprintf (data(fs)->log, "DIR items in %lu leaves WERE corrupted\n", nr_leaves); printf ("DIR items in %lu leaves WERE corrupted\n", nr_leaves); reiserfs_close_ondisk_bitmap (fs); } /* corrupt the random number of stat data items in random number of leaves */ void do_sd_random_corrupt (reiserfs_filsys_t * fs, unsigned long nr_leaves_cr) { unsigned int nr_ih_cr; int i, j; struct buffer_head * bh; struct item_head * ih; unsigned long nr_leaves = 0; unsigned int should_be_corrupted = 0; srand (time (0)); printf ("SD items in %lu leaves will be corrupted\n", nr_leaves_cr); if ((data(fs)->log_file_name) && (data(fs)->log)) { fprintf (data(fs)->log, "SD items in %lu leaves will be corrupted\n", nr_leaves_cr); } if (reiserfs_open_ondisk_bitmap (fs) < 0) reiserfs_panic ("Could not open ondisk bitmap"); for (i = 0; (i < get_sb_block_count (fs->fs_ondisk_sb)) && nr_leaves < nr_leaves_cr; i ++) { if (!reiserfs_bitmap_test_bit (fs->fs_bitmap2, i)) continue; bh = bread (fs->fs_dev, i, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "could not read block %lu\n", i); continue; } if (who_is_this (bh->b_data, bh->b_size) != THE_LEAF) { brelse (bh); continue; } if ((!is_leaf_node (bh)) || (block_of_journal (fs, i))) { brelse (bh); continue; } should_be_corrupted = (unsigned int) get_rand ((double)0, (double)1); if (should_be_corrupted == 0) { brelse (bh); continue; } /* get next item, look is it a SD */ nr_ih_cr = get_rand (1, get_blkh_nr_items (B_BLK_HEAD (bh))); for (j = 0; j < nr_ih_cr; j ++ ) { should_be_corrupted = (unsigned int) get_rand ((double)0, (double)1); if (should_be_corrupted == 0) continue; if ((data(fs)->log_file_name) && (data(fs)->log)) fprintf (data(fs)->log, "# block %lu , item %d\n", bh->b_blocknr, j); printf ("# block %lu , item %d\n", bh->b_blocknr, j); ih = B_N_PITEM_HEAD (bh, j); if (get_type (&ih->ih_key) != TYPE_STAT_DATA) continue; do_one_item_random_corrupt (bh, ih); } mark_buffer_dirty (bh); bwrite(bh); brelse (bh); nr_leaves ++ ; } if ((data(fs)->log_file_name) && (data(fs)->log)) fprintf (data(fs)->log, "SD items in %lu leaves WERE corrupted\n", nr_leaves); printf ("SD items in %lu leaves WERE corrupted\n", nr_leaves); reiserfs_close_ondisk_bitmap (fs); } /* corrupt the random number of indierct items in random number of leaves */ void do_ind_random_corrupt (reiserfs_filsys_t * fs, unsigned long nr_leaves_cr) { unsigned int nr_ih_cr; int i, j; struct buffer_head * bh; struct item_head * ih; unsigned long nr_leaves = 0; unsigned int should_be_corrupted = 0; srand (time (0)); printf ("IND items in %lu leaves will be corrupted\n", nr_leaves_cr); if ((data(fs)->log_file_name) && (data(fs)->log)) { fprintf (data(fs)->log, "IND items in %lu leaves will be corrupted\n", nr_leaves_cr); } if (reiserfs_open_ondisk_bitmap (fs) < 0) reiserfs_panic ("Could not open ondisk bitmap"); for (i = 0; (i < get_sb_block_count (fs->fs_ondisk_sb)) && nr_leaves < nr_leaves_cr; i ++) { if (!reiserfs_bitmap_test_bit (fs->fs_bitmap2, i)) continue; bh = bread (fs->fs_dev, i, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "could not read block %lu\n", i); continue; } if (who_is_this (bh->b_data, bh->b_size) != THE_LEAF) { brelse (bh); continue; } if ((!is_leaf_node (bh)) || (block_of_journal (fs, i))) { brelse (bh); continue; } should_be_corrupted = (unsigned int) get_rand ((double)0, (double)1); if (should_be_corrupted == 0) { brelse (bh); continue; } /* get next item, look is it an IND */ nr_ih_cr = get_rand (1, get_blkh_nr_items (B_BLK_HEAD (bh))); for (j = 0; j < nr_ih_cr; j ++ ) { should_be_corrupted = (unsigned int) get_rand ((double)0, (double)1); if (should_be_corrupted == 0) continue; ih = B_N_PITEM_HEAD (bh, j); if (get_type (&ih->ih_key) != TYPE_INDIRECT) continue; if ((data(fs)->log_file_name) && (data(fs)->log)) fprintf (data(fs)->log, "# block %lu , item %d\n", bh->b_blocknr, j); printf ("# block %lu , item %d\n", bh->b_blocknr, j); do_one_item_random_corrupt (bh, ih); } mark_buffer_dirty (bh); bwrite(bh); brelse (bh); nr_leaves ++ ; } if ((data(fs)->log_file_name) && (data(fs)->log)) fprintf (data(fs)->log, "IND items in %lu leaves WERE corrupted\n", nr_leaves); printf ("IND items in %lu leaves WERE corrupted\n", nr_leaves); reiserfs_close_ondisk_bitmap (fs); } /* this reads list of desired corruptions from stdin and performs the corruptions. Format of that list: B - the random number of bitmap to be corrupted L nr_leaves - block headers in nr_leaves leaves to be corupted H nr_leaves - the random number of item headers in nr_leaves to be corrupted S nr_leaves - the random number of stat data items in nr_leaves to be corrupted D nr_leaves - the random number of directory items in nr_leaves to be corrupted I nr_leaves - the random number of indirect items in nr_leaves to be corrupted */ void what_to_corrupt (reiserfs_filsys_t * fs, char * corruption_command) { unsigned long nr_leaves_cr; char code; switch (corruption_command [0]){ case 'B' : /* bitmap */ do_bitmap_corruption (fs); break; case 'L' : /* leaves */ if (sscanf (corruption_command, "%c %lu\n", &code, &nr_leaves_cr) != 2) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } do_leaves_corruption (fs, nr_leaves_cr); break; case 'H' : /* item headers */ if (sscanf (corruption_command, "%c %lu\n", &code, &nr_leaves_cr) != 2) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } do_ih_random_corrupt (fs, nr_leaves_cr); break; case 'D' : /* directory items */ if (sscanf (corruption_command, "%c %lu\n", &code, &nr_leaves_cr) != 2) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } do_dir_random_corrupt (fs, nr_leaves_cr); break; case 'S' : /* stat data items */ if (sscanf (corruption_command, "%c %lu\n", &code, &nr_leaves_cr) != 2) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } do_sd_random_corrupt (fs, nr_leaves_cr); break; case 'I' : /* indirect items */ if (sscanf (corruption_command, "%c %lu\n", &code, &nr_leaves_cr) != 2) { printf ("Wrong format \'%c\'\n", corruption_command [0]); return; } do_ind_random_corrupt (fs, nr_leaves_cr); break; default : printf ("Unknown command specified\n"); } } void do_fs_random_corrupt (reiserfs_filsys_t * fs) { char * line = 0; size_t n = 0; printf ("Corrupting fs. Please insert one of the following command\n" " B - the random number of bitmap to be corrupted\n" " L nr_leaves - block headers in nr_leaves leaves to be corupted\n" " H nr_leaves - the random number of item headers in nr_leaves to be corrupted\n" " S nr_leaves - the random number of stat data items in nr_leaves to be corrupted\n" " D nr_leaves - the random number of directory items in nr_leaves to be corrupted\n" " I nr_leaves - the random number of indirect items in nr_leaves to be corrupted\n" ".. ->\n"); /* Get list of corruptions from stdin */ while (getline (&line, &n, stdin) != -1) { if ( line [0] == '\n' ) { free (line); line = 0; n = 0; break; } printf ("################## command : %s", line); if ((data(fs)->log_file_name) && (data(fs)->log)) { fprintf (data(fs)->log, "################## command : %s", line); } what_to_corrupt (fs, line); free (line); line = 0; n = 0; } } /* Local variables: c-indentation-style: "K&R" mode-name: "LC" c-basic-offset: 4 tab-width: 4 fill-column: 80 End: */ reiserfsprogs-3.6.9/debugreiserfs/debugreiserfs.80000664000077100007710000000426207705261642015705 .\" -*- nroff -*- .\" Copyright 1996-2003 Hans Reiser. .\" .TH DEBUGREISERFS 8 "April 2003" "Reiserfsprogs 3.6.9" .SH NAME debugreiserfs .SH SYNOPSIS .B debugreiserfs [ .B -dDJmoqpS ] [ .B -j \fIdevice ] [ .B -B \fIblocknumber ] .\" ] [ .\" .B -s .\" ] [ .I device .SH DESCRIPTION It helps sometimes to solve problems with reiserfs filesystems. Being called without options it prints super block of reiserfs filesystem found on the \fIdevice\fR. .TP .I device is the special file corresponding to the device (e.g /dev/hdXX for IDE disk partition or /dev/sdXX for SCSI disk partition). .SH OPTIONS .TP \fB-j\fR \fIdevice\fR print contents of journal. Also with the option -p it allows to pack journal into archive with other metadata .TP \fB-J\fR print journal header. .TP .B -d print formatted nodes of the internal tree of the filesystem .TP .B -D print formatted nodes of all used blocks of the filesystem .TP .B -m print contents of bitmap (not very useful) .TP .B -o print objectid map (not very useful) .TP \fB-1\fR \fIblocknumber\fR print specified block of the filesystem .TP .\" \fB-s .\" scans the partition and prints a line when any kind of reiserfs .\" formatted nodes found. Can be used to find specific key in the filesystem. .\" .TP .B -p Makes \fBdebugreiserfs\fR to find filesystem metadata This option exists to help reiserfsck debugging. If reiserfsck fails - you may extract filesystem metadata with \fBdebugreiserfs\fR -p /dev/xxx |gzip -c > xxx.gz. We download that data and make the filesystem similar to your with gunzip -c xxx.gz | unpack /dev/xxx (unpack is included into reiserfsprogs package). This usually allows to reproduce and debug the problem quickly. When data file is not too large. .TP .B -S When -S is not specified -p .\" and -s deals with blocks marked used in the filesystem bitmap. With this option set they will work with whole device. .TP .B -q Suppress showing speed of progress when .\" -s or -p is in use .SH AUTHOR This version of \fBdebugreiserfs\fR has been written by Hans Reiser . .SH BUGS There are probably few of them. Please, report bugs to ReiserFS mail-list . .SH SEE ALSO .BR reiserfsck (8), .BR mkreiserfs (8) reiserfsprogs-3.6.9/debugreiserfs/debugreiserfs.c0000664000077100007710000004471707705261642015771 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "debugreiserfs.h" reiserfs_filsys_t * fs; #define print_usage_and_exit() {\ fprintf (stderr, "Usage: %s [options] device\n\n\ Options:\n\ -d\t\tprint blocks details of the internal tree\n\ -D\t\tprint blocks details of all used blocks\n\ -m\t\tprint bitmap blocks\n\ -o\t\tprint objectid map\n\n\ -J\t\tprint journal header\n\ -j journal_device\n\t\tprint journal\n\ -p\t\tsend filesystem metadata to stdout\n\ -S\t\thandle all blocks, not only used\n\ -1 block\tblock to print\n\ -q\t\tno speed info (for -p, -s and -n)\n\n", argv[0]);\ exit (16);\ } /* -B file\textract list of badblocks\n\ Undocumented options: -a map_file\n\tstore to the file the map of file. Is used with -n, -N, -r, -f\n -f creates a file map.\n -S\t\tgo through whole device when running -p, -s or -n\n\ -U\t\tgo through unused blocks only when running -p, -s or -n\n\ -D\t\tprint blocks details scanning the device, not the tree as -d does\n\ -b bitmap_file\n\t\trunning -p, -s or -n read blocks marked in this bitmap only\n\ -n\tscan device for specific name in reiserfs directories\n\ -N\tscan tree for specific key in reiserfs directories\n\ -s\tscan device either for specific key or for any metadata\n\ -C\tallow to change reiserfs metadata\n\ -r\tprint map file content.\n\ -J\tsearch block numbers in the journal\n\ -t\tstat the device\n\ */ #if 1 struct reiserfs_fsstat { int nr_internals; int nr_leaves; int nr_files; int nr_directories; int nr_unformatted; } g_stat_info; #endif static void print_disk_tree (reiserfs_filsys_t * fs, unsigned long block_nr) { struct buffer_head * bh; int i, count; static int level = -1; if (level == -1) level = get_sb_tree_height (fs->fs_ondisk_sb); bh = bread (fs->fs_dev, block_nr, fs->fs_blocksize); if (!bh) { die ("Could not read block %lu\n", block_nr); } level --; if (level < 1) die ("level too small"); if (level != get_blkh_level (B_BLK_HEAD (bh))) { printf ("%d expected, %d found in %lu\n", level, get_blkh_level (B_BLK_HEAD (bh)), bh->b_blocknr); } if (is_internal_node (bh)) { struct disk_child * dc; g_stat_info.nr_internals ++; print_block (stdout, fs, bh, data (fs)->options & PRINT_TREE_DETAILS, -1, -1); dc = B_N_CHILD (bh, 0); count = B_NR_ITEMS(bh); for (i = 0; i <= count; i++, dc++) print_disk_tree (fs, get_dc_child_blocknr (dc)); } else if (is_leaf_node (bh)) { struct item_head *ih; g_stat_info.nr_leaves ++; print_block (stdout, fs, bh, data (fs)->options & PRINT_TREE_DETAILS, -1, -1); ih = B_N_PITEM_HEAD (bh, 0); count = leaf_item_number_estimate(bh); for (i = 0; i <= count; i++, ih++) { if (is_indirect_ih(ih)) g_stat_info.nr_unformatted += I_UNFM_NUM(ih); } } else { print_block (stdout, fs, bh, data (fs)->options & PRINT_TREE_DETAILS, -1, -1); reiserfs_warning (stdout, "print_disk_tree: bad block type (%b)\n", bh); } brelse (bh); level ++; } static void print_disk_blocks (reiserfs_filsys_t * fs) { int type; unsigned long done = 0, total; struct buffer_head * bh; unsigned int j; total = reiserfs_bitmap_ones (input_bitmap(fs)); for (j = 0; j < get_sb_block_count (fs->fs_ondisk_sb); j ++) { if (!reiserfs_bitmap_test_bit (input_bitmap (fs), j)) continue; print_how_far (stderr, &done, total, 1, be_quiet (fs)); bh = bread (fs->fs_dev, j, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "could not read block %lu\n", j); continue; } type = who_is_this (bh->b_data, bh->b_size); if (type != THE_UNKNOWN) print_block (stdout, fs, bh, PRINT_TREE_DETAILS | PRINT_DIRECT_ITEMS, -1, -1); if (type == THE_INTERNAL) g_stat_info.nr_internals ++; else if (type == THE_LEAF || type == HAS_IH_ARRAY) g_stat_info.nr_leaves ++; brelse (bh); } fprintf (stderr, "\n"); } void pack_one_block (reiserfs_filsys_t * fs, unsigned long block); static void print_one_block (reiserfs_filsys_t * fs, unsigned long block) { struct buffer_head * bh; if (!fs->fs_bitmap2) { struct buffer_head * bm_bh; unsigned long bm_block; if (spread_bitmaps (fs)) bm_block = ( block / (fs->fs_blocksize * 8) ) ? (block / (fs->fs_blocksize * 8)) * (fs->fs_blocksize * 8) : fs->fs_super_bh->b_blocknr + 1; else bm_block = fs->fs_super_bh->b_blocknr + 1 + (block / (fs->fs_blocksize * 8)); bm_bh = bread (fs->fs_dev, bm_block, fs->fs_blocksize); if (bm_bh) { if ( misc_test_bit((block % (fs->fs_blocksize * 8)), bm_bh->b_data) ) fprintf (stderr, "%lu is used in ondisk bitmap\n", block); else fprintf (stderr, "%lu is free in ondisk bitmap\n", block); brelse (bm_bh); } } else { if (reiserfs_bitmap_test_bit (fs->fs_bitmap2, block)) fprintf (stderr, "%lu is used in ondisk bitmap\n", block); else fprintf (stderr, "%lu is free in ondisk bitmap\n", block); } bh = bread (fs->fs_dev, block, fs->fs_blocksize); if (!bh) { printf ("print_one_block: bread failed\n"); return; } if (debug_mode (fs) == DO_PACK) { pack_one_block (fs, bh->b_blocknr); brelse (bh); return; } if (who_is_this (bh->b_data, bh->b_size) != THE_UNKNOWN) print_block (stdout, fs, bh, PRINT_TREE_DETAILS, -1, -1); else printf ("Looks like unformatted\n"); brelse (bh); return; } /* debugreiserfs -p or -P compresses reiserfs meta data: super block, journal, bitmap blocks and blocks looking like leaves. It may save "bitmap" of blocks they packed in the file of special format. Reiserfsck can then load "bitmap" saved in that file and build the tree of blocks marked used in that "bitmap" */ char * where_to_save; char * badblocks_file; char * corruption_list_file; static char * parse_options (struct debugreiserfs_data * data, int argc, char * argv []) { int c; char * tmp; data->scan_area = USED_BLOCKS; data->mode = DO_DUMP; while ((c = getopt (argc, argv, "a:b:C:F:SU1:psn:Nfr:dDomj:J:qtZl:L")) != EOF) { switch (c) { case 'a': /* -r will read this, -n and -N will write to it */ asprintf (&data->map_file, "%s", optarg); break; case 'b': /* will load bitmap from a file and read only blocks marked in it. This is for -p and -s */ asprintf (&data->input_bitmap, "%s", optarg); data->scan_area = EXTERN_BITMAP; break; case 'S': /* have debugreiserfs -p or -s to read all the device */ data->scan_area = ALL_BLOCKS; break; case 'U': /* have debugreiserfs -p or -s to read unused blocks only */ data->scan_area = UNUSED_BLOCKS; break; case '1': /* print a single node */ data->block = strtol (optarg, &tmp, 0); if (*tmp) die ("parse_options: bad block number"); break; case 'C': data->mode = DO_CORRUPT_ONE; data->block = strtol (optarg, &tmp, 0); if (*tmp) { die ("parse_options: bad block number"); } break; case 'F': data->mode = DO_CORRUPT_FILE; if (asprintf (&corruption_list_file, "%s", optarg) == -1 ) { die ("parse_options: bad list corruption file"); } break; case 'p': data->mode = DO_PACK; break; case 't': data->mode = DO_STAT; break; case 's': /* read the device and print reiserfs blocks which contain defined key */ data->mode = DO_SCAN; break; case 'n': /* scan for names matching a specified pattern */ data->mode = DO_SCAN_FOR_NAME; data->pattern = optarg; /*asprintf (&data->pattern, "%s", optarg);*/ break; case 'N': /* search name in the tree */ data->mode = DO_LOOK_FOR_NAME; break; case 'f': data->mode = DO_FILE_MAP; break; case 'r': asprintf (&data->recovery_file, "%s", optarg); data->mode = DO_RECOVER; break; case 'd': /* print leaf details from internal tree */ data->options |= PRINT_TREE_DETAILS; break; case 'D': /* print leaf details accordingly the bitmap - can be used with -S */ data->options |= PRINT_DETAILS; break; case 'o': /* print objectid map */ data->options |= PRINT_OBJECTID_MAP; break; case 'm': /* print a block map */ case 'M': /* print a block map with details */ data->options |= PRINT_BITMAP; break; case 'j': /* -j must have a parameter */ data->options |= PRINT_JOURNAL; data->journal_device_name = optarg; break; case 'J': data->options |= PRINT_JOURNAL_HEADER; data->journal_device_name = optarg; break; case 'R': /* read block numbers from stdin and look for them in the journal */ data->mode = DO_SCAN_JOURNAL; data->JJ ++; break; case 'B': /*disabled for a while*/ asprintf (&badblocks_file, "%s", optarg); data->mode = DO_EXTRACT_BADBLOCKS; break; case 'q': /* this makes packing to not show speed info during -p or -P */ data->options |= BE_QUIET; break; case 'Z': data->mode = DO_ZERO_BITMAP; break; case 'l': /* --logfile */ data->log_file_name = optarg; data->log = fopen (optarg, "w"); if (!data->log) fprintf (stderr, "debugreiserfs: Cannot not open \'%s\': %s", optarg, strerror(errno)); break; case 'L' : /* random fs corruption */ data->mode = DO_RANDOM_CORRUPTION; break; } } if (optind != argc - 1) /* only one non-option argument is permitted */ print_usage_and_exit(); data->device_name = argv[optind]; return argv[optind]; } void pack_partition (reiserfs_filsys_t * fs); static void do_pack (reiserfs_filsys_t * fs) { if (certain_block (fs)) pack_one_block (fs, certain_block (fs)); else pack_partition (fs); } /* static int comp (const void * vp1, const void * vp2) { const int * p1, * p2; p1 = vp1; p2 = vp2; if (*p1 < *p2) return -1; if (*p1 > *p2) return 1; return 0; } */ static void init_bitmap (reiserfs_filsys_t * fs) { FILE * fp; unsigned long block_count; if (reiserfs_open_ondisk_bitmap (fs) < 0) reiserfs_panic ("Could not open ondisk bitmap"); block_count = get_sb_block_count (fs->fs_ondisk_sb); switch (scan_area (fs)) { case ALL_BLOCKS: input_bitmap (fs) = reiserfs_create_bitmap (block_count); reiserfs_bitmap_fill (input_bitmap (fs)); reiserfs_warning (stderr, "Whole device (%d blocks) is to be scanned\n", reiserfs_bitmap_ones (input_bitmap (fs))); break; case USED_BLOCKS: reiserfs_warning (stderr, "Loading on-disk bitmap .. "); input_bitmap (fs) = reiserfs_create_bitmap (block_count); reiserfs_bitmap_copy (input_bitmap (fs), fs->fs_bitmap2); reiserfs_warning (stderr, "%d bits set - done\n", reiserfs_bitmap_ones (input_bitmap (fs))); break; case UNUSED_BLOCKS: reiserfs_warning (stderr, "Loading on-disk bitmap .. "); input_bitmap (fs) = reiserfs_create_bitmap (block_count); reiserfs_bitmap_copy (input_bitmap (fs), fs->fs_bitmap2); reiserfs_bitmap_invert (input_bitmap (fs)); reiserfs_warning (stderr, "%d bits set - done\n", reiserfs_bitmap_ones (input_bitmap (fs))); break; case EXTERN_BITMAP: fp = fopen (input_bitmap_file_name(fs), "r"); if (!fp) reiserfs_panic ("init_bitmap: could not load bitmap: %m\n"); input_bitmap (fs) = reiserfs_bitmap_load (fp); if (!input_bitmap (fs)) reiserfs_panic ("could not load fitmap from \"%s\"", input_bitmap_file_name(fs)); reiserfs_warning (stderr, "%d blocks marked in the given bitmap\n", reiserfs_bitmap_ones (input_bitmap (fs))); fclose (fp); break; default: reiserfs_panic ("No area to scan specified"); } } /* FIXME: statistics does not work */ static void do_dump_tree (reiserfs_filsys_t * fs) { if (certain_block (fs)) { print_one_block (fs, certain_block (fs)); return; } if (data (fs)->options & PRINT_JOURNAL || data (fs)->options & PRINT_JOURNAL_HEADER) { if (!reiserfs_journal_opened (fs) && reiserfs_open_journal (fs, data (fs)->journal_device_name, O_RDONLY)) { printf ("Could not open journal\n"); return; } } print_filesystem_state (stdout, fs); print_block (stdout, fs, fs->fs_super_bh); if (data (fs)->options & PRINT_JOURNAL) print_journal (fs); if (data (fs)->options & PRINT_JOURNAL_HEADER) print_journal_header (fs); if (data (fs)->options & PRINT_OBJECTID_MAP) print_objectid_map (stdout, fs); if (data (fs)->options & PRINT_BITMAP) print_bmap (stdout, fs, 0/*opt_print_block_map == 1 ? 1 : 0*/); if (data (fs)->options & PRINT_DETAILS) init_bitmap (fs); if (data (fs)->options & PRINT_DETAILS || data (fs)->options & PRINT_TREE_DETAILS) { if (data (fs)->options & PRINT_DETAILS) print_disk_blocks (fs); else print_disk_tree (fs, get_sb_root_block (fs->fs_ondisk_sb)); /* print the statistic */ printf ("File system uses %d internal + %d leaves + %d unformatted nodes = %d blocks\n", g_stat_info.nr_internals, g_stat_info.nr_leaves, g_stat_info.nr_unformatted, g_stat_info.nr_internals + g_stat_info.nr_leaves + g_stat_info.nr_unformatted); } } void extract_badblock_list () { FILE * fd; struct key badblock_key = {-1, -1, {{0, 0}}}; struct key * rdkey; struct path badblock_path; struct item_head * tmp_ih; __u32 i; __u32 * ind_item; fd = fopen (badblocks_file, "w"); if (fd == NULL) { reiserfs_warning (stderr, "debugreiserfs: could not open badblock file %s\n", badblocks_file); exit (1); } badblock_path.path_length = ILLEGAL_PATH_ELEMENT_OFFSET; set_type_and_offset (KEY_FORMAT_2, &badblock_key, 1, TYPE_INDIRECT); while (1) { reiserfs_search_by_key_4 (fs, &badblock_key, &badblock_path); if (get_blkh_nr_items ( B_BLK_HEAD (get_bh(&badblock_path))) <= PATH_LAST_POSITION (&badblock_path)) { break; } tmp_ih = get_ih(&badblock_path); if (get_key_dirid(&tmp_ih->ih_key) != (__u32)-1 || get_key_objectid(&tmp_ih->ih_key) != (__u32)-1) { break; } /* even if offset or type are corrupted it could be a badblock list */ if (!is_indirect_ih (tmp_ih)) { reiserfs_warning (stderr, "$s: a badblock item which was found has a wrong type.\n" " It probable contains not correct bad block list, check it.\n", __FUNCTION__); } ind_item = (__u32 *)B_I_PITEM (get_bh (&badblock_path), tmp_ih); for (i = 0; i < get_ih_item_len (tmp_ih) / UNFM_P_SIZE; i++, ind_item++) fprintf (fd, "%u\n", le32_to_cpu (*ind_item)); if ((rdkey = get_next_key_2 (&badblock_path)) == NULL) break; else badblock_key = *rdkey; pathrelse (&badblock_path); } pathrelse (&badblock_path); fclose (fd); } static int str2int (char * str, int * res) { int val; char * tmp; val = (int) strtol (str, &tmp, 0); if (tmp == str) /* could not convert string into a number */ return 0; *res = val; return 1; } void do_corrupt_blocks (reiserfs_filsys_t * fs) { char * line; FILE * fd; size_t n = 0; int numblock; fd = fopen (corruption_list_file, "r"); if (fd == NULL) { reiserfs_warning (stderr, "debugreiserfs: could not open corruption_list_file %s\n", corruption_list_file); exit (1); } while (1) { line = NULL; n = 0; if (getline (&line, &n, fd) == -1) { break; } /* remove '\n' */ line [strlen (line) - 1] = '\0'; if (str2int(line, &numblock)) { data (fs)->block = (unsigned long) numblock; } else { do_corrupt_one_block(fs, line); } printf ("before free line : %s\n", line); free (line); printf ("after free\n"); reiserfs_reopen (fs, O_RDWR); } fclose (fd); return; } void zero_bitmap_blocks(reiserfs_filsys_t * fs) { unsigned long done, total, i; struct buffer_head * bh; reiserfs_reopen (fs, O_RDWR); total = reiserfs_bitmap_ones (input_bitmap (fs)); done = 0; for (i = 0; i < input_bitmap(fs)->bm_bit_size; i ++) { if (!reiserfs_bitmap_test_bit (input_bitmap(fs), i)) continue; bh = getblk(fs->fs_dev, i, fs->fs_blocksize); if (!bh) die("Could not get block %lu\n", i); memset(bh->b_data, 0, fs->fs_blocksize); mark_buffer_dirty(bh); mark_buffer_uptodate(bh, 0); bwrite(bh); brelse (bh); print_how_far (stderr, &done, total, 1, be_quiet (fs)); } fprintf(stderr, "\n"); fflush(stderr); } /* FIXME: need to open reiserfs filesystem first */ int main (int argc, char * argv[]) { char * file_name; int error; struct debugreiserfs_data * data; print_banner ("debugreiserfs"); data = getmem (sizeof (struct debugreiserfs_data)); file_name = parse_options (data, argc, argv); fs = reiserfs_open (file_name, O_RDONLY, &error, data, 0); if (no_reiserfs_found (fs)) { fprintf (stderr, "\n\ndebugreiserfs: can not open reiserfs on \"%s\": %s\n\n", file_name, error ? strerror (error) : "no filesystem found"); exit(1) ; } if (reiserfs_open_journal (fs, data (fs)->journal_device_name, O_RDONLY)) { fprintf(stderr, "\ndebugreiserfs: Failed to open the fs journal.\n"); exit(1); } switch (debug_mode (fs)) { case DO_STAT: init_bitmap (fs); do_stat (fs); break; case DO_PACK: init_bitmap (fs); do_pack (fs); break; case DO_CORRUPT_ONE: reiserfs_reopen (fs, O_RDWR); do_corrupt_one_block (fs, (char *)NULL); break; case DO_CORRUPT_FILE: reiserfs_reopen (fs, O_RDWR); do_corrupt_blocks (fs); break; case DO_RANDOM_CORRUPTION: reiserfs_reopen (fs, O_RDWR); /* do_leaves_corruption (fs); do_bitmap_corruption (fs); */ do_fs_random_corrupt (fs); break; case DO_DUMP: do_dump_tree (fs); break; case DO_SCAN: case DO_SCAN_FOR_NAME: case DO_LOOK_FOR_NAME: case DO_SCAN_JOURNAL: init_bitmap (fs); do_scan (fs); break; case DO_FILE_MAP: print_map(fs); break; case DO_RECOVER: do_recover (fs); break; case DO_TEST: /*do_test (fs);*/ break; case DO_EXTRACT_BADBLOCKS: reiserfs_warning (stderr, "Will try to extract list of bad blocks and save it to '%s' file\n", badblocks_file); extract_badblock_list (); reiserfs_warning (stderr, "Done\n\n"); break; } reiserfs_close (fs); if (data(fs)->log) { fclose (data(fs)->log); } return 0; } /* Local variables: c-indentation-style: "K&R" mode-name: "LC" c-basic-offset: 4 tab-width: 4 fill-column: 80 End: */ reiserfsprogs-3.6.9/debugreiserfs/debugreiserfs.h0000664000077100007710000001751107705261642015766 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "io.h" #include "misc.h" #include "reiserfs_lib.h" #include "../include/config.h" #include "../version.h" extern reiserfs_filsys_t * fs; /* * modes */ #define DO_DUMP 1 /* not a real dump, just printing to stdout contents of tree nodes */ #define DO_CORRUPT_ONE 2 /* used to make filesystem corruption and then test fsck */ #define DO_CORRUPT_FILE 3 /* used to make filesystem corruption and then test fsck, the list of corruption is set on the file */ #define DO_RANDOM_CORRUPTION 4 #define DO_SCAN 5 #define DO_RECOVER 6 #define DO_TEST 7 #define DO_PACK 8 /* -p extract meta data of reiserfs filesystem */ #define DO_STAT 9 #define DO_SCAN_FOR_NAME 10 /* -n */ #define DO_LOOK_FOR_NAME 11 /* -N */ #define DO_SCAN_JOURNAL 12 /* -J */ #define DO_EXTRACT_BADBLOCKS 13 #define DO_FILE_MAP 14 #define DO_ZERO_BITMAP 15 /*first bits are in reiserfs_fs.b*/ #define PRINT_JOURNAL 0x10 #define PRINT_JOURNAL_HEADER 0x20 #define PRINT_BITMAP 0x40 #define PRINT_OBJECTID_MAP 0x80 #define BE_QUIET 0x100 /* these moved to reiserfs_fs.h */ //#define PRINT_TREE_DETAILS //#define PRINT_DETAILS //#define PRINT_ITEM_DETAILS //#define PRINT_DIRECT_ITEMS // the leaf is stored in compact form: // start magic number // block number __u32 // item number __u16 // struct packed_item // .. // end magic number /* we store hash code in high byte of 16 bits */ #define LEAF_START_MAGIC 0xa6 #define LEAF_END_MAGIC 0x5a #define FULL_BLOCK_START_MAGIC 0xb6 #define FULL_BLOCK_END_MAGIC 0x6b #define UNFORMATTED_BITMAP_START_MAGIC 0xc7 #define UNFORMATTED_BITMAP_END_MAGIC 0x7c #define END_MAGIC 0x8d #define INTERNAL_START_MAGIC #define INTERNAL_START_MAGIC #define SEPARATED_JOURNAL_START_MAGIC 0xf8 #define SEPARATED_JOURNAL_END_MAGIC 0x8f #define ITEM_START_MAGIC 0x476576 #define ITEM_END_MAGIC 0x2906504 #define MAP_MAGIC 0xe9 #define MAP_END_MAGIC 0x9e /* 12 bits of mask are used to define */ #define NEW_FORMAT 0x01 /* 1. 0 here means - old format, 1 - new format */ #define DIR_ID 0x02 /* 2. dir_id is stored */ #define OBJECT_ID 0x04 /* 3. objectid is stored */ #define OFFSET_BITS_32 0x08 /* 4. offset is stored as 32 bit */ #define OFFSET_BITS_64 0x10 /* 5. offset is stored as 64 bit */ #define IH_ENTRY_COUNT 0x20 /* 6. ih_free_space/ih_entry_count is stored */ #define IH_FREE_SPACE 0x20 #define IH_FORMAT 0x40 /* 7. ih_format is stored */ #define WITH_SD_FIRST_DIRECT_BYTE 0x80 /* 8. for old stat data first_direct_byte is stored */ #define NLINK_BITS_32 0x0100 /* 9. nlinks stored in 32 bits */ #define SIZE_BITS_64 0x0200 /* 10. size has to be stored in 64 bit */ #define WHOLE_INDIRECT 0x0400 /* 11. indirect item is stored with compression */ #define SAFE_LINK 0x0800 /* 11. indirect item is stored with compression */ #define TYPE_MASK 0x3 /* two lowest bits are used to store item type */ //#define MASK_MASK 0xffffc /* what is packed: dirid, objectid, etc */ #define ITEM_LEN_MASK 0xfff00000 /* contents of ih_item_len of item_head */ struct packed_item { __u32 type_2_mask_18_len_12; }; /* defined as inlines in both pack.c and unpack.c */ inline void set_pi_type( struct packed_item *pi, __u32 val ); inline __u32 get_pi_type( const struct packed_item *pi ); inline void set_pi_mask( struct packed_item *pi, __u32 val ); inline __u32 get_pi_mask( const struct packed_item *pi ); inline void set_pi_item_len( struct packed_item *pi, __u32 val ); inline __u32 get_pi_item_len( const struct packed_item *pi ); #define HAS_DIR_ID 0x01 #define HAS_GEN_COUNTER 0x02 #define HAS_STATE 0x04 #define YURA 0x08 #define TEA 0x10 #define R5 0x20 struct packed_dir_entry { __u8 mask; __u16 entrylen; }; /* packed_dir_entry.mask is *always* endian safe, since it's 8 bit */ #define get_pe_entrylen(pe) (le16_to_cpu((pe)->entrylen)) #define set_pe_entrylen(pe,v) ((pe)->entrylen = cpu_to_le16(v)) #define fread8(pv) fread (pv, sizeof (__u8), 1, stdin) #define fread_le16(pv)\ {\ __u16 tmp; \ fread16(&tmp); \ *pv = le16_to_cpu(tmp); \ } #define fread_le32(pv)\ {\ __u32 tmp; \ fread32(&tmp); \ *pv = le32_to_cpu(tmp); \ } #define fread_le64(pv)\ {\ __u64 tmp; \ fread64(&tmp); \ *pv = le64_to_cpu(tmp); \ } #define fread8(pv) fread (pv, sizeof (__u8), 1, stdin) #define fread16(pv) fread (pv, sizeof (__u16), 1, stdin) #define fread32(pv) fread (pv, sizeof (__u32), 1, stdin) #define fread64(pv) fread (pv, sizeof (__u64), 1, stdin) #define fwrite_le16(pv)\ {\ __u16 tmp = cpu_to_le16(*(pv));\ fwrite16(&tmp);\ } #define fwrite_le32(pv)\ {\ __u32 tmp = cpu_to_le32(*(pv));\ fwrite32(&tmp);\ } #define fwrite_le64(pv)\ {\ __u64 tmp = cpu_to_le64(*(pv));\ fwrite64(&tmp);\ } #define fwrite8(pv) {\ if (fwrite (pv, sizeof (__u8), 1, stdout) != 1)\ reiserfs_panic ("fwrite8 failed: %m");\ sent_bytes ++;\ } #define fwrite16(pv) {\ if (fwrite (pv, sizeof (__u16), 1, stdout) != 1)\ reiserfs_panic ("fwrite16 failed: %m");\ sent_bytes += 2;\ } #define fwrite32(pv) {\ if (fwrite (pv, sizeof (__u32), 1, stdout) != 1)\ reiserfs_panic ("fwrite32 failed: %m");\ sent_bytes += 4;\ } #define fwrite64(pv) {\ if (fwrite (pv, sizeof (__u64), 1, stdout) != 1)\ reiserfs_panic ("fwrite64 failed: %m");\ sent_bytes += 8;\ } struct debugreiserfs_data { int mode; /* DO_DUMP | DO_PACK | DO_CORRUPT_ONE... */ #define USED_BLOCKS 1 #define EXTERN_BITMAP 2 #define ALL_BLOCKS 3 #define UNUSED_BLOCKS 4 int scan_area; /* for -p, -s and -n */ char * input_bitmap; /* when ->scan_area is set to EXTERN_BITMAP */ reiserfs_bitmap_t * bitmap; /* bitmap is read from ->input_bitmap */ unsigned long block; /* set by -B. this is a must for -C, option for -p and -d */ char * pattern; /* for -n */ char * device_name; char * journal_device_name; /* for -j */ char * map_file; /* for -n, -N and -f */ char * recovery_file; /* for -r */ unsigned long options; /* -q only yet*/ int JJ; /* log file name and handle */ char * log_file_name; FILE * log ; }; #define data(fs) ((struct debugreiserfs_data *)((fs)->fs_vp)) #define debug_mode(fs) (data(fs)->mode) #define certain_block(fs) (data(fs)->block) #define input_bitmap(fs) (data(fs)->bitmap) #define input_bitmap_file_name(fs) (data(fs)->input_bitmap) #define scan_area(fs) (data(fs)->scan_area) #define name_pattern(fs) (data(fs)->pattern) #define device_name(fs) (data(fs)->device_name) #define journal_device_name(fs) (data(fs)->journal_device_name) #define map_file(fs) (data(fs)->map_file) #define recovery_file(fs) (data(fs)->recovery_file) #define be_quiet(fs) (data(fs)->options & BE_QUIET) /* stat.c */ void do_stat (reiserfs_filsys_t * fs); /* corruption.c */ void do_corrupt_one_block (reiserfs_filsys_t * fs, char * fline); void do_leaves_corruption (reiserfs_filsys_t * fs, unsigned long nr_leaves_cr); void do_bitmap_corruption (reiserfs_filsys_t * fs); void do_fs_random_corrupt (reiserfs_filsys_t * fs); /* recover.c */ void do_recover (reiserfs_filsys_t * fs); /* scan.c */ void do_scan (reiserfs_filsys_t * fs); /* journal.c */ void scan_journal (reiserfs_filsys_t * fs); void print_map(reiserfs_filsys_t * fs); struct saved_item { struct item_head si_ih; unsigned long si_block; int si_item_num; struct saved_item * si_next; /* list of items having the same key */ }; /* Local variables: c-indentation-style: "K&R" mode-name: "LC" c-basic-offset: 4 tab-width: 4 fill-column: 80 End: */ reiserfsprogs-3.6.9/AUTHORS0000664000077100007710000000000007665645672011202 reiserfsprogs-3.6.9/INSTALL0000664000077100007710000001722707665645672011206 Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. reiserfsprogs-3.6.9/resize_reiserfs/0000777000077100007710000000000007705315454013414 5reiserfsprogs-3.6.9/resize_reiserfs/fe.c0000664000077100007710000000160107665645673014104 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "resize.h" /* the front-end for kernel on-line resizer */ int resize_fs_online(char * devname, unsigned long blocks) { static char buf[40]; FILE * f; struct mntent * mnt; if ((f = setmntent (MOUNTED, "r")) == NULL) goto fail; while ((mnt = getmntent (f)) != NULL) if(strcmp(devname, mnt->mnt_fsname) == 0) { if (strcmp(mnt->mnt_type,"reiserfs")) die ("resize_reiserfs: can\'t resize fs other than reiserfs\n"); sprintf(buf,"resize=%lu", blocks); if (mount(mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, (unsigned long)(MS_MGC_VAL | MS_REMOUNT), buf)) die ("resize_reiserfs: remount failed: %s\n", strerror(errno)); endmntent(f); return 0; } fail: die ("resize_reiserfs: can't find mount entry\n"); return 1; } reiserfsprogs-3.6.9/resize_reiserfs/resize.h0000664000077100007710000000202607665645673015022 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #if __GLIBC__ >= 2 #include #else #include #endif #include "io.h" #include "misc.h" #include "reiserfs_lib.h" #include "../include/config.h" #include "../version.h" #define print_usage_and_exit() {\ fprintf (stderr, "Usage: %s [-s[+|-]#[G|M|K]] [-fqv] device\n\n", argv[0]);\ exit(16);\ } #define DIE(form, args...) die("%s: " form "\n", g_progname , ## args) /* reiserfs_resize.c */ extern struct buffer_head * g_sb_bh; extern char * g_progname; extern int opt_force; extern int opt_verbose; extern int opt_nowrite; extern int opt_safe; /* fe.c */ int resize_fs_online(char * devname, unsigned long blocks); /* do_shrink.c */ int shrink_fs(reiserfs_filsys_t *, unsigned long blocks); reiserfsprogs-3.6.9/resize_reiserfs/resize_reiserfs.80000664000077100007710000000554207705261642016633 .\" -*- nroff -*- .\" Copyright 1996-2003 Hans Reiser. .\" .TH RESIZE_REISERFS 8 "April 2003" "Reiserfsprogs-3.6.9" .SH NAME resize_reiserfs \- Reiserfs filesystem resizer .SH SYNOPSIS .BR resize_reiserfs [ .B \-s .IR \fR[\fB+\fR|\fB\- ]\fIsize\fB[\fBK\fR|\fBM\fR|\fBG\fR] ] [ .B \-j .IR \fR\fIdev ] [ .B \-fqv ] .I device .SH DESCRIPTION The .B resize_reiserfs tool resizes an unmounted reiserfs file system. It enlarges or shrinks an reiserfs file system located on a .I device so that it will have .I size bytes or size=old_size +(\-) .I size bytes if the + or \- prefix is used. If the .B \-s option is not specified, the filesystem will be resized to fill the given device. The .I size parameter may have one of the optional modifiers .BR K ", " M ", " G , which means the .I size parameter is given in kilo\-, mega\-, gigabytes respectively. .PP The .B resize_reiserfs program does not manipulate the size of the device. If you wish to enlarge a filesystem, you must make sure you expand the underlying device first. This can be done using .BR cfdisk (8) for partitions, by deleting the partition and recreating it with a larger size (assuming there is free space .I after the partition in question). Make sure you re\-create it with the same starting disk cylinder as before! Otherwise, the resize operation will certainly not work, and you may lose your entire filesystem. .PP The .B resize_reiserfs program allows to grow a reiserfs on-line if there is a free space on block .I device. .PP If you wish to shrink an reiserfs partition, first use .B resize_reiserfs to shrink the file system. You may then use .BR cfdisk (8) to shrink the device. When shrinking the size of the device, make sure you do not make it smaller than the reduced size of the reiserfs filesystem. .SH OPTIONS .TP .BR \-s\ [+|\-]\fIsize Set the new size in bytes. .TP .BR \-j\ \fIdev Set the journal device name. .TP .BR \-f Force, do not perform checks. .TP .BR \-q Do not print anything but error messages. .TP .BR \-v Turn on extra progress status messages (default). .SH RETURN VALUES 0 Resizing successful. .TP \-1 In another case. .SH EXAMPLES The following example shows how to test .B resize_reiserfs\fR. Suppose 2Gb reiserfs filesystem is created on the device /dev/hda8 and is mounted on /mnt. For shrinking the device we need to unmount it first, then run .B resize_reiserfs with a .I size \fR parameter (in this case -1Gb): .PP \ df .br \ umount /mnt .br \ resize_reiserfs -s -1G /dev/hda8 .br \ mount /dev/hda8 /mnt .br \ df /mnt .SH WARNING Note that this is a BETA program and may corrupt filesystems. .SH AUTHOR This version of .B resize_reiserfs has been written by Alexander Zarochentcev . .SH BUGS Please, report about the bugs to Alexander Zarochentcev or to Hans Reiser . .SH SEE ALSO .BR cfdisk (8), .BR reiserfsck (8), .BR debugreiserfs (8) reiserfsprogs-3.6.9/resize_reiserfs/resize_reiserfs.c0000664000077100007710000001667307705261642016715 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ /* * Written by Alexander Zarochentcev. * * FS resize utility * */ #include "resize.h" #include int opt_force = 0; int opt_verbose = 1; /* now "verbose" option is default */ int opt_nowrite = 0; int opt_safe = 0; int opt_skipj = 0; char * g_progname; /* calculate the new fs size (in blocks) from old fs size and the string representation of new size */ static unsigned long calc_new_fs_size(unsigned long count, int bs, char *bytes_str) { long long int bytes; unsigned long blocks; int c; bytes = atoll(bytes_str); c = bytes_str[strlen(bytes_str) - 1]; switch (c) { case 'G': case 'g': bytes *= 1024; case 'M': case 'm': bytes *= 1024; case 'K': case 'k': bytes *= 1024; } blocks = bytes / bs; if (bytes_str[0] == '+' || bytes_str[0] == '-') return (count + blocks); return blocks; } /* print some fs parameters */ static void sb_report(struct reiserfs_super_block * sb1, struct reiserfs_super_block * sb2) { printf( "ReiserFS report:\n" "blocksize %d\n" "block count %d (%d)\n" "free blocks %d (%d)\n" "bitmap block count %d (%d)\n", get_sb_block_size(sb1), get_sb_block_count(sb1), get_sb_block_count(sb2), get_sb_free_blocks(sb1), get_sb_free_blocks(sb2), get_sb_bmap_nr(sb1), get_sb_bmap_nr(sb2)); }; /* conditional bwrite */ static int bwrite_cond (struct buffer_head * bh) { if(!opt_nowrite) { mark_buffer_uptodate(bh,1); mark_buffer_dirty(bh); bwrite(bh); } return 0; } /* the first one of the most important functions */ static int expand_fs (reiserfs_filsys_t * fs, unsigned long block_count_new) { unsigned int bmap_nr_new, bmap_nr_old; struct reiserfs_super_block * sb; unsigned int i; reiserfs_reopen(fs, O_RDWR); if (reiserfs_open_ondisk_bitmap (fs)) DIE("cannot open ondisk bitmap"); sb = fs->fs_ondisk_sb; set_sb_fs_state (fs->fs_ondisk_sb, FS_ERROR); bwrite_cond(fs->fs_super_bh); if (reiserfs_expand_bitmap(fs->fs_bitmap2, block_count_new)) DIE("cannot expand bitmap\n"); /* count bitmap blocks in new fs */ bmap_nr_new = (block_count_new - 1) / (fs->fs_blocksize * 8) + 1; bmap_nr_old = get_sb_bmap_nr(sb); /* update super block buffer*/ set_sb_free_blocks (sb, get_sb_free_blocks(sb) + (block_count_new - get_sb_block_count(sb)) - (bmap_nr_new - bmap_nr_old)); set_sb_block_count (sb, block_count_new); set_sb_bmap_nr (sb, bmap_nr_new); /* mark new bitmap blocks as used */ for (i = bmap_nr_old; i < bmap_nr_new; i++) reiserfs_bitmap_set_bit (fs->fs_bitmap2, i * fs->fs_blocksize * 8); /* normally, this is done by reiserfs_bitmap_set_bit, but if we ** haven't actually added any bitmap blocks, the bitmap won't be dirtied. ** ** In memory, reiserfsprogs puts zeros for the bits past the end of ** the old filesystem. But, on disk that bitmap is full of ones. ** we explicitly dirty the bitmap here to make sure the zeros get written ** to disk */ fs->fs_bitmap2->bm_dirty = 1 ; return 0; } int main(int argc, char *argv[]) { char * bytes_count_str = NULL; char * devname; char * jdevice_name = NULL; reiserfs_filsys_t * fs; struct reiserfs_super_block * sb; int c; int error; struct reiserfs_super_block *sb_old; unsigned long block_count_new; g_progname = basename(argv[0]); print_banner (g_progname); while ((c = getopt(argc, argv, "fvcqks:j:")) != EOF) { switch (c) { case 's' : if (!optarg) DIE("Missing argument to -s option"); bytes_count_str = optarg; break; case 'j' : if (!optarg) DIE("Missing argument to -j option"); jdevice_name = optarg; case 'f': opt_force = 1; break; case 'v': opt_verbose++; break; case 'n': /* no nowrite option at this moment */ /* opt_nowrite = 1; */ break; case 'c': opt_safe = 1; break; case 'q': opt_verbose = 0; break; case 'k': opt_skipj = 1; break; default: print_usage_and_exit (); } } if (optind == argc ) print_usage_and_exit(); devname = argv[optind]; fs = reiserfs_open(devname, O_RDONLY, &error, 0, 1); if (!fs) DIE ("cannot open '%s': %s", devname, strerror(error)); if (reiserfs_open_journal (fs, jdevice_name, O_RDWR | O_LARGEFILE)) DIE ("Failed to open the journal device (%s).", jdevice_name); if (reiserfs_journal_params_check(fs)) { if (!opt_skipj) DIE ("Wrong journal parameters detected on (%s)", jdevice_name); else reiserfs_close_journal(fs); } /* forced to continue without journal available/specified */ if (no_reiserfs_found (fs)) { DIE ("no reiserfs found on the device."); } if (!spread_bitmaps (fs)) { DIE ("cannot resize reiserfs in old (not spread bitmap) format."); } sb = fs->fs_ondisk_sb; if(bytes_count_str) { /* new fs size is specified by user */ block_count_new = calc_new_fs_size(get_sb_block_count(sb), fs->fs_blocksize, bytes_count_str); } else { /* use whole device */ block_count_new = count_blocks(devname, fs->fs_blocksize); } if (is_mounted (devname)) { reiserfs_close(fs); if ((error = resize_fs_online(devname, block_count_new))) reiserfs_warning(stderr, "\n\nresize_reiserfs: On-line resizing " "failed.\n\n "); else reiserfs_warning(stderr, "\n\nresize_reiserfs: On-line resizing " "finished successfully.\n\n "); return error; } if (!reiserfs_is_fs_consistent (fs)) { reiserfs_warning (stderr, "\n\nresize_reiserfs: run reiserfsck --check " "first\n\n"); reiserfs_close (fs); return 1; } if (get_sb_umount_state(sb) != FS_CLEANLY_UMOUNTED) /* fixme: shouldn't we check for something like: fsck guarantees: fs is ok */ DIE ("the file system isn't in valid state."); if (block_count_new >= get_sb_block_count(sb)) { if (block_count_new == get_sb_block_count(sb)) { reiserfs_warning (stderr, "%s already is of the needed size. " "Nothing to be done\n\n", devname); exit (1); } if(!valid_offset(fs->fs_dev, (loff_t)block_count_new * fs->fs_blocksize - 1)) { reiserfs_warning (stderr, "%s is of %lu blocks size only with " "reiserfs of %d blocks\nsize on it. You are trying to expand " "reiserfs up to %lu blocks size.\nYou probably forgot to " "expand your partition size.\n\n", devname, count_blocks(devname, fs->fs_blocksize), get_sb_block_count(sb), block_count_new); exit (1); } } /* Needed to keep idiot compiler from issuing false warning */ sb_old = 0; /* save SB for reporting */ if(opt_verbose) { sb_old = getmem(SB_SIZE); memcpy(sb_old, fs->fs_ondisk_sb, SB_SIZE); } error = (block_count_new > get_sb_block_count(fs->fs_ondisk_sb)) ? expand_fs(fs, block_count_new) : shrink_fs(fs, block_count_new); if (error) { reiserfs_warning(stderr, "\n\nresize_reiserfs: Resizing failed.\n\n "); return error; } if(opt_verbose) { sb_report(fs->fs_ondisk_sb, sb_old); freemem(sb_old); } set_sb_fs_state (fs->fs_ondisk_sb, FS_CONSISTENT); bwrite_cond(fs->fs_super_bh); if (opt_verbose) { printf("\nSyncing.."); fflush(stdout); } reiserfs_close (fs); if (opt_verbose) printf("done\n"); reiserfs_warning(stderr, "\n\nresize_reiserfs: Resizing finished " "successfully.\n\n "); return 0; } reiserfsprogs-3.6.9/resize_reiserfs/Makefile.am0000664000077100007710000000035007665645673015402 sbin_PROGRAMS = resize_reiserfs resize_reiserfs_SOURCES = fe.c resize_reiserfs.c do_shrink.c resize.h man_MANS = resize_reiserfs.8 EXTRA_DIST = $(man_MANS) LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a reiserfsprogs-3.6.9/resize_reiserfs/Makefile.in0000644000077100007710000003305307705315226015376 # Makefile.in generated by automake 1.7.2 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__quote = @am__quote@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ sbin_PROGRAMS = resize_reiserfs resize_reiserfs_SOURCES = fe.c resize_reiserfs.c do_shrink.c resize.h man_MANS = resize_reiserfs.8 EXTRA_DIST = $(man_MANS) LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a subdir = resize_reiserfs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = sbin_PROGRAMS = resize_reiserfs$(EXEEXT) PROGRAMS = $(sbin_PROGRAMS) am_resize_reiserfs_OBJECTS = fe.$(OBJEXT) resize_reiserfs.$(OBJEXT) \ do_shrink.$(OBJEXT) resize_reiserfs_OBJECTS = $(am_resize_reiserfs_OBJECTS) resize_reiserfs_LDADD = $(LDADD) resize_reiserfs_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \ $(top_srcdir)/reiserfscore/libcore.a resize_reiserfs_LDFLAGS = DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/do_shrink.Po ./$(DEPDIR)/fe.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/resize_reiserfs.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(resize_reiserfs_SOURCES) NROFF = nroff MANS = $(man_MANS) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(resize_reiserfs_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu resize_reiserfs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(sbindir) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f || exit 1; \ else :; fi; \ done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ rm -f $(DESTDIR)$(sbindir)/$$f; \ done clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) resize_reiserfs$(EXEEXT): $(resize_reiserfs_OBJECTS) $(resize_reiserfs_DEPENDENCIES) @rm -f resize_reiserfs$(EXEEXT) $(LINK) $(resize_reiserfs_LDFLAGS) $(resize_reiserfs_OBJECTS) $(resize_reiserfs_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/do_shrink.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resize_reiserfs.Po@am__quote@ distclean-depend: -rm -rf ./$(DEPDIR) .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: man8dir = $(mandir)/man8 install-man8: $(man8_MANS) $(man_MANS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(man8dir) @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.8*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ *) ext='8' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ done uninstall-man8: @$(NORMAL_UNINSTALL) @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.8*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ *) ext='8' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ rm -f $(DESTDIR)$(man8dir)/$$inst; \ done ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) installdirs: $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(man8dir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-man install-exec-am: install-sbinPROGRAMS install-info: install-info-am install-man: install-man8 installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am uninstall-man uninstall-sbinPROGRAMS uninstall-man: uninstall-man8 .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-sbinPROGRAMS ctags distclean distclean-compile \ distclean-depend distclean-generic distclean-tags distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-man8 install-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-info-am uninstall-man \ uninstall-man8 uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: reiserfsprogs-3.6.9/resize_reiserfs/do_shrink.c0000664000077100007710000001617507705261642015467 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "resize.h" #include static unsigned long int_node_cnt = 0, int_moved_cnt = 0; static unsigned long leaf_node_cnt = 0, leaf_moved_cnt = 0; static unsigned long unfm_node_cnt = 0, unfm_moved_cnt = 0; static unsigned long total_node_cnt = 0; static unsigned long total_moved_cnt = 0; static unsigned long unused_block; static unsigned long blocks_used; static int block_count_mismatch = 0; static reiserfs_bitmap_t * bmp; static struct reiserfs_super_block * ondisk_sb; /* abnornal exit from block reallocation process */ static void quit_resizer(reiserfs_filsys_t * fs) { /* save changes to bitmap blocks */ reiserfs_close (fs); /* leave fs in ERROR state */ DIE ("fs shrinking was not completed successfully, run reiserfsck."); } /* block moving */ static unsigned long move_generic_block(reiserfs_filsys_t * fs, unsigned long block, unsigned long bnd, int h) { struct buffer_head * bh, * bh2; /* primitive fsck */ if (block > get_sb_block_count(ondisk_sb)) { fprintf(stderr, "resize_reiserfs: invalid block number (%lu) found.\n", block); quit_resizer(fs); } /* progress bar, 3D style :) */ if (opt_verbose) print_how_far(stderr, &total_node_cnt, blocks_used, 1, 0); else total_node_cnt ++; /* infinite loop check */ if( total_node_cnt > blocks_used && !block_count_mismatch) { fputs("resize_reiserfs: warning: block count exeeded\n",stderr); block_count_mismatch = 1; } if (block < bnd) /* block will not be moved */ return 0; /* move wrong block */ bh = bread(fs->fs_dev, block, fs->fs_blocksize); if (!bh) reiserfs_panic ("move_generic_block: bread failed.\n"); reiserfs_bitmap_find_zero_bit(bmp, &unused_block); if (unused_block == 0 || unused_block >= bnd) { fputs ("resize_reiserfs: can\'t find free block\n", stderr); quit_resizer(fs); } /* blocknr changing */ bh2 = getblk(fs->fs_dev, unused_block, fs->fs_blocksize); memcpy(bh2->b_data, bh->b_data, bh2->b_size); reiserfs_bitmap_clear_bit(bmp, block); reiserfs_bitmap_set_bit(bmp, unused_block); brelse(bh); mark_buffer_uptodate(bh2,1); mark_buffer_dirty(bh2); bwrite(bh2); brelse(bh2); total_moved_cnt++; return unused_block; } static unsigned long move_unformatted_block(reiserfs_filsys_t * fs, unsigned long block, unsigned long bnd, int h) { unsigned long b; unfm_node_cnt++; b = move_generic_block(fs, block, bnd, h); if (b) unfm_moved_cnt++; return b; } /* recursive function processing all tree nodes */ static unsigned long move_formatted_block(reiserfs_filsys_t * fs, unsigned long block, unsigned long bnd, int h) { struct buffer_head * bh; struct item_head *ih; unsigned long new_blocknr = 0; int node_is_internal = 0; unsigned int i, j; bh = bread(fs->fs_dev, block, fs->fs_blocksize); if (!bh) reiserfs_panic ("move_formatted_block: bread failed"); if (is_leaf_node (bh)) { leaf_node_cnt++; for (i = 0; i < B_NR_ITEMS(bh); i++) { ih = B_N_PITEM_HEAD(bh, i); if (is_indirect_ih(ih)) { __u32 * indirect; indirect = (__u32 *)B_I_PITEM (bh, ih); for (j = 0; j < I_UNFM_NUM(ih); j++) { unsigned long unfm_block; if (indirect [j] == 0) /* hole */ continue; unfm_block = move_unformatted_block(fs, le32_to_cpu (indirect [j]), bnd, h + 1); if (unfm_block) { indirect [j] = cpu_to_le32 (unfm_block); mark_buffer_dirty(bh); } } } } } else if (is_internal_node (bh)) { /* internal node */ int_node_cnt++; node_is_internal = 1; for (i=0; i <= B_NR_ITEMS(bh); i++) { unsigned long moved_block; moved_block = move_formatted_block(fs, get_dc_child_blocknr (B_N_CHILD (bh, i)), bnd, h+1); if (moved_block) { set_dc_child_blocknr (B_N_CHILD (bh, i), moved_block); mark_buffer_dirty(bh); } } } else { DIE ("block (%lu) has invalid format\n", block); } if (buffer_dirty(bh)) { mark_buffer_uptodate(bh,1); bwrite(bh); } brelse(bh); new_blocknr = move_generic_block(fs, block, bnd, h); if (new_blocknr) { if (node_is_internal) int_moved_cnt++; else leaf_moved_cnt++; } return new_blocknr; } int shrink_fs(reiserfs_filsys_t * fs, unsigned long blocks) { unsigned long n_root_block; unsigned int bmap_nr_new; ondisk_sb = fs->fs_ondisk_sb; /* warn about alpha version */ { int c; printf( "You are running BETA version of reiserfs shrinker.\n" "This version is only for testing or VERY CAREFUL use.\n" "Backup of you data is recommended.\n\n" "Do you want to continue? [y/N]:" ); fflush(stdout); c = getchar(); if (c != 'y' && c != 'Y') exit(1); } bmap_nr_new = (blocks - 1) / (8 * fs->fs_blocksize) + 1; /* is shrinking possible ? */ if (get_sb_block_count(ondisk_sb) - blocks > get_sb_free_blocks(ondisk_sb) + get_sb_bmap_nr(ondisk_sb) - bmap_nr_new) { fprintf(stderr, "resize_reiserfs: can\'t shrink fs; too many " "blocks already allocated\n"); return -1; } reiserfs_reopen(fs, O_RDWR); if (reiserfs_open_ondisk_bitmap (fs)) DIE("cannot open ondisk bitmap"); bmp = fs->fs_bitmap2; ondisk_sb = fs->fs_ondisk_sb; set_sb_fs_state (fs->fs_ondisk_sb, FS_ERROR); mark_buffer_uptodate(fs->fs_super_bh, 1); mark_buffer_dirty(fs->fs_super_bh); bwrite(fs->fs_super_bh); /* calculate number of data blocks */ blocks_used = get_sb_block_count(fs->fs_ondisk_sb) - get_sb_free_blocks(fs->fs_ondisk_sb) - get_sb_bmap_nr(fs->fs_ondisk_sb) - get_jp_journal_size(sb_jp (fs->fs_ondisk_sb)) - REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize - 2; /* superblock itself and 1 descriptor after the journal */ unused_block = 1; if (opt_verbose) { printf("Processing the tree: "); fflush(stdout); } n_root_block = move_formatted_block(fs, get_sb_root_block(ondisk_sb), blocks, 0); if (n_root_block) set_sb_root_block (ondisk_sb, n_root_block); if (opt_verbose) printf ("\n\nnodes processed (moved):\n" "int %lu (%lu),\n" "leaves %lu (%lu),\n" "unfm %lu (%lu),\n" "total %lu (%lu).\n\n", int_node_cnt, int_moved_cnt, leaf_node_cnt, leaf_moved_cnt, unfm_node_cnt, unfm_moved_cnt, (unsigned long)total_node_cnt, total_moved_cnt); if (block_count_mismatch) { fprintf(stderr, "resize_reiserfs: data block count %lu" " doesn\'t match data block count %lu from super block\n", (unsigned long)total_node_cnt, blocks_used); } #if 1 { unsigned long l; /* make sure that none of truncated block are in use */ printf("check for used blocks in truncated region\n"); for (l = blocks; l < fs->fs_bitmap2->bm_bit_size; l ++) { if ((l % (fs->fs_blocksize * 8)) == 0) continue; if (reiserfs_bitmap_test_bit (fs->fs_bitmap2, l)) printf ("<%lu>", l); } printf("\n"); } #endif reiserfs_shrink_bitmap (fs->fs_bitmap2, blocks); set_sb_free_blocks (ondisk_sb, get_sb_free_blocks(ondisk_sb) - (get_sb_block_count(ondisk_sb) - blocks) + (get_sb_bmap_nr(ondisk_sb) - bmap_nr_new)); set_sb_block_count (ondisk_sb, blocks); set_sb_bmap_nr (ondisk_sb, bmap_nr_new); return 0; } reiserfsprogs-3.6.9/ChangeLog0000664000077100007710000003152507705277441011712 2003-07-16 *reiserfsprogs Credits were changed. A pair of them are printed at mkfs time. *reiserfsprogs 3.6.9 release. 2003-06-25 *reiserfsprogs Bugs were fixed: - in reiserfsck rebuild-sb of relocated journal; - in reiserfstune --no-journal-available; - in bitmap handling during resizing; - in mkreiserfs with notstandard journal on the main device with not standard offset; - in not standard journal creation. 2003-05-29 *reiserfsprogs Bugs in journal traversing and in rebuild-sb were fixed. 2003-05-20 *reiserfsck Forks another process with openned file descriptor of the partition being checked when fscking on boot and sleep for 5 secs to avoid reading of all bitmaps on mount again. 2003-05-16 *mkreiserfs A bug with not standard journal cretion was fixed. *reiserfsprogs 3.6.8 release. 2003-05-07 *reiserfsck Exit codes were fixed; --yes option was added into fsck *mkreiserfs --quiet option was added into mkfs 2003-05-06 *reiserfsprogs A bug in journal replaying code when the only transaction exists was fixed. 2003-05-01 *reiserfsprogs Make fsck to proceed when wrong journal parameters in the journal header on a fs with standard journal detected fixing them with the warning. *reiserfsprogs 3.6.7 release. 2003-04-24 *reiserfsprogs 3.6.6 release. 2003-04-01 *reiserfsprogs Bug with flushing buffers on bad file descriptor was fixed. *reiserfstune Bugs with not standard journal were fixed. 2003-03-13 *reiserfsck Leaves recovery was improved - if some items are detected, try to recover the leaf even if block head is corrupted. 2003-03-04 *reiserfsck The objectid handling was improved, significant speedup at semantic pass and lost+found pass. 2003-02-27 *reiserfsprogs The check if the last block on fs is readable was moved from bitmap check to fs_open. Check transactions content before replaying, sware on invalid content instead of replay attempts, print about results. *reiserfsprogs 3.6.5 release. 2003-02-21 *reiserfsck a critical bug on pass0 of rebuild-tree with overflowing while checking unformatted item offsets was fixed. *reiserfsprogs 3.6.5-pre2 release. 2003-02-20 *reiserfsck reiserfsck -a (started at boot) replays journal, checks error flags in sb, bitmaps, fs size, 2 levels of internal tree and switches to fixble mode if any problem is detected. For root fs fixable cannot be performed (as fs is mounted) and just --check will be done. 2003-02-14 *reiserfsck fix-fixable does not relocated shared object ids anymore. Bug in relocation - entry key was not updated correctly with the new key of relocated file. 2003-02-12 *reiserfsprogs Journal replay was improved - check blocks if they are journable before replaying; - replay only transactions which has trans_id == last replayed transaction trans_id + 1. 2003-02-10 *reiserfsprogs le bitops operations were added back to avoid arch dependence with including asm/bitops.h - we should use le operations even on be mashins. 2003-01-31 *reiserfsprogs Warning messages about the broken hardware were improved. 2003-01-30 *reiserfsprogs Check for bits in ondisk bitmaps after the last valid bit was added - all these bits should be set to 1. 2002-12-13 *reiserfsck Keep only permanent fields of the super block, but not the whole super block, in separate memory while replaying. 2002-12-11 *reiserfsck While openning the journal check that journal parameters in super block and in jheader mathches; Advice to run rebuild-sb if not. While rebuilding super block, do the same check and ask the user if he wants to rebuild the jheader or continue without the journal or he wants to change the start of the partition before using reiserfsck. 2002-12-04 *reiserfsprogs 3.6.5-pre1 is released. 2002-12-02 *reiserfsck a few bugs were fixed: - bug in balancing code led to abort when a leaf could be viewed as a super block; - bug in checking statdata size for symlinks - there cannot be a hole at the end of symlink. 2002-11-28 *reiserfsck pass0 does not need a true objectid map, just those objectids which are not used. This sppedups pass0 a lot as many memoves are eliminated. *reiserfsck bug with item format for symlinks was fixed. 2002-10-02 *reiserfsprogs 3.6.4 is released. 2002-09-24 *reiserfsck bitmap handling was improved: fix-fixable fixes not only those blocks of bitmap which are wrongly marked as unused, but those which are wrongly marked as used also. 2002-09-10 * reiserfsck fix-fixable fixes item header formats, check complains about wrong ones. * reiserfsck check/fix-fixable does not complain about/fix file sizes if safe link exists. 2002-08-30 * reiserfsck user recieves a warning if dma mode/speed is descreased - it could happen due to hardware problems. 2002-08-20 * reiserfsprogs Warning/error messages were changed to more user friendly form. 2002-08-15 * reiserfsck Correction of nlinks on fix-fixable was disabled, because fix-fixable zeroes nlinks on the first pass and wants to increment them on semantic pass. But semantic pass is skipped if there are fatal corruptions. 2002-08-11 * reiserfsck exit codes were fixed 2002-08-08 * reiserfsck a critical bug in journal replaying was fixed. * reiserfsprogs called 3.6.3. 2002-06-06 * reiserfsck speedup for pass2: avoid checking whether a file body should be rewritten every time we have another item to insert into it. 2002-05-30 * reiserfsck speedup for pass2: avoid checking whether a file should be relocated on every insertion of a new item into it. Check it only for the first time. 2002-06-27 * reiserfsprogs called 3.6.2 2002-05-20 * reiserfsck speedup for pass2: do not check whether a file should be relocated if the file body was previously deleted from the tree and is inserted again. 2002-05-15 * reiserfsck speedup for pass2: insertion by many pointers at once was added 2002-05-10 * reiserfsck fix-fixable is able to fix wrong nlinks. check makes some check about nlinks also. 2002-04-30 * reiserfsck delete direntries of old format in new format directories 2002-03-29 * reiserfsprogs bad blocks support added. 2002-03-15 * reiserfsprogs different blocksize support added. 2002-02-18 * debugreiserfs new option -J, prints a journal header. 2002-02-10 * reiserfsprogs a few speedups were added. 2002-02-05 * reiserfsprogs optimization of the work with disk buffers. 2002-01-28 * mkreiserfs zeroing the first block on the device if not SPARC 2002-01-26 * reiserfsck a few speedups were added. 2002-01-20 * debugreiserfs investigation of unused space added (-D -U options, hidden) 2002-01-16 * reiserfsprogs support for UUID and LABEL was added 2002-01-15 * reiserfstune creates a standard journal from a non-standard 2001-12-25 * reiserfsck Handles safe links. 2001-12-03 * reiserfsck Filenames output during tree scan is now nicely scrolled left and right, when entire line does not fit the screen. 2001-11-20 * reiserfsck Can rebuild superblock properly. 2001-11-03 * reiserfsck Can now backup all data which get changed during fscking and can rollback all changes. 2001-10-30 * reiserfsprogs mkreiserfs/reiserfsck/reiserfstune/debugreiserfs work with relocated journal 2001-09-30 * debugreiserfs super block editor (-C -B 16) 2001-08-23 * reiserfsck --fix-fixable becomes a mode, can fix everything what does not need to rebuild a tree. --fix-non-critical option moved to --ajust-file-size option, work in --fix-fixable and --rebuild-tree modes. 2001-07-19 * mkreiserfs can now create non-standard journal: journal size, offset, device may now vary * reiserfstune initial release. Allows to change journal parameters for existing filesystems * reisrefsck it now sets "consistency checked" flag after --rebuild-tree and --check which did not find anything broken * man pages updated 2001-06-25 * mkreiserfs long options (--journal-device, --journal-size) * library reiserfs_create, reiserfs_create_journal 2001-06-20 * global changes Jeff's patch (safe endianness) is merged (with changes) mlock is used to estimate amount of memory available 2001-06-14 * reiserfsck update journal header when transaction is replayed 2001-06-13 * reiserfsck lost+found's mode is set to drwx------ after lost+found pass 2001-06-08 * library functions to deal with journal 2001-06-05 * global change Unified access via get_/set_ macroses is added for fields of struct key, struct item_head, struct reiserfs_journal_desc/commit, struct block_head, struct disk_child 2001-05-22 * global change Access to super block's fields are unified vid get_sb_xxx and set_sb_xxx macroses 2001-05-05 * called 3.x.0k-pre4 * reiserfsck entries in lost+found are removed on pass 0 2001-05-03 * mkreiserfs first 64k get zeroed now. This kills JFS if it was there * reiserfsprogs.spec (Anthon van der Neut) prereleases can be built by rpm now link from /sbin/mkreiserfs to /sbin/mkfs.reiserfs guess about reiserfs kernel support is added 2001-04-16 * reiserfsck in --check mode it exits with 0 if there were no corruptions found, 1 if there were only corruptions fixable by --fix-fixable or 2 if --rebuild-tree is required man page updated, simple example of using reiserfsck is added 2001-04-15 * mkreiserfs bug in confirmation dialogs fixed 2001-04-13-Friday * reiserfsck --hash option makes reiserfsck to skip blocks having directory entries created with other hash. It is useful together with --scan-whole-partition --background option allows to fork fsck end exit (useful for running remotely) 2001-03-31 * reiserfsck empty lost directories do not get linked into /lost+found 2001-03-28 * reiserfsck --nolog option is added 2001-03-26 * called 3.x.0j * reiserfsck with -o it tries to fix "objectid sharing" problem * reiserfsprogs.spec (Anthon van der Neut) rpm can be built as non-root link from reiserfsck to fsck.reiserfs rpm -e reiserfsprogs should now work without rmdir of / 2001-03-13 * reiserfsck --quiet option is added --fix-bogus-files option is added to fix transprently corrupted modes and to fix sizes which are longer that real file size directory item verifying changed -u has been replaced with -b to pass reiserfsck the list of block to build tree off -c is added to have pass 0 to save bitmap fo leaves found 2001-03-10 * called 3.x.0h * configure.in RPM_OPT_FLASG is added to CFLAGS (Anthon van der Neut) * reiserfsck -u option is added. It should save time when repeating --rebuild-tree hash hits statistic is added on pass 0 2001-03-07 * reiserfsck -V option to print version and exit added --fix-fixable changed: directory's sd_size and st_blocks corrections, removing of entries pointing to nowhere * resize_reiserfs man page is added 2001-03-05 * resize_reiserfs Marcel Waldvogel 's user interface and error messages improvements 2001-03-01 * mkreiserfs -q option is added (Larry Auton ) * reiserfsck --fix-fixable changed: bitmap correction commented out. Correction of broken slots of indirect items and corrections of dir entry state added 2001-02-23 * called 3.x.0e * reiserfsck not tested on 2.2 is now able to work with regular file (2.4.x is needed for that) lost+found fixed: it now first links directories then files. Still not good as it can not pull out deep directory 2001-02-19 * called 3.x.0c * reiserfsck --fix-fixable option is added. So far it only repairs bitmaps and free block count when they mismatch * library reiserfs_find/add_entry added 2001-02-05 * mkreiserfs can make filesystem with 1 data block 3.6 format is now default 2001-01-20 * portability Zam ran the reiserfsprogs on alpha * resizer Zam managed to resize few partitions. * reiserfsck pass0 deletes items which are out of order, tries to fix items with zeroed k_objectid or k_dir_id and to throw items which are transparently out of order and tries to fix "." and ".." of directory items. Pass0 corrects also corruptions in directory items * man pages: get included into dist when doing 'make dist' * mkreisrefs explains what is mininal size of reiserfs partition which can be created 2001-01-12 * reiserfsck: --interactive option is added * debugreiserfs: few bugs fixed 2001-01-07 * reiserfs library: started with reiserfs_open, reiserfs_close, bitmap tools * reiserfsck: filesystem mounted read-only can be checked number of options decreased journal replay fixed pass 0 added. fsck can be stopped after the tree is built. (should safe time when debugging) a lot of work still left * debugreiserfs: metadata packing changed added a feature to intentionally corrupt filesystem (should be useful for fsck debugging) * resizer: not updated yet * man pages: updated for all three progs reiserfsprogs-3.6.9/include/0000777000077100007710000000000007705315452011632 5reiserfsprogs-3.6.9/include/io.h0000664000077100007710000000505007705261642012331 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ struct buffer_head { unsigned long b_blocknr; int b_dev; unsigned long b_size; char * b_data; unsigned long b_state; unsigned int b_count; unsigned int b_list ; void (*b_start_io) (unsigned long); void (*b_end_io)(struct buffer_head *bh, int uptodate); struct buffer_head * b_next; struct buffer_head * b_prev; struct buffer_head * b_hash_next; struct buffer_head * b_hash_prev; }; #define BH_Uptodate 0 #define BH_Dirty 1 #define BH_Lock 2 #define BH_Do_not_flush 3 #define buffer_uptodate(bh) misc_test_bit(BH_Uptodate, &(bh)->b_state) #define buffer_dirty(bh) misc_test_bit(BH_Dirty, &(bh)->b_state) #define buffer_locked(bh) misc_test_bit(BH_Lock, &(bh)->b_state) #define buffer_clean(bh) !misc_test_bit(BH_Dirty, &(bh)->b_state) #define buffer_do_not_flush(bh) misc_test_bit(BH_Do_not_flush, &(bh)->b_state) #define mark_buffer_dirty(bh) misc_set_bit(BH_Dirty, &(bh)->b_state) #define mark_buffer_uptodate(bh,i) misc_set_bit(BH_Uptodate, &(bh)->b_state) #define mark_buffer_clean(bh) misc_clear_bit(BH_Dirty, &(bh)->b_state) #define mark_buffer_do_not_flush(bh) misc_set_bit(BH_Do_not_flush, &(bh)->b_state) #define clear_buffer_do_not_flush(bh) misc_clear_bit(BH_Do_not_flush, &(bh)->b_state) /* printf ("%s:%s:%u %p %p %p\n", __FILE__, __FUNCTION__, __LINE__, __builtin_return_address (0), __builtin_return_address (1), __builtin_return_address (2)); */ void __wait_on_buffer (struct buffer_head * bh); struct buffer_head * getblk (int dev, unsigned long block, int size); struct buffer_head * reiserfs_getblk (int dev, unsigned long block, int size, int *repeat); struct buffer_head * find_buffer (int dev, unsigned long block, unsigned long size); struct buffer_head * get_hash_table(dev_t dev, unsigned long block, int size); struct buffer_head * bread (int dev, unsigned long block, size_t size); struct buffer_head * reiserfs_bread (int dev, unsigned long block, int size, int *repeat); int valid_offset (int fd, loff_t offset); int bwrite (struct buffer_head * bh); void brelse (struct buffer_head * bh); void bforget (struct buffer_head * bh); void init_rollback_file (char * rollback_file, int *bloksize, FILE * log); int open_rollback_file (char * rollback_file, FILE * log); void close_rollback_file (); void do_fsck_rollback (int fd_device, int fd_journal_device, FILE * log); void flush_buffers (int); void free_buffers (void); void invalidate_buffers (int); int user_confirmed (FILE * fp, char * q, char * yes); reiserfsprogs-3.6.9/include/Makefile.am0000664000077100007710000000010407665645672013616 noinst_HEADERS = io.h misc.h reiserfs_fs.h reiserfs_lib.h swab.h reiserfsprogs-3.6.9/include/Makefile.in0000644000077100007710000002063007705315225013612 # Makefile.in generated by automake 1.7.2 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__quote = @am__quote@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ noinst_HEADERS = io.h misc.h reiserfs_fs.h reiserfs_lib.h swab.h subdir = include mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = DIST_SOURCES = HEADERS = $(noinst_HEADERS) DIST_COMMON = $(noinst_HEADERS) Makefile.am Makefile.in config.h.in all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu include/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status include/config.h $(srcdir)/config.h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && $(AUTOHEADER) touch $(srcdir)/config.h.in distclean-hdr: -rm -f config.h stamp-h1 uninstall-info-am: ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(HEADERS) config.h installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-generic distclean-hdr distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic ctags \ distclean distclean-generic distclean-hdr distclean-tags \ distdir dvi dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am tags uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: reiserfsprogs-3.6.9/include/config.h.in0000644000077100007710000000527707705262325013604 /* include/config.h.in. Generated from configure.in by autoheader. */ /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #undef HAVE_DOPRNT /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strstr' function. */ #undef HAVE_STRSTR /* Define to 1 if you have the `strtol' function. */ #undef HAVE_STRTOL /* Define to 1 if `st_rdev' is member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_RDEV /* Define to 1 if your `struct stat' has `st_rdev'. Deprecated, use `HAVE_STRUCT_STAT_ST_RDEV' instead. */ #undef HAVE_ST_RDEV /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vprintf' function. */ #undef HAVE_VPRINTF /* gets set when configure --enable-io-failure-emulation */ #undef IO_FAILURE_EMULATION /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define as `__inline' if that's what the C compiler calls it, or to nothing if it is not supported. */ #undef inline /* Define to `unsigned' if does not define. */ #undef size_t reiserfsprogs-3.6.9/include/misc.h0000664000077100007710000001322507705261642012660 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ /* nothing abount reiserfs here */ #ifndef REISERFS_MISC_H #define REISERFS_MISC_H #include #include "swab.h" #include #include #include #define POSITION_FOUND 8 #define POSITION_NOT_FOUND 9 void check_memory_msg(void); void die (char * fmt, ...) __attribute__ ((format (printf, 1, 2))); void * getmem (int size); void *mem_alloc(int size); void freemem (void * p); void checkmem (char * p, int size); void * expandmem (void * p, int size, int by); unsigned int get_mem_size (char * p); int is_mounted (char * device_name); int is_mounted_read_only (char * device_name); void check_and_free_mem (void); char * kdevname (int dev); void misc_print_credit(FILE *out); typedef struct dma_info { int fd; struct stat64 stat; int support_type; int dma; __u64 speed; } dma_info_t; int prepare_dma_check(dma_info_t *dma_info); int get_dma_info(dma_info_t *dma_info); void clean_after_dma_check(int fd, dma_info_t *dma_info); void print_how_far (FILE * fp, unsigned long *passed, unsigned long total, unsigned int inc, int quiet); void print_how_fast (unsigned long total, unsigned long passed, int cursor_pos, int reset_time); __u32 get_random (void); int uuid_is_null(unsigned char * uuid); int generate_random_uuid (unsigned char * uuid); int uuid_is_correct (unsigned char * uuid); int set_uuid (const unsigned char * text, unsigned char * UUID); //#include extern inline int misc_set_bit (unsigned long long nr, void * addr); extern inline int misc_clear_bit (unsigned long long nr, void * addr); extern inline int misc_test_bit(unsigned long long nr, const void * addr); extern inline unsigned long long misc_find_first_zero_bit (const void *vaddr, unsigned long long size); extern inline unsigned long long misc_find_next_zero_bit (const void *vaddr, unsigned long long size, unsigned long long offset); extern inline unsigned long long misc_find_next_set_bit(const void *vaddr, unsigned long long size, unsigned long long offset); extern inline unsigned long long misc_find_first_set_bit (const void *vaddr, unsigned long long size); #if __BYTE_ORDER == __LITTLE_ENDIAN # define cpu_to_le16(val) (val) # define le16_to_cpu(val) (val) # define cpu_to_le32(val) (val) # define le32_to_cpu(val) (val) # define cpu_to_le64(val) (val) # define le64_to_cpu(val) (val) #elif __BYTE_ORDER == __BIG_ENDIAN # define cpu_to_le16(val) __swab16(val) # define le16_to_cpu(val) __swab16(val) # define cpu_to_le32(val) __swab32(val) # define le32_to_cpu(val) __swab32(val) # define cpu_to_le64(val) __swab64(val) # define le64_to_cpu(val) __swab64(val) #else # error "nuxi/pdp-endian archs are not supported" #endif unsigned long count_blocks (char * filename, int blocksize); mode_t get_st_mode (char * file_name); dev_t get_st_rdev (char * file_name); off64_t get_st_size (char * file_name); blkcnt64_t get_st_blocks (char * file_name); /* these are to access bitfield in endian safe manner */ __u16 mask16 (int from, int count); __u32 mask32 (int from, int count); __u64 mask64 (int from, int count); int reiserfs_bin_search (void * key, void * base, __u32 num, int width, __u32 *ppos, comparison_fn_t comp_func); struct block_handler { __u32 blocknr; dev_t device; }; int blocklist__is_block_saved (struct block_handler ** base, __u32 * count, __u32 blocknr, dev_t device, __u32 * position); void blocklist__insert_in_position (void * block_h, void ** base, __u32 * count, int elem_size, __u32 * position); int blockdev_list_compare (const void * block1, const void * block2); #define set_bit_field_XX(XX,vp,val,from,count) \ {\ __u##XX * p, tmp;\ \ /* make sure that given value can be put in 'count' bits */\ if (val > (1 << count))\ die ("set_bit_field: val %d is too big for %d bits", val, count);\ \ p = (__u##XX *)vp;\ tmp = le##XX##_to_cpu (*p);\ \ /* clear 'count' bits starting from 'from'-th one */\ tmp &= ~mask##XX (from, count);\ \ /* put given value in proper bits */\ tmp |= (val << from);\ \ *p = cpu_to_le##XX (tmp);\ } #define get_bit_field_XX(XX,vp,from,count) \ \ __u##XX * p, tmp;\ \ p = (__u##XX *)vp;\ tmp = le##XX##_to_cpu (*p);\ \ /* clear all bits but 'count' bits starting from 'from'-th one */\ tmp &= mask##XX (from, count);\ \ /* get value written in specified bits */\ tmp >>= from;\ return tmp; #ifndef MAJOR #define MAJOR(rdev) ((rdev)>>8) #define MINOR(rdev) ((rdev) & 0xff) #endif /* MAJOR */ #ifndef SCSI_DISK_MAJOR #define SCSI_DISK_MAJOR(maj) ((maj) == SCSI_DISK0_MAJOR || \ ((maj) >= SCSI_DISK1_MAJOR && (maj) <= SCSI_DISK7_MAJOR)) #endif /* SCSI_DISK_MAJOR */ #ifndef SCSI_BLK_MAJOR #define SCSI_BLK_MAJOR(maj) (SCSI_DISK_MAJOR(maj) || (maj) == SCSI_CDROM_MAJOR) #endif /* SCSI_BLK_MAJOR */ #ifndef IDE_DISK_MAJOR #ifdef IDE9_MAJOR #define IDE_DISK_MAJOR(maj) ((maj) == IDE0_MAJOR || (maj) == IDE1_MAJOR || \ (maj) == IDE2_MAJOR || (maj) == IDE3_MAJOR || \ (maj) == IDE4_MAJOR || (maj) == IDE5_MAJOR || \ (maj) == IDE6_MAJOR || (maj) == IDE7_MAJOR || \ (maj) == IDE8_MAJOR || (maj) == IDE9_MAJOR) #else #define IDE_DISK_MAJOR(maj) ((maj) == IDE0_MAJOR || (maj) == IDE1_MAJOR || \ (maj) == IDE2_MAJOR || (maj) == IDE3_MAJOR || \ (maj) == IDE4_MAJOR || (maj) == IDE5_MAJOR) #endif /* IDE9_MAJOR */ #endif /* IDE_DISK_MAJOR */ #endif /* REISERFS_MISC_H */ reiserfsprogs-3.6.9/include/swab.h0000664000077100007710000000060207665645672012672 /* * Copyright 2002-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #ifndef _REISERFS_SWAB_H_ #define _REISERFS_SWAB_H_ #include #if __BYTE_ORDER == __BIG_ENDIAN #define extern static #define __BYTEORDER_HAS_U64__ #include #undef extern #else #include #endif #endif /* _REISERFS_SWAB_H_ */ reiserfsprogs-3.6.9/include/reiserfs_lib.h0000664000077100007710000004042107705261642014373 /* * Copyright 2000-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #ifndef REISERFS_LIB_H #define REISERFS_LIB_H typedef struct reiserfs_filsys reiserfs_filsys_t; #include "reiserfs_fs.h" struct _bitmap { unsigned long bm_byte_size; unsigned long bm_bit_size; char * bm_map; unsigned long bm_set_bits; int bm_dirty; /* used for fetched bitmap */ }; typedef struct _bitmap reiserfs_bitmap_t; typedef __u32 (*hashf_t) (const char *, int); struct reiserfs_filsys { unsigned int fs_blocksize; int fs_format; /* on-disk format version */ hashf_t fs_hash_function; /* pointer to function which is used to sort names in directory. It is set by reiserfs_open if it is set in the super block, otherwise it is set by first is_properly_hashed */ char * fs_file_name; /* file name of underlying device */ int fs_dev; /* descriptor of opened block device file */ struct buffer_head * fs_super_bh; /* buffer containing super block */ struct reiserfs_super_block * fs_ondisk_sb; /* pointer to its b_data */ reiserfs_bitmap_t * fs_bitmap2; /* ondisk bitmap after reiserfs_open_ondisk_bitmap */ /* opened journal fields */ char * fs_j_file_name; /* file name of relocated journal device */ int fs_journal_dev; /* descriptor of opened journal device */ struct buffer_head * fs_jh_bh; /* buffer containing journal header */ /* badblocks */ reiserfs_bitmap_t * fs_badblocks_bm; int fs_dirt; int fs_flags; void * fs_vp; int (*block_allocator) (reiserfs_filsys_t * fs, unsigned long * free_blocknrs, unsigned long start, int amount_needed); int (*block_deallocator) (reiserfs_filsys_t * fs, unsigned long block); }; struct _transaction { unsigned long mount_id; unsigned long trans_id; unsigned long desc_blocknr; unsigned long trans_len; unsigned long commit_blocknr; unsigned long next_trans_offset; }; typedef struct _transaction reiserfs_trans_t; /* reiserfslib.c */ void init_tb_struct (struct tree_balance * tb, reiserfs_filsys_t *, struct path * path, int size); reiserfs_filsys_t * reiserfs_open (char * filename, int flags, int * error, void * vp, int skip_check); reiserfs_filsys_t * reiserfs_create (char * filename, int version, unsigned long block_count, int block_size, int default_journal, int new_format); void reiserfs_flush (reiserfs_filsys_t *); void reiserfs_free (reiserfs_filsys_t *); void reiserfs_close (reiserfs_filsys_t *); void reiserfs_reopen (reiserfs_filsys_t *, int flags); int is_opened_rw (reiserfs_filsys_t * fs); struct key * get_next_key_2 (struct path * path); /* void reiserfs_read_bitmap_blocks (reiserfs_filsys_t *); void reiserfs_free_bitmap_blocks (reiserfs_filsys_t *); */ int no_reiserfs_found (reiserfs_filsys_t *); int is_block_count_correct (unsigned long block_of_super_block, unsigned int block_size, unsigned long block_count, unsigned long journal_size); //unsigned long min_block_amount (int block_size, unsigned long journal_size); unsigned long get_size_of_journal_or_reserved_area (struct reiserfs_super_block * sb); int reiserfs_new_blocknrs (reiserfs_filsys_t *, unsigned long * free_blocknrs, unsigned long start, int amount_needed); int reiserfs_free_block (reiserfs_filsys_t *, unsigned long block); int spread_bitmaps (reiserfs_filsys_t *); int filesystem_dirty (reiserfs_filsys_t *); void mark_filesystem_dirty (reiserfs_filsys_t *); void reiserfs_paste_into_item (reiserfs_filsys_t *, struct path * path, const void * body, int size); void reiserfs_insert_item (reiserfs_filsys_t *, struct path * path, struct item_head * ih, const void * body); int reiserfs_locate_entry (reiserfs_filsys_t *, struct key * dir, char * name, struct path * path); int reiserfs_find_entry (reiserfs_filsys_t *, struct key * dir, char * name, unsigned int * min_gen_counter, struct key * key); int reiserfs_add_entry (reiserfs_filsys_t *, struct key * dir, char * name, int name_len, struct key * key, __u16 fsck_need); /*int reiserfs_bin_search (void * key, void * base, int num, int width, int *ppos, comparison_fn_t comp_func);*/ struct key * uget_lkey (struct path * path); struct key * uget_rkey (struct path * path); int reiserfs_search_by_key_3 (reiserfs_filsys_t *, struct key * key, struct path * path); int reiserfs_search_by_key_4 (reiserfs_filsys_t *, struct key * key, struct path * path); int reiserfs_search_by_entry_key (reiserfs_filsys_t *, struct key * key, struct path * path); int usearch_by_position (reiserfs_filsys_t *, struct key * key, int version, struct path * path); struct key * reiserfs_next_key (struct path * path); void copy_key (void * to, void * from); void copy_short_key (void * to, void * from); void copy_item_head(void * p_v_to, void * p_v_from); int comp_keys (const void * k1, const void * k2); int comp_keys_3 (const void * k1, const void * k2); int comp_short_keys (const void * p_s_key1, const void * p_s_key2); int comp_items (struct item_head * p_s_ih, struct path * p_s_path); int create_dir_sd (reiserfs_filsys_t * fs, struct path * path, struct key * key, void (*modify_item)(struct item_head *, void *)); void make_sure_root_dir_exists (reiserfs_filsys_t * fs, void (*modyfy_item)(struct item_head *, void *), int ih_flags); int create_badblock_bitmap (reiserfs_filsys_t * fs, char * badblocks_file); void add_badblock_list (reiserfs_filsys_t * fs, int no_badblock_in_tree_yet); extern struct key root_dir_key; extern struct key parent_root_dir_key; extern struct key lost_found_dir_key; extern __u16 root_dir_format; extern __u16 lost_found_dir_format; /* bitmap.c */ int reiserfs_open_ondisk_bitmap (reiserfs_filsys_t *); int reiserfs_create_ondisk_bitmap (reiserfs_filsys_t *); void reiserfs_free_ondisk_bitmap (reiserfs_filsys_t *); void reiserfs_close_ondisk_bitmap (reiserfs_filsys_t *); int reiserfs_flush_to_ondisk_bitmap (reiserfs_bitmap_t * bm, reiserfs_filsys_t * fs); reiserfs_bitmap_t * reiserfs_create_bitmap (unsigned int bit_count); int reiserfs_expand_bitmap (reiserfs_bitmap_t * bm, unsigned int bit_count); void reiserfs_shrink_bitmap (reiserfs_bitmap_t * bm, unsigned int bit_count); void reiserfs_delete_bitmap (reiserfs_bitmap_t * bm); void reiserfs_bitmap_copy (reiserfs_bitmap_t * to, reiserfs_bitmap_t * from); int reiserfs_bitmap_compare (reiserfs_bitmap_t * bm1, reiserfs_bitmap_t * bm2); void reiserfs_bitmap_disjunction (reiserfs_bitmap_t * disk, reiserfs_bitmap_t * cont); void reiserfs_bitmap_delta (reiserfs_bitmap_t * base, reiserfs_bitmap_t * exclude); void reiserfs_bitmap_set_bit (reiserfs_bitmap_t * bm, unsigned int bit_number); void reiserfs_bitmap_clear_bit (reiserfs_bitmap_t * bm, unsigned int bit_number); int reiserfs_bitmap_test_bit (reiserfs_bitmap_t * bm, unsigned int bit_number); int reiserfs_bitmap_find_zero_bit (reiserfs_bitmap_t * bm, unsigned long * start); /*int reiserfs_fetch_ondisk_bitmap (reiserfs_bitmap_t * bm, reiserfs_filsys_t *);*/ /*int reiserfs_flush_bitmap (reiserfs_bitmap_t * bm, reiserfs_filsys_t *);*/ void reiserfs_bitmap_zero (reiserfs_bitmap_t * bm); void reiserfs_bitmap_fill (reiserfs_bitmap_t * bm); unsigned int reiserfs_bitmap_ones (reiserfs_bitmap_t * bm); unsigned int reiserfs_bitmap_zeros (reiserfs_bitmap_t * bm); FILE * open_file(char * filename, char * option); void close_file(FILE * fp); void reiserfs_bitmap_save (FILE * fp, reiserfs_bitmap_t * bm); /* this probably should be in fsck */ void reiserfs_begin_stage_info_save(FILE * file, unsigned long stage); void reiserfs_end_stage_info_save(FILE * file); int is_stage_magic_correct (FILE * fp); //void reiserfs_stage_info_save(struct fsck_data *, FILE * file); reiserfs_bitmap_t * reiserfs_bitmap_load (FILE * fp); void reiserfs_bitmap_invert (reiserfs_bitmap_t * bm); int reiserfs_remove_entry (reiserfs_filsys_t *, struct key * key); /* node_formats.c */ #define THE_LEAF 1 #define THE_INTERNAL 2 #define THE_SUPER 3 #define THE_JDESC 4 #define HAS_IH_ARRAY 5 #define THE_UNKNOWN 6 int is_blocksize_correct (unsigned int blocksize); int is_reiserfs_3_5_magic_string (struct reiserfs_super_block * rs); int is_reiserfs_3_6_magic_string (struct reiserfs_super_block * rs); int is_reiserfs_jr_magic_string (struct reiserfs_super_block * rs); int does_look_like_super_block (struct reiserfs_super_block * rs); int is_any_reiserfs_magic_string (struct reiserfs_super_block * rs); int get_reiserfs_format (struct reiserfs_super_block * sb); int reiserfs_super_block_size (struct reiserfs_super_block * rs); /*int magic_2_version (struct reiserfs_super_block * rs);*/ int is_prejournaled_reiserfs (struct reiserfs_super_block * rs); int who_is_this (char * buf, int blocksize); int leaf_count_ih(char * buf, int blocksize); int leaf_free_space_estimate(char * buf, int blocksize); int is_a_leaf(char * buf, int blocksize); int leaf_item_number_estimate(struct buffer_head * bh); char * which_block (int code); int get_journal_size (reiserfs_filsys_t *); int not_data_block (reiserfs_filsys_t *, unsigned long block); int not_journalable (reiserfs_filsys_t *, unsigned long block); int block_of_bitmap (reiserfs_filsys_t *, unsigned long block); int block_of_journal (reiserfs_filsys_t *, unsigned long block); int is_tree_node (struct buffer_head * bh, int level); int is_properly_hashed (reiserfs_filsys_t *, char * name, int namelen, __u32 offset); int dir_entry_bad_location (struct reiserfs_de_head * deh, struct item_head * ih, int first); void make_dir_stat_data (int blocksize, int key_format, __u32 dirid, __u32 objectid, struct item_head * ih, void * sd); void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, __u32 par_dirid, __u32 par_objid); void make_empty_dir_item (char * body, __u32 dirid, __u32 objid, __u32 par_dirid, __u32 par_objid); int reiserfs_is_fs_consistent (reiserfs_filsys_t * fs); typedef void (*item_action_t) (struct buffer_head * bh, struct item_head * ih); typedef void (*item_head_action_t) (struct item_head * ih); void for_every_item (struct buffer_head * bh, item_head_action_t action, item_action_t * actions); int key_format (const struct key * key); unsigned long long get_offset (const struct key * key); int uniqueness2type (__u32 uniqueness); __u32 type2uniqueness (int type); int get_type (const struct key * key); char * key_of_what (const struct key * key); int type_unknown (struct key * key); void set_type (int format, struct key * key, int type); void set_offset (int format, struct key * key, loff_t offset); void set_type_and_offset (int format, struct key * key, loff_t offset, int type); typedef int (*check_unfm_func_t) (reiserfs_filsys_t *, __u32); int is_it_bad_item (reiserfs_filsys_t *, struct item_head *, char *, check_unfm_func_t, int bad_dir); #define hash_func_is_unknown(fs) ((fs)->fs_hash_function == 0) #define reiserfs_hash(fs) ((fs)->fs_hash_function) int known_hashes (void); char *code2name (unsigned int code); int func2code (hashf_t func); hashf_t code2func (unsigned int code); hashf_t name2func (char * hash); int find_hash_in_use (char * name, int namelen, __u32 hash_value_masked, unsigned int code_to_try_first); int entry_length (struct item_head * ih, struct reiserfs_de_head * deh, int pos_in_item); char * name_in_entry (struct reiserfs_de_head * deh, int pos_in_item); int name_in_entry_length (struct item_head * ih, struct reiserfs_de_head * deh, int pos_in_item); int name_length (char * name, int key_format); /* access to stat data fields */ void get_set_sd_field (int field, struct item_head * ih, void * sd, void * value, int set); #define GET_SD_MODE 0 #define GET_SD_SIZE 1 #define GET_SD_NLINK 2 #define GET_SD_BLOCKS 3 #define GET_SD_FIRST_DIRECT_BYTE 4 #define get_sd_mode(ih,sd,pmode) get_set_sd_field (GET_SD_MODE, ih, sd, pmode, 0/*get*/) #define set_sd_mode(ih,sd,pmode) get_set_sd_field (GET_SD_MODE, ih, sd, pmode, 1/*set*/) #define get_sd_size(ih,sd,psize) get_set_sd_field (GET_SD_SIZE, ih, sd, psize, 0/*get*/) #define set_sd_size(ih,sd,psize) get_set_sd_field (GET_SD_SIZE, ih, sd, psize, 1/*set*/) #define get_sd_blocks(ih,sd,pblocks) get_set_sd_field (GET_SD_BLOCKS, ih, sd, pblocks, 0/*get*/) #define set_sd_blocks(ih,sd,pblocks) get_set_sd_field (GET_SD_BLOCKS, ih, sd, pblocks, 1/*set*/) //#define get_sd_rdev(ih,sd,pblocks) get_set_sd_field (GET_SD_RDEV, ih, sd, pblocks, 0/*get*/) //#define set_sd_rdev(ih,sd,pblocks) get_set_sd_field (GET_SD_RDEV, ih, sd, pblocks, 1/*set*/) //#define get_sd_generation(ih,sd,pblocks) get_set_sd_field (GET_SD_GENER, ih, sd, pblocks, 0/*get*/) //#define set_sd_generation(ih,sd,pblocks) get_set_sd_field (GET_SD_GENER, ih, sd, pblocks, 1/*set*/) #define get_sd_nlink(ih,sd,pnlink) get_set_sd_field (GET_SD_NLINK, ih, sd, pnlink, 0/*get*/) #define set_sd_nlink(ih,sd,pnlink) get_set_sd_field (GET_SD_NLINK, ih, sd, pnlink, 1/*set*/) #define get_sd_first_direct_byte(ih,sd,pfdb) get_set_sd_field (GET_SD_FIRST_DIRECT_BYTE, ih, sd, pfdb, 0/*get*/) #define set_sd_first_direct_byte(ih,sd,pfdb) get_set_sd_field (GET_SD_FIRST_DIRECT_BYTE, ih, sd, pfdb, 1/*set*/) int is_objectid_used (reiserfs_filsys_t * fs, __u32 objectid); void mark_objectid_used (reiserfs_filsys_t * fs, __u32 objectid); /* journal.c */ int get_boundary_transactions (reiserfs_filsys_t *, reiserfs_trans_t *, reiserfs_trans_t *); int next_transaction (reiserfs_filsys_t *, reiserfs_trans_t *, reiserfs_trans_t); int replay_one_transaction (reiserfs_filsys_t *, reiserfs_trans_t *); typedef void (*action_on_trans_t) (reiserfs_filsys_t *, reiserfs_trans_t *); void for_each_transaction (reiserfs_filsys_t *, action_on_trans_t); typedef void (*action_on_block_t) (reiserfs_filsys_t *, reiserfs_trans_t *, unsigned int index, unsigned long in_journal, unsigned long in_place); void for_each_block (reiserfs_filsys_t * fs, reiserfs_trans_t * trans, action_on_block_t action); int reiserfs_open_journal (reiserfs_filsys_t *, char *, int flags); int reiserfs_journal_params_check(reiserfs_filsys_t *fs); int reiserfs_create_journal (reiserfs_filsys_t * fs, char * j_filename, unsigned long offset, unsigned long len, int transaction_max_size); int reiserfs_journal_opened (reiserfs_filsys_t *); void reiserfs_flush_journal (reiserfs_filsys_t * fs); void reiserfs_free_journal (reiserfs_filsys_t * fs); void reiserfs_close_journal (reiserfs_filsys_t *); void reiserfs_reopen_journal (reiserfs_filsys_t * fs, int flag); __u32 advise_journal_max_trans_age (void); __u32 advise_journal_max_commit_age (void); __u32 advise_journal_max_batch (unsigned long journal_trans_max); __u32 advise_journal_max_trans_len (__u32 desired, __u32 journal_size, int blocksize, int verbose); /* prints.c */ void print_indirect_item (FILE * fp, struct buffer_head * bh, int item_num); void print_block (FILE * fp, reiserfs_filsys_t *, struct buffer_head * bh, ...);//int print_mode, int first, int last); int print_super_block (FILE * fp, reiserfs_filsys_t *, char * file_name, struct buffer_head * bh, int short_print); void print_journal (reiserfs_filsys_t *); void print_journal_header (reiserfs_filsys_t * fs); void reiserfs_warning (FILE * fp, const char * fmt, ...); char ftypelet (mode_t mode); void reiserfs_print_item (FILE * fp, struct buffer_head * bh, struct item_head * ih); void print_filesystem_state (FILE * fp, reiserfs_filsys_t * fs); void print_one_transaction (reiserfs_filsys_t * fs, reiserfs_trans_t * trans); void print_journal_params (FILE * fp, struct journal_params * jp); char * get_reiserfs_version (__u16 version); int can_we_format_it (char * device_name, int force); #define reiserfs_panic(fmt, list...) \ {\ fflush (stdout);\ fprintf (stderr, "%s %d %s\n", __FILE__, __LINE__, __FUNCTION__);\ reiserfs_warning (stderr, (const char *)fmt, ## list);\ reiserfs_warning (stderr, "\n" );\ abort ();\ } #define reiserfs_exit(val, fmt, list...) \ {\ fflush (stdout);\ fprintf (stderr, "%s %d %s\n", __FILE__, __LINE__, __FUNCTION__);\ reiserfs_warning (stderr, (const char *)fmt, ## list);\ reiserfs_warning (stderr, "\n" );\ exit (val);\ } #define check_forcing_ask_confirmation(force) \ if (force < 1) {\ /* avoid formatting it without being forced */\ reiserfs_warning (stderr, "Use -f to force over\n");\ return 0;\ }\ if (force < 2) {\ if (!user_confirmed (stderr, "Continue (y/n):", "y\n"))\ return 0;\ }\ #endif /* REISERFS_LIB_H */ reiserfsprogs-3.6.9/include/reiserfs_fs.h0000664000077100007710000020116007705261642014234 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ /* * Reiser File System constants and structures */ /* in reading the #defines, it may help to understand that they employ the following abbreviations: B = Buffer I = Item header H = Height within the tree (should be changed to LEV) N = Number of the item in the node STAT = stat data DEH = Directory Entry Header EC = Entry Count E = Entry number UL = Unsigned Long BLKH = BLocK Header UNFM = UNForMatted node DC = Disk Child P = Path These #defines are named by concatenating these abbreviations, where first comes the arguments, and last comes the return value, of the macro. */ #ifndef NO_EXTERN_INLINE # define extern_inline extern inline #else # define extern_inline #endif #define get_leXX(xx,p,field) (le##xx##_to_cpu ((p)->field)) #define set_leXX(xx,p,field,val) do { (p)->field = cpu_to_le##xx(val); } while (0) #define get_le16(p,field) get_leXX (16, p, field) #define set_le16(p,field,val) set_leXX (16, p, field, val) #define get_le32(p,field) get_leXX (32, p, field) #define set_le32(p,field,val) set_leXX (32, p, field, val) #define get_le64(p,field) get_leXX (64, p, field) #define set_le64(p,field,val) set_leXX (64, p, field, val) /***************************************************************************/ /* SUPER BLOCK */ /***************************************************************************/ #define UNSET_HASH 0 // read_super will guess about, what hash names // in directories were sorted with #define TEA_HASH 1 #define YURA_HASH 2 #define R5_HASH 3 #define DEFAULT_HASH R5_HASH /* super block of prejournalled version */ struct reiserfs_super_block_v0 { __u32 s_block_count; __u32 s_free_blocks; __u32 s_root_block; __u16 s_blocksize; __u16 s_oid_maxsize; __u16 s_oid_cursize; __u16 s_state; char s_magic[16]; __u16 s_tree_height; __u16 s_bmap_nr; __u16 s_reserved; }; struct journal_params { __u32 jp_journal_1st_block; /* where does journal start from on its device */ __u32 jp_journal_dev; /* journal device st_rdev */ __u32 jp_journal_size; /* size of the journal on FS creation. used to make sure they don't overflow it */ __u32 jp_journal_trans_max; /* max number of blocks in a transaction. */ __u32 jp_journal_magic; /* random value made on fs creation (this was sb_journal_block_count) */ __u32 jp_journal_max_batch; /* max number of blocks to batch into a trans */ __u32 jp_journal_max_commit_age; /* in seconds, how old can an async commit be */ __u32 jp_journal_max_trans_age; /* in seconds, how old can a transaction be */ }; #define get_jp_journal_1st_block(jp) get_le32 (jp, jp_journal_1st_block) #define set_jp_journal_1st_block(jp,val) set_le32 (jp, jp_journal_1st_block, val) #define get_jp_journal_dev(jp) get_le32 (jp, jp_journal_dev) #define set_jp_journal_dev(jp,val) set_le32 (jp, jp_journal_dev, val) #define get_jp_journal_size(jp) get_le32 (jp, jp_journal_size) #define set_jp_journal_size(jp,val) set_le32 (jp, jp_journal_size, val) #define get_jp_journal_max_trans_len(jp) get_le32 (jp, jp_journal_trans_max) #define set_jp_journal_max_trans_len(jp,val) set_le32 (jp, jp_journal_trans_max, val) #define get_jp_journal_magic(jp) get_le32 (jp, jp_journal_magic) #define set_jp_journal_magic(jp,val) set_le32 (jp, jp_journal_magic, val) #define NEED_TUNE 0xffffffff #define get_jp_journal_max_batch(jp) get_le32 (jp, jp_journal_max_batch) #define set_jp_journal_max_batch(jp,val) set_le32 (jp, jp_journal_max_batch, val) #define get_jp_journal_max_commit_age(jp) get_le32 (jp, jp_journal_max_commit_age) #define set_jp_journal_max_commit_age(jp,val) set_le32 (jp, jp_journal_max_commit_age, val) #define get_jp_journal_max_trans_age(jp) get_le32 (jp, jp_journal_max_commit_age) #define set_jp_journal_max_trans_age(jp,val) set_le32 (jp, jp_journal_max_commit_age, val) /* this is the super from 3.5.X */ struct reiserfs_super_block_v1 { __u32 sb_block_count; /* 0 number of block on data device */ __u32 sb_free_blocks; /* 4 free blocks count */ __u32 sb_root_block; /* 8 root of the tree */ struct journal_params sb_journal; /* 12 */ __u16 sb_blocksize; /* 44 */ __u16 sb_oid_maxsize; /* 46 max size of object id array, see get_objectid() commentary */ __u16 sb_oid_cursize; /* 48 current size of object id array */ __u16 sb_umount_state; /* 50 this is set to 1 when filesystem was umounted, to 2 - when not */ char s_magic[10]; /* 52 reiserfs magic string indicates that file system is reiserfs: "ReIsErFs" or "ReIsEr2Fs" or "ReIsEr3Fs" */ __u16 sb_fs_state; /* 62 it is set to used by fsck to mark which phase of rebuilding is done (used for fsck debugging) */ __u32 sb_hash_function_code;/* 64 code of fuction which was/is/will be used to sort names in a directory. See codes in above */ __u16 sb_tree_height; /* 68 height of filesytem tree. Tree consisting of only one root block has 2 here */ __u16 sb_bmap_nr; /* 70 amount of bitmap blocks needed to address each block of file system */ __u16 sb_version; /* 72 this field is only reliable on filesystem with non-standard journal */ __u16 sb_reserved_for_journal; /* 74 size in blocks of journal area on main device, we need to keep after non-standard journal relocation */ }; #define SB_SIZE_V1 (sizeof(struct reiserfs_super_block_v1)) /* 76 bytes */ #define sb_jp(sb) (&((sb)->s_v1.sb_journal)) /* values for sb_version field of struct reiserfs_super_block. sb_version is only reliable on filesystem with non-standard journal */ #define REISERFS_FORMAT_3_5 0 #define REISERFS_FORMAT_3_6 2 #define REISERFS_FORMAT_UNKNOWN -1 /* values for sb_mount_state field */ #define FS_CLEANLY_UMOUNTED 1 /* this was REISERFS_VALID_FS */ #define FS_NOT_CLEANLY_UMOUNTED 2 /* this was REISERFS_ERROR. It means that filesystem was not cleanly unmounted */ /* Structure of super block on disk */ struct reiserfs_super_block { /* 0 */ struct reiserfs_super_block_v1 s_v1; /* 76 */ __u32 sb_inode_generation; /* 80 */ __u32 s_flags; /* Right now used only by inode-attributes, if enabled */ /* 84 */ unsigned char s_uuid[16]; /* filesystem unique identifier */ /*100 */ unsigned char s_label[16]; /* filesystem volume label */ /*116 */ char s_unused[88] ; /* zero filled by mkreiserfs and reiserfs_convert_objectid_map_v1() * so any additions must be updated there as well. */ /*204*/ } __attribute__ ((__packed__));; typedef enum { reiserfs_attrs_cleared = 0x00000001, } reiserfs_super_block_flags; #define SB_SIZE (sizeof(struct reiserfs_super_block)) /* 204 bytes */ /* set/get fields of super block with these defines */ #define get_sb_block_count(sb) get_le32 (sb, s_v1.sb_block_count) #define set_sb_block_count(sb,val) set_le32 (sb, s_v1.sb_block_count, val) #define get_sb_free_blocks(sb) get_le32 (sb, s_v1.sb_free_blocks) #define set_sb_free_blocks(sb,val) set_le32 (sb, s_v1.sb_free_blocks, val) #define get_sb_root_block(sb) get_le32 (sb,s_v1.sb_root_block) #define set_sb_root_block(sb,val) set_le32 (sb, s_v1.sb_root_block, val) #if 0 #define get_sb_mount_id(sb) get_le32 (sb,s_v1.sb_mountid) #define set_sb_mount_id(sb,val) set_le32 (sb, s_v1.sb_mountid, val) #define get_sb_journal_magic(sb) get_le32 (sb, s_v1.sb_journal_magic) #define set_sb_journal_magic(sb,val) set_le32 (sb, s_v1.sb_journal_magic, val) #endif #define get_sb_block_size(sb) get_le16 (sb, s_v1.sb_blocksize) #define set_sb_block_size(sb,val) set_le16 (sb, s_v1.sb_blocksize, val) #define get_sb_oid_maxsize(sb) get_le16 (sb, s_v1.sb_oid_maxsize) #define set_sb_oid_maxsize(sb,val) set_le16 (sb, s_v1.sb_oid_maxsize, val) #define get_sb_oid_cursize(sb) get_le16 (sb, s_v1.sb_oid_cursize) #define set_sb_oid_cursize(sb,val) set_le16 (sb, s_v1.sb_oid_cursize, val) #define get_sb_umount_state(sb) get_le16 (sb, s_v1.sb_umount_state) #define set_sb_umount_state(sb,val) set_le16 (sb, s_v1.sb_umount_state, val) #define get_sb_fs_state(sb) get_le16 (sb, s_v1.sb_fs_state) #define set_sb_fs_state(sb,flag) set_le16 (sb, s_v1.sb_fs_state, flag) #define get_sb_hash_code(sb) get_le32 (sb, s_v1.sb_hash_function_code) #define set_sb_hash_code(sb,val) set_le32 (sb, s_v1.sb_hash_function_code, val) #define get_sb_tree_height(sb) get_le16 (sb, s_v1.sb_tree_height) #define set_sb_tree_height(sb,val) set_le16 (sb, s_v1.sb_tree_height, val) #define get_sb_bmap_nr(sb) get_le16 (sb, s_v1.sb_bmap_nr) #define set_sb_bmap_nr(sb,val) set_le16 (sb, s_v1.sb_bmap_nr, val) #define get_sb_version(sb) get_le16 (sb, s_v1.sb_version) #define set_sb_version(sb,val) set_le16 (sb, s_v1.sb_version, val) #define get_sb_reserved_for_journal(sb) get_le16 (sb, s_v1.sb_reserved_for_journal) #define set_sb_reserved_for_journal(sb,val) set_le16 (sb, s_v1.sb_reserved_for_journal, val) #define get_sb_v2_inode_generation(sb) get_le32 (sb, sb_inode_generation) #define set_sb_v2_inode_generation(sb,val) set_le32 (sb, sb_inode_generation, val) #define get_sb_v2_flags(sb) get_le32 (sb, s_flags) #define set_sb_v2_flags(sb, val) set_le32 (sb, s_flags, val) #define get_sb_v2_flag(sb, flag) (get_le32 (sb, s_flags) & flag) #define set_sb_v2_flag(sb, flag) set_le32 (sb, s_flags, get_le32 (sb, s_flags) | flag) #define clear_sb_v2_flag(sb, flag) set_le32 (sb, s_flags, get_le32 (sb, s_flags) & ~(flag)) /* #define journal_is_relocated(sb) get_jp_journal_dev(sb_jp (sb)) */ /* these are possible values for sb_fs_state */ #define FS_CONSISTENT 0x0 /* this is set by mkreiserfs and by reiserfsck */ #define FS_ERROR 0x1 /* this is set by the kernel when fsck is wanted. */ #define FS_FATAL 0x2 /* this is set by fsck when fatal corruption is found */ #define IO_ERROR 0x4 /* this is set by kernel when io error occures */ #define PASS_0_DONE 0xfa02 /* set by fsck when pass-by-pass (-d), FS_FATAL flag included */ #define PASS_1_DONE 0xfb02 /* set by fsck when pass-by-pass (-d), FS_FATAL flag included */ #define TREE_IS_BUILT 0xfc02 /* set by fsck when pass-by-pass (-d), FS_FATAL flag included */ #define SEMANTIC_DONE 0xfd02 /* set by fsck when pass-by-pass (-d), FS_FATAL flag included */ #define LOST_FOUND_DONE 0xfe02 /* set by fsck when pass-by-pass (-d), FS_FATAL flag included */ /* struct stat_data* access macros */ /* v1 */ #define sd_v1_mode(sd) (le16_to_cpu((sd)->sd_mode)) #define set_sd_v1_mode(sd,n) ((sd)->sd_mode = cpu_to_le16((n))) #define sd_v1_nlink(sd) (le16_to_cpu((sd)->sd_nlink)) #define set_sd_v1_nlink(sd,n) ((sd)->sd_nlink = cpu_to_le16((n))) #define sd_v1_uid(sd) (le16_to_cpu((sd)->sd_uid)) #define set_sd_v1_uid(sd,n) ((sd)->sd_uid = cpu_to_le16((n))) #define sd_v1_gid(sd) (le16_to_cpu((sd)->sd_gid)) #define set_sd_v1_gid(sd,n) ((sd)->sd_gid = cpu_to_le16((n))) #define sd_v1_size(sd) (le32_to_cpu((sd)->sd_size)) #define set_sd_v1_size(sd,n) ((sd)->sd_size = cpu_to_le32((n))) #define sd_v1_atime(sd) (le32_to_cpu((sd)->sd_atime)) #define set_sd_v1_atime(sd,n) ((sd)->sd_atime = cpu_to_le32((n))) #define sd_v1_mtime(sd) (le32_to_cpu((sd)->sd_mtime)) #define set_sd_v1_mtime(sd,n) ((sd)->sd_mtime = cpu_to_le32((n))) #define sd_v1_ctime(sd) (le32_to_cpu((sd)->sd_ctime)) #define set_sd_v1_ctime(sd,n) ((sd)->sd_ctime = cpu_to_le32((n))) #define sd_v1_blocks(sd) (le32_to_cpu((sd)->u.sd_blocks)) #define set_sd_v1_blocks(sd,n) ((sd)->u.sd_blocks = cpu_to_le32((n))) #define sd_v1_rdev(sd) (le32_to_cpu((sd)->u.sd_rdev)) #define set_sd_v1_rdev(sd,n) ((sd)->u.sd_rdev = cpu_to_le32((n))) #define sd_v1_first_direct_byte(sd) (le32_to_cpu((sd)->sd_first_direct_byte)) #define set_sd_v1_first_direct_byte(sd,n) \ ((sd)->sd_first_direct_byte = cpu_to_le32((n))) /* v2 */ #define sd_v2_mode(sd) (le16_to_cpu((sd)->sd_mode)) #define set_sd_v2_mode(sd,n) ((sd)->sd_mode = cpu_to_le16((n))) #define sd_v2_sd_attrs(sd) (le16_to_cpu((sd)->sd_attrs)) #define set_sd_v2_sd_attrs(sd,n) ((sd)->sd_attrs = cpu_to_le16((n))) #define sd_v2_nlink(sd) (le32_to_cpu((sd)->sd_nlink)) #define set_sd_v2_nlink(sd,n) ((sd)->sd_nlink = cpu_to_le32((n))) #define sd_v2_size(sd) (le64_to_cpu((sd)->sd_size)) #define set_sd_v2_size(sd,n) ((sd)->sd_size = cpu_to_le64((n))) #define sd_v2_uid(sd) (le32_to_cpu((sd)->sd_uid)) #define set_sd_v2_uid(sd,n) ((sd)->sd_uid = cpu_to_le32((n))) #define sd_v2_gid(sd) (le32_to_cpu((sd)->sd_gid)) #define set_sd_v2_gid(sd,n) ((sd)->sd_gid = cpu_to_le32((n))) #define sd_v2_atime(sd) (le32_to_cpu((sd)->sd_atime)) #define set_sd_v2_atime(sd,n) ((sd)->sd_atime = cpu_to_le32((n))) #define sd_v2_mtime(sd) (le32_to_cpu((sd)->sd_mtime)) #define set_sd_v2_mtime(sd,n) ((sd)->sd_mtime = cpu_to_le32((n))) #define sd_v2_ctime(sd) (le32_to_cpu((sd)->sd_ctime)) #define set_sd_v2_ctime(sd,n) ((sd)->sd_ctime = cpu_to_le32((n))) #define sd_v2_blocks(sd) (le32_to_cpu((sd)->sd_blocks)) #define set_sd_v2_blocks(sd,n) ((sd)->sd_blocks = cpu_to_le32((n))) #define sd_v2_rdev(sd) (le32_to_cpu((sd)->u.sd_rdev)) #define set_sd_v2_rdev(sd,n) ((sd)->u.sd_rdev = cpu_to_le32((n))) /* ReiserFS leaves the first 64k unused, so that partition labels have enough space. If someone wants to write a fancy bootloader that needs more than 64k, let us know, and this will be increased in size. This number must be larger than than the largest block size on any platform, or code will break. -Hans */ #define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024) /*#define MD_RAID_SUPERBLOCKS_IN_BYTES (128 * 1024)*/ /* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */ #define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024) /* prejournalled reiserfs had signature in the other place in super block */ #define REISERFS_SUPER_MAGIC_STRING_OFFSET_NJ 20 /* f_type of struct statfs will be set at this value by statfs(2) */ #define REISERFS_SUPER_MAGIC 0x52654973 /* various reiserfs signatures. We have 3 so far. ReIsErFs for 3.5 format with standard journal, ReIsEr2Fs for 3.6 (or converted 3.5) and ReIsEr3Fs for filesystem with non-standard journal (formats are distinguished by sb_version in that case). Those signatures should be looked for at the 64-th and at the 8-th 1k block of the device */ #define REISERFS_3_5_SUPER_MAGIC_STRING "ReIsErFs" #define REISERFS_3_6_SUPER_MAGIC_STRING "ReIsEr2Fs" #define REISERFS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" /* JR stands for Journal Relocation */ #define get_reiserfs_ondisk_offset(block_of_super_block, block_size) \ (block_of_super_block * block_size) #define is_new_sb_location(block_of_super_block, block_size) \ ((get_reiserfs_ondisk_offset(block_of_super_block, block_size) == REISERFS_DISK_OFFSET_IN_BYTES) \ ? 1 : 0) /*only 4k blocks for old location*/ #define is_old_sb_location(block_of_super_block, block_size) \ ((get_reiserfs_ondisk_offset(block_of_super_block, 4096) == REISERFS_OLD_DISK_OFFSET_IN_BYTES) \ ? 1 : 0) /***************************************************************************/ /* JOURNAL */ /***************************************************************************/ #define JOURNAL_DESC_MAGIC "ReIsErLB" /* ick. magic string to find desc blocks in the journal */ /* journal.c see journal.c for all the comments here */ //#define JOURNAL_TRANS_HALF 1018 /* must be correct to keep the desc and commit structs at 4k */ /* first block written in a commit. BUG, not 64bit safe */ struct reiserfs_journal_desc { __u32 j2_trans_id ; /* id of commit */ __u32 j2_len ; /* length of commit. len +1 is the commit block */ __u32 j2_mount_id ; /* mount id of this trans*/ __u32 j2_realblock[1] ; /* real locations for each block */ }; #define get_jd_magic(bh) (bh->b_data + bh->b_size - 12) #define journal_trans_half(blocksize) \ ((blocksize - sizeof (struct reiserfs_journal_desc) + sizeof (__u32) - 12) / sizeof (__u32)) #define jdesc_header(bh) ((struct reiserfs_journal_desc *)bh->b_data) #define get_desc_trans_id(bh) get_le32 (jdesc_header (bh), j2_trans_id) #define set_desc_trans_id(bh,val) set_le32 (jdesc_header (bh), j2_trans_id, val) #define get_desc_trans_len(bh) get_le32 (jdesc_header (bh), j2_len) #define set_desc_trans_len(bh,val) set_le32 (jdesc_header (bh), j2_len, val) #define get_desc_mount_id(bh) get_le32 (jdesc_header (bh), j2_mount_id) #define set_desc_mount_id(bh,val) set_le32 (jdesc_header (bh), j2_mount_id, val) /* last block written in a commit BUG, not 64bit safe */ struct reiserfs_journal_commit { __u32 j3_trans_id ; /* must match j_trans_id from the desc block */ __u32 j3_len ; /* ditto */ __u32 j3_realblock[1] ; /* real locations for each block */ } ; #define jcommit_header(bh) ((struct reiserfs_journal_commit *)bh->b_data) #define get_commit_trans_id(bh) get_le32 (jcommit_header(bh), j3_trans_id) #define set_commit_trans_id(bh,val) set_le32 (jcommit_header(bh), j3_trans_id, val) #define get_commit_trans_len(bh) get_le32 (jcommit_header(bh), j3_len) #define set_comm_trans_len(bh,val) set_le32 (jcommit_header(bh), j3_len, val) /* this header block gets written whenever a transaction is considered fully ** flushed, and is more recent than the last fully flushed transaction. fully ** flushed means all the log blocks and all the real blocks are on disk, and ** this transaction does not need to be replayed. */ struct reiserfs_journal_header { __u32 jh_last_flush_trans_id ; /* id of last fully flushed transaction */ __u32 jh_first_unflushed_offset ; /* offset in the log of where to start replay after a crash */ __u32 jh_mount_id ; struct journal_params jh_journal; __u32 jh_last_check_mount_id; /* the mount id of the fs during the last reiserfsck --check. */ }; /* set/get fields of journal header with these defines */ #define get_jh_mount_id(jh) get_le32 (jh, jh_mount_id) #define set_jh_mount_id(jh,val) set_le32 (jh, jh_mount_id, val) #define get_jh_last_flushed(jh) get_le32 (jh, jh_last_flush_trans_id) #define set_jh_last_flushed(jh,val) set_le32 (jh, jh_last_flush_trans_id, val) #define get_jh_replay_start_offset(jh) get_le32 (jh, jh_first_unflushed_offset) #define set_jh_replay_start_offset(jh,val) set_le32 (jh, jh_first_unflushed_offset, val) /* journal default settings */ #define JOURNAL_MIN_SIZE 512 #define JOURNAL_TRANS_MAX 1024 /* biggest possible single transaction, don't change for now (8/3/99) */ #define JOURNAL_TRANS_MIN 256 /* need to check whether it works */ #define JOURNAL_DEFAULT_RATIO 8 /* default journal size / max trans length */ #define JOURNAL_MIN_RATIO 2 #define JOURNAL_MAX_BATCH 900 /* max blocks to batch into one transaction, don't make this any bigger than 900 */ #define JOURNAL_MAX_COMMIT_AGE 30 #define JOURNAL_MAX_TRANS_AGE 30 /* journal max size is a maximum number of blocks pointed by first bitmap - REISERFS_DISK_OFFSET - superblock - first bitmap - journal herader */ #define journal_max_size(block_of_super_block,blocksize) \ blocksize * 8 - (block_of_super_block + 1 + 1 + 1) #define journal_default_size(block_of_super_block,blocksize) \ (unsigned long long)((8192 > journal_max_size (block_of_super_block,blocksize)) ? \ journal_max_size (block_of_super_block,blocksize) : 8192) //#define JOURNAL_DEFAULT_SIZE 8192 number of blocks in the journal //#define JOURNAL_DEFAULT_SIZE_FOR_BS_1024 8125 number of blocks in the journal for block size 1KB #define bh_desc(bh) ((struct reiserfs_journal_desc *)((bh)->b_data)) #define bh_commit(bh) ((struct reiserfs_journal_commit *)((bh)->b_data)) /***************************************************************************/ /* KEY & ITEM HEAD */ /***************************************************************************/ struct offset_v1 { __u32 k_offset; __u32 k_uniqueness; } __attribute__ ((__packed__)); struct offset_v2 { #if __BYTE_ORDER == __LITTLE_ENDIAN __u64 k_offset:60; __u64 k_type: 4; // TYPE_STAT_DATA | TYPE_INDIRECT | TYPE_DIRECT | TYPE_DIRENTRY #elif __BYTE_ORDER == __BIG_ENDIAN __u64 k_type: 4; // TYPE_STAT_DATA | TYPE_INDIRECT | TYPE_DIRECT | TYPE_DIRENTRY __u64 k_offset:60; #else # error "nuxi/pdp-endian archs are not supported" #endif } __attribute__ ((__packed__)); /* Key of the object determines object's location in the tree, composed of 4 components */ struct key { __u32 k2_dir_id; /* packing locality: by default parent directory object id */ __u32 k2_objectid; /* object identifier */ union { struct offset_v1 k2_offset_v1; struct offset_v2 k2_offset_v2; } __attribute__ ((__packed__)) u; } __attribute__ ((__packed__)); /* set/get fields of keys on disk with these defines */ #define get_key_dirid(k) get_le32 (k, k2_dir_id) #define set_key_dirid(k,val) set_le32 (k, k2_dir_id, val) #define get_key_objectid(k) get_le32 (k, k2_objectid) #define set_key_objectid(k,val) set_le32 (k, k2_objectid, val) #define get_key_offset_v1(k) get_le32 (k, u.k2_offset_v1.k_offset) #define set_key_offset_v1(k,val) set_le32 (k, u.k2_offset_v1.k_offset, val) #define get_key_uniqueness(k) get_le32 (k, u.k2_offset_v1.k_uniqueness) #define set_key_uniqueness(k,val) set_le32 (k, u.k2_offset_v1.k_uniqueness, val) /* #define get_key_offset_v2(k) get_le64 (k, u.k2_offset_v2.k_offset) #define set_key_offset_v2(k,val) set_le64 (k, u.k2_offset_v2.k_offset, val) */ /* ??? */ /* #define get_key_type(k) get_le16 (k, u.k2_offset_v2.k_type) #define set_key_type(k,val) set_le16 (k, u.k2_offset_v2.k_type, val) */ /* #define key_dir_id(key) (le32_to_cpu((key)->k_dir_id)) #define set_key_dir_id(key,n) ((key)->k_dir_id = cpu_to_le32((n))) #define key_objectid(key) (le32_to_cpu((key)->k_objectid)) #define set_key_objectid(key,n) ((key)->k_objectid = cpu_to_le32((n))) */ #define KEY_SIZE (sizeof(struct key)) #define SHORT_KEY_SIZE 8 // values for k_uniqueness field of the struct key #define V1_SD_UNIQUENESS 0 #define V1_DIRENTRY_UNIQUENESS 500 #define DIRENTRY_UNIQUENESS 500 #define V1_DIRECT_UNIQUENESS 0xffffffff #define V1_INDIRECT_UNIQUENESS 0xfffffffe #define V1_UNKNOWN_UNIQUENESS 555 // values for k_type field of the struct key #define TYPE_STAT_DATA 0 #define TYPE_INDIRECT 1 #define TYPE_DIRECT 2 #define TYPE_DIRENTRY 3 #define TYPE_UNKNOWN 15 /* special type for symlink not conflicting to any of item types. */ #define TYPE_SYMLINK 4 #define KEY_FORMAT_1 0 #define KEY_FORMAT_2 1 #define KEY_FORMAT_UNDEFINED 15 /* Our function for comparing keys can compare keys of different lengths. It takes as a parameter the length of the keys it is to compare. These defines are used in determining what is to be passed to it as that parameter. */ #define REISERFS_FULL_KEY_LEN 4 #define REISERFS_SHORT_KEY_LEN 2 /* Everything in the filesystem is stored as a set of items. The item head contains the key of the item, its free space (for indirect items) and specifies the location of the item itself within the block. */ struct item_head { struct key ih_key; /* Everything in the tree is found by searching for it based on its key.*/ union { __u16 ih2_free_space; /* The free space in the last unformatted node of an indirect item if this is an indirect item. This equals 0xFFFF iff this is a direct item or stat data item. Note that the key, not this field, is used to determine the item type, and thus which field this union contains. */ __u16 ih2_entry_count; /* Iff this is a directory item, this field equals the number of directory entries in the directory item. */ } __attribute__ ((__packed__)) u; __u16 ih2_item_len; /* total size of the item body */ __u16 ih2_item_location; /* an offset to the item body within the block */ __u16 ih_format; /* key format is stored in bits 0-11 of this item flags are stored in bits 12-15 */ #if 0 struct { __u16 key_format : 12; /* KEY_FORMAT_1 or KEY_FORMAT_2. This is not necessary, but we have space, let use it */ __u16 flags : 4; /* fsck set here its flag (reachable/unreachable) */ } __attribute__ ((__packed__)) ih2_format; #endif } __attribute__ ((__packed__)); /* size of item header */ #define IH_SIZE (sizeof(struct item_head)) /* set/get fields of item head on disk with these defines */ #define get_ih_entry_count(ih) get_le16 (ih, u.ih2_entry_count) #define set_ih_entry_count(ih,val) set_le16 (ih, u.ih2_entry_count, val) #define get_ih_free_space(ih) get_le16 (ih, u.ih2_free_space) #define set_ih_free_space(ih,val) set_le16 (ih, u.ih2_free_space, 0) #define get_ih_item_len(ih) get_le16 (ih, ih2_item_len) #define set_ih_item_len(ih,val) set_le16 (ih, ih2_item_len, val) #define get_ih_location(ih) get_le16 (ih, ih2_item_location) #define set_ih_location(ih,val) set_le16 (ih, ih2_item_location, val) __u16 get_ih_flags (const struct item_head * ih); __u16 get_ih_key_format (const struct item_head * ih); void set_ih_flags (struct item_head * ih, __u16 val); void set_ih_key_format (struct item_head * ih, __u16 val); /* #define get_ih_key_format(ih) get_le16 (ih, ih2_format.key_format) #define set_ih_key_format(ih,val) set_le16 (ih, ih2_format.key_format, val) #define get_ih_flags(ih) get_le16 (ih, ih2_format.flags) #define set_ih_flags(ih,val) set_le16 (ih, ih2_format.flags, val) */ #define I_K_KEY_IN_ITEM(p_s_ih, p_s_key, n_blocksize) \ ( ! not_of_one_file(p_s_ih, p_s_key) && \ I_OFF_BYTE_IN_ITEM(p_s_ih, get_offset (p_s_key), n_blocksize) ) #define IH_Unreachable 0 #define IH_Was_Tail 1 #define IH_Checked 2 #define IH_Writable 3 /* Bad item flag is set temporary by recover_leaf */ /* extern_inline __u16 mark_ih_bad( struct item_head *ih ) { set_ih_flags(ih, get_ih_flags(ih) | IH_Bad ); return get_ih_flags(ih); } extern_inline __u16 ih_bad( struct item_head *ih ) { __u16 tmp = get_ih_flags(ih); return test_bit(IH_Bad, &tmp ); } extern_inline __u16 unmark_item_bad( struct item_head *ih ) { __u16 tmp = get_ih_flags(ih); clear_bit( IH_Bad, &tmp ); set_ih_flags( ih, tmp ); return tmp; } */ /* Unreachable bit is set on tree rebuilding and is cleared in semantic pass */ #define clean_ih_flags(ih) set_ih_flags (ih, 0) #define ih_reachable(ih) (!(get_ih_flags (ih) & (1 << IH_Unreachable))) #define mark_ih_reachable(ih) set_ih_flags (ih, get_ih_flags (ih) & ~(1 << IH_Unreachable)) #define mark_ih_unreachable(ih) set_ih_flags (ih, get_ih_flags (ih) | (1 << IH_Unreachable)) #define ih_was_tail(ih) (get_ih_flags (ih) & (1 << IH_Was_Tail)) #define mark_ih_was_tail(ih) set_ih_flags (ih, get_ih_flags (ih) | (1 << IH_Was_Tail)) #define mark_ih_become_tail(ih) set_ih_flags (ih, get_ih_flags (ih) & ~(1 << IH_Was_Tail)) #define ih_checked(ih) (get_ih_flags (ih) & (1 << IH_Checked)) #define mark_ih_checked(ih) set_ih_flags (ih, get_ih_flags (ih) | (1 << IH_Checked)) #define clear_ih_checked(ih) set_ih_flags (ih, get_ih_flags (ih) & ~(1 << IH_Checked)) #define ih_writable(ih) (get_ih_flags (ih) & (1 << IH_Writable)) #define mark_ih_writable(ih) set_ih_flags (ih, get_ih_flags (ih) | (1 << IH_Writable)) #define clear_ih_writable(ih) set_ih_flags (ih, get_ih_flags (ih) & ~(1 << IH_Writable)) /* maximal length of item */ #define MAX_ITEM_LEN(block_size) (block_size - BLKH_SIZE - IH_SIZE) #define MIN_ITEM_LEN 1 /* object identifier for root dir */ #define REISERFS_ROOT_OBJECTID 2 #define REISERFS_ROOT_PARENT_OBJECTID 1 /* * Picture represents a leaf of internal tree * ______________________________________________________ * | | Array of | | | * |Block | Object-Item | F r e e | Objects- | * | head | Headers | S p a c e | Items | * |______|_______________|___________________|___________| */ /* Header of a disk block. More precisely, header of a formatted leaf or internal node, and not the header of an unformatted node. */ struct block_head { __u16 blk2_level; /* Level of a block in the tree. */ __u16 blk2_nr_item; /* Number of keys/items in a block. */ __u16 blk2_free_space; /* Block free space in bytes. */ __u16 blk_reserved; __u32 reserved [4]; }; #define BLKH_SIZE (sizeof(struct block_head)) /* set/get fields of block head on disk with these defines */ #define get_blkh_level(blkh) get_le16 (blkh, blk2_level) #define set_blkh_level(blkh,val) set_le16 (blkh, blk2_level, val) #define get_blkh_nr_items(blkh) get_le16 (blkh, blk2_nr_item) #define set_blkh_nr_items(blkh,val) set_le16 (blkh, blk2_nr_item, val) #define get_blkh_free_space(blkh) get_le16 (blkh, blk2_free_space) #define set_blkh_free_space(blkh,val) set_le16 (blkh, blk2_free_space, val) /* * values for blk_type field */ #define FREE_LEVEL 0 /* Node of this level is out of the tree. */ #define DISK_LEAF_NODE_LEVEL 1 /* Leaf node level. */ #define is_leaf_block_head(buf) (get_blkh_level ((struct block_head *)(buf)) == DISK_LEAF_NODE_LEVEL) #define is_internal_block_head(buf) \ ((get_blkh_level (((struct block_head *)(buf))) > DISK_LEAF_NODE_LEVEL) &&\ (get_blkh_level (((struct block_head *)(buf))) <= MAX_HEIGHT)) /* Given the buffer head of a formatted node, resolve to the block head of that node. */ #define B_BLK_HEAD(p_s_bh) ((struct block_head *)((p_s_bh)->b_data)) #define B_NR_ITEMS(bh) get_blkh_nr_items (B_BLK_HEAD(bh)) #define B_LEVEL(bh) get_blkh_level (B_BLK_HEAD(bh)) #define B_FREE_SPACE(bh) get_blkh_free_space (B_BLK_HEAD(bh)) #define is_leaf_node(bh) is_leaf_block_head ((bh)->b_data) #define is_internal_node(bh) is_internal_block_head ((bh)->b_data) /***************************************************************************/ /* STAT DATA */ /***************************************************************************/ /* Stat Data on disk (reiserfs version of UFS disk inode minus the address blocks) */ /* The sense of adding union to stat data is to keep a value of real number of blocks used by file. The necessity of adding such information is caused by existing of files with holes. Reiserfs should keep number of used blocks for file, but not calculate it from file size (that is not correct for holed files). Thus we have to add additional information to stat data. When we have a device special file, there is no need to get number of used blocks for them, and, accordingly, we doesn't need to keep major and minor numbers for regular files, which might have holes. So this field is being overloaded. */ struct stat_data_v1 { __u16 sd_mode; /* file type, permissions */ __u16 sd_nlink; /* number of hard links */ __u16 sd_uid; /* owner */ __u16 sd_gid; /* group */ __u32 sd_size; /* file size */ __u32 sd_atime; /* time of last access */ __u32 sd_mtime; /* time file was last modified */ __u32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */ union { __u32 sd_rdev; __u32 sd_blocks; /* number of blocks file uses */ } __attribute__ ((__packed__)) u; __u32 sd_first_direct_byte; /* first byte of file which is stored in a direct item: except that if it equals 1 it is a symlink and if it equals MAX_KEY_OFFSET there is no direct item. The existence of this field really grates on me. Let's replace it with a macro based on sd_size and our tail suppression policy. Someday. -Hans */ } __attribute__ ((__packed__)); #define SD_V1_SIZE (sizeof(struct stat_data_v1)) /* this is used to check sd_size of stat data v1 */ #define MAX_FILE_SIZE_V1 0x7fffffff // sd_first_direct_byte is set to this when there are no direct items in a // file #define NO_BYTES_IN_DIRECT_ITEM 0xffffffff /* Stat Data on disk (reiserfs version of UFS disk inode minus the address blocks) */ struct stat_data { __u16 sd_mode; /* file type, permissions */ __u16 sd_attrs; __u32 sd_nlink; /* 32 bit nlink! */ __u64 sd_size; /* 64 bit size!*/ __u32 sd_uid; /* 32 bit uid! */ __u32 sd_gid; /* 32 bit gid! */ __u32 sd_atime; /* time of last access */ __u32 sd_mtime; /* time file was last modified */ __u32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */ __u32 sd_blocks; union { __u32 sd_rdev; __u32 sd_generation; //__u32 sd_first_direct_byte; /* first byte of file which is stored in a direct item: except that if it equals 1 it is a symlink and if it equals ~(__u32)0 there is no direct item. The existence of this field really grates on me. Let's replace it with a macro based on sd_size and our tail suppression policy? */ } __attribute__ ((__packed__)) u; } __attribute__ ((__packed__)); // // this is 44 bytes long // #define SD_SIZE (sizeof(struct stat_data)) // there are two ways: to check length of item or ih_format field // (for old stat data it is set to 0 (KEY_FORMAT_1)) #define stat_data_v1(ih) (get_ih_key_format (ih) == KEY_FORMAT_1) /* this is used to check sd_size of stat data v2: max offset which can be reached with a key of format 2 is 60 bits */ #define MAX_FILE_SIZE_V2 0xfffffffffffffffLL /***************************************************************************/ /* DIRECTORY STRUCTURE */ /***************************************************************************/ /* Picture represents the structure of directory items ________________________________________________ | Array of | | | | | | | directory |N-1| N-2 | .... | 1st |0th| | entry headers | | | | | | |_______________|___|_____|________|_______|___| <---- directory entries ------> First directory item has k_offset component 1. We store "." and ".." in one item, always, we never split "." and ".." into differing items. This makes, among other things, the code for removing directories simpler. */ #define SD_OFFSET 0 #define DOT_OFFSET 1 #define DOT_DOT_OFFSET 2 /* Each directory entry has its header. This header has deh_dir_id and deh_objectid fields, those are key of object, entry points to */ /* NOT IMPLEMENTED: Directory will someday contain stat data of object */ struct reiserfs_de_head { __u32 deh2_offset; /* third component of the directory entry key */ __u32 deh2_dir_id; /* objectid of the parent directory of the object, that is referenced by directory entry */ __u32 deh2_objectid;/* objectid of the object, that is referenced by directory entry */ __u16 deh2_location;/* offset of name in the whole item */ __u16 deh2_state; /* whether 1) entry contains stat data (for future), and 2) whether entry is hidden (unlinked) */ } __attribute__ ((__packed__)); #define DEH_SIZE sizeof(struct reiserfs_de_head) /* set/get fields of dir entry head these defines */ #define get_deh_offset(deh) get_le32 (deh, deh2_offset) #define set_deh_offset(deh,val) set_le32 (deh, deh2_offset, val) #define get_deh_dirid(deh) get_le32 (deh, deh2_dir_id) #define set_deh_dirid(deh,val) set_le32 (deh, deh2_dir_id, val) #define get_deh_objectid(deh) get_le32 (deh, deh2_objectid) #define set_deh_objectid(deh,val) set_le32 (deh, deh2_objectid, val) #define get_deh_location(deh) get_le16 (deh, deh2_location) #define set_deh_location(deh,val) set_le16 (deh, deh2_location, val) #define get_deh_state(deh) get_le16 (deh, deh2_state) #define set_deh_state(deh,val) set_le16 (deh, deh2_state, val) #define deh_offset(deh) (le32_to_cpu ((deh)->deh_offset)) #define deh_dir_id(deh) (le32_to_cpu ((deh)->deh_dir_id)) #define deh_objectid(deh) (le32_to_cpu ((deh)->deh_objectid)) #define deh_location(deh) (le16_to_cpu ((deh)->deh_location)) #define deh_state(deh) (le16_to_cpu ((deh)->deh_state)) /* empty directory contains two entries "." and ".." and their headers */ #define EMPTY_DIR_SIZE \ (DEH_SIZE * 2 + ROUND_UP (strlen (".")) + ROUND_UP (strlen (".."))) /* old format directories have this size when empty */ #define EMPTY_DIR_SIZE_V1 (DEH_SIZE * 2 + 3) #define DEH_Statdata 0 /* not used now */ #define DEH_Visible2 2 #define DEH_Bad_offset 4 /* fsck marks entries to be deleted with this flag */ #define DEH_Bad_location 5 #define test_deh_state_le_bit(deh,bit) (get_deh_state (deh) & (1 << bit)) #define set_deh_state_le_bit(deh,bit) \ {\ __u16 state;\ state = get_deh_state (deh);\ state |= (1 << bit);\ set_deh_state(deh, state);\ } #define clear_deh_state_le_bit(deh,bit) \ {\ __u16 state;\ state = get_deh_state (deh);\ state &= ~(1 << bit);\ set_deh_state(deh, state);\ } #define mark_de_without_sd(deh) clear_deh_state_le_bit (deh, DEH_Statdata) #define mark_de_visible(deh) set_deh_state_le_bit (deh, DEH_Visible2) #define mark_de_hidden(deh) clear_deh_state_le_bit (deh, DEH_Visible) #define de_with_sd(deh) test_deh_state_le_bit (deh, DEH_Statdata) #define de_visible(deh) test_deh_state_le_bit (deh, DEH_Visible2) #define de_hidden(deh) !test_deh_state_le_bit (deh, DEH_Visible2) /* Bad means "hashed unproperly or/and invalid location" */ #define de_bad_location(deh) test_deh_state_le_bit (deh, DEH_Bad_location) #define mark_de_bad_location(deh) set_deh_state_le_bit (deh, DEH_Bad_location) #define mark_de_good_location(deh) clear_deh_state_le_bit (deh, DEH_Bad_location) #define de_bad_offset(deh) test_deh_state_le_bit (deh, DEH_Bad_offset) #define mark_de_bad_offset(deh) set_deh_state_le_bit (deh, DEH_Bad_offset) #define de_bad(deh) (de_bad_location(deh) || de_bad_offset(deh)) /* for directories st_blocks is number of 512 byte units which fit into dir size round up to blocksize */ #define dir_size2st_blocks(size) ((size + 511) / 512) /* array of the entry headers */ #define B_I_DEH(bh,ih) ((struct reiserfs_de_head *)(B_I_PITEM(bh,ih))) #define REISERFS_MAX_NAME_LEN(block_size) (block_size - BLKH_SIZE - IH_SIZE - DEH_SIZE) /* -SD_SIZE when entry will contain stat data */ /* hash value occupies 24 bits starting from 7 up to 30 */ #define GET_HASH_VALUE(offset) ((offset) & 0x7fffff80) /* generation number occupies 7 bits starting from 0 up to 6 */ #define GET_GENERATION_NUMBER(offset) ((offset) & 0x0000007f) /* * Picture represents an internal node of the reiserfs tree * ______________________________________________________ * | | Array of | Array of | Free | * |block | keys | pointers | space | * | head | N | N+1 | | * |______|_______________|___________________|___________| */ /***************************************************************************/ /* DISK CHILD */ /***************************************************************************/ /* Disk child pointer: The pointer from an internal node of the tree to a node that is on disk. */ struct disk_child { __u32 dc2_block_number; /* Disk child's block number. */ __u16 dc2_size; /* Disk child's used space. */ __u16 dc2_reserved; } __attribute__ ((__packed__)); #define DC_SIZE (sizeof(struct disk_child)) /* set/get fields of disk_child with these defines */ #define get_dc_child_blocknr(dc) get_le32 (dc, dc2_block_number) #define set_dc_child_blocknr(dc,val) set_le32 (dc, dc2_block_number, val) #define get_dc_child_size(dc) get_le16 (dc, dc2_size) #define set_dc_child_size(dc,val) set_le16 (dc, dc2_size, val) /* Get disk child by buffer header and position in the tree node. */ #define B_N_CHILD(p_s_bh,n_pos) ((struct disk_child *)\ ((p_s_bh)->b_data + BLKH_SIZE + B_NR_ITEMS(p_s_bh) \ * KEY_SIZE + DC_SIZE * (n_pos))) /* maximal value of field child_size in structure disk_child */ /* child size is the combined size of all items and their headers */ #define MAX_CHILD_SIZE(blocksize) ((blocksize) - BLKH_SIZE) #define MAX_FREE_SPACE(blocksize) MAX_CHILD_SIZE(blocksize) /* amount of used space in buffer (not including block head) */ #define B_CHILD_SIZE(cur) (MAX_CHILD_SIZE(cur->b_size)-(B_FREE_SPACE(cur))) /* max and min number of keys in internal node */ #define MAX_NR_KEY(bh) ( (MAX_CHILD_SIZE(bh->b_size)-DC_SIZE)/(KEY_SIZE+DC_SIZE) ) #define MIN_NR_KEY(bh) (MAX_NR_KEY(bh)/2) /***************************************************************************/ /* PATH STRUCTURES AND DEFINES */ /***************************************************************************/ /* Search_by_key fills up the path from the root to the leaf as it descends the tree looking for the key. It uses reiserfs_bread to try to find buffers in the cache given their block number. If it does not find them in the cache it reads them from disk. For each node search_by_key finds using reiserfs_bread it then uses bin_search to look through that node. bin_search will find the position of the block_number of the next node if it is looking through an internal node. If it is looking through a leaf node bin_search will find the position of the item which has key either equal to given key, or which is the maximal key less than the given key. */ struct path_element { struct buffer_head * pe_buffer; /* Pointer to the buffer at the path in the tree. */ int pe_position; /* Position in the tree node which is placed in the buffer above. */ }; #define MAX_HEIGHT 6 #define FIRST_PATH_ELEMENT_OFFSET 2 #define EXTENDED_MAX_HEIGHT (MAX_HEIGHT + FIRST_PATH_ELEMENT_OFFSET) #define ILLEGAL_PATH_ELEMENT_OFFSET 1 #define MAX_FEB_SIZE (MAX_HEIGHT + 1) /* We need to keep track of who the ancestors of nodes are. When we perform a search we record which nodes were visited while descending the tree looking for the node we searched for. This list of nodes is called the path. This information is used while performing balancing. Note that this path information may become invalid, and this means we must check it when using it to see if it is still valid. You'll need to read search_by_key and the comments in it, especially about decrement_counters_in_path(), to understand this structure. */ struct path { unsigned int path_length; /* Length of the array above. */ struct path_element path_elements[EXTENDED_MAX_HEIGHT]; /* Array of the path elements. */ unsigned int pos_in_item; }; #define INITIALIZE_PATH(var) \ struct path var = {ILLEGAL_PATH_ELEMENT_OFFSET, } /* Get path element by path and path position. */ #define PATH_OFFSET_PELEMENT(p_s_path,n_offset) ((p_s_path)->path_elements +(n_offset)) /* Get buffer header at the path by path and path position. */ #define PATH_OFFSET_PBUFFER(p_s_path,n_offset) (PATH_OFFSET_PELEMENT(p_s_path,n_offset)->pe_buffer) /* Get position in the element at the path by path and path position. */ #define PATH_OFFSET_POSITION(p_s_path,n_offset) (PATH_OFFSET_PELEMENT(p_s_path,n_offset)->pe_position) #define PATH_PLAST_BUFFER(p_s_path) (PATH_OFFSET_PBUFFER((p_s_path), (p_s_path)->path_length)) #define PATH_LAST_POSITION(p_s_path) (PATH_OFFSET_POSITION((p_s_path), (p_s_path)->path_length)) #define PATH_PITEM_HEAD(p_s_path) B_N_PITEM_HEAD(PATH_PLAST_BUFFER(p_s_path),PATH_LAST_POSITION(p_s_path)) /* in do_balance leaf has h == 0 in contrast with path structure, where root has level == 0. That is why we need these defines */ #define PATH_H_PBUFFER(p_s_path, h) PATH_OFFSET_PBUFFER (p_s_path, p_s_path->path_length - (h)) /* tb->S[h] */ #define PATH_H_PPARENT(path, h) PATH_H_PBUFFER (path, (h) + 1) /* tb->F[h] or tb->S[0]->b_parent */ #define PATH_H_POSITION(path, h) PATH_OFFSET_POSITION (path, path->path_length - (h)) #define PATH_H_B_ITEM_ORDER(path, h) PATH_H_POSITION(path, h + 1) /* tb->S[h]->b_item_order */ #define PATH_H_PATH_OFFSET(p_s_path, n_h) ((p_s_path)->path_length - (n_h)) #define get_bh(path) PATH_PLAST_BUFFER(path) #define get_ih(path) PATH_PITEM_HEAD(path) #define get_item_pos(path) PATH_LAST_POSITION(path) #define get_item(path) ((void *)B_N_PITEM(PATH_PLAST_BUFFER(path), PATH_LAST_POSITION (path))) #define item_moved(ih,path) comp_items(ih, path) #define path_changed(ih,path) comp_items (ih, path) /***************************************************************************/ /* MISC */ /***************************************************************************/ /* n must be power of 2 */ #define _ROUND_UP(x,n) (((x)+(n)-1u) & ~((n)-1u)) // to be ok for alpha and others we have to align structures to 8 byte // boundary. // FIXME: do not change 4 by anything else: there is code which relies on that #define ROUND_UP(x) _ROUND_UP(x,8LL) // search_by_key (and clones) and fix_nodes error code #define CARRY_ON 0 #define NO_DISK_SPACE 3 /* #define IO_ERROR 0x4 - defined above as 0x4 */ #define NO_BALANCING_NEEDED 5 #define ITEM_FOUND 6 #define ITEM_NOT_FOUND 7 #define GOTO_PREVIOUS_ITEM 10 #define POSITION_FOUND_INVISIBLE 11 #define FILE_NOT_FOUND 12 // used by fsck #define DIRECTORY_NOT_FOUND 13 #define REGULAR_FILE_FOUND 14 #define DIRECTORY_FOUND 15 struct unfm_nodeinfo { __u32 unfm_nodenum; __u16 unfm_freespace; }; /* Size of pointer to the unformatted node. */ #define UNFM_P_SIZE (sizeof(__u32)) #define MAX_KEY1_OFFSET 0xffffffff #define MAX_KEY2_OFFSET 0xfffffffffffffffLL /* this is aggressive tail suppression policy taken from the kernel */ /* It should be MAX_DIRECT_ITEM_LEN used here, but sometimes it is not enough, * and items got deleted. */ #define STORE_TAIL_IN_UNFM(n_file_size,n_tail_size,n_block_size) \ (\ (!(n_tail_size)) || \ (((n_tail_size) > MAX_ITEM_LEN(n_block_size)) || \ ( (n_file_size) >= (n_block_size) * 4 ) || \ ( ( (n_file_size) >= (n_block_size) * 3 ) && \ ( (n_tail_size) >= (MAX_ITEM_LEN(n_block_size))/4) ) || \ ( ( (n_file_size) >= (n_block_size) * 2 ) && \ ( (n_tail_size) >= (MAX_ITEM_LEN(n_block_size))/2) ) || \ ( ( (n_file_size) >= (n_block_size) ) && \ ( (n_tail_size) >= (MAX_ITEM_LEN(n_block_size) * 3)/4) ) ) \ ) /***************************************************************************/ /* FIXATE NODES */ /***************************************************************************/ #define VI_TYPE_STAT_DATA 1 #define VI_TYPE_DIRECT 2 #define VI_TYPE_INDIRECT 4 #define VI_TYPE_DIRECTORY 8 #define VI_TYPE_FIRST_DIRECTORY_ITEM 16 #define VI_TYPE_INSERTED_DIRECTORY_ITEM 32 #define VI_TYPE_LEFT_MERGEABLE 64 #define VI_TYPE_RIGHT_MERGEABLE 128 /* To make any changes in the tree we always first find node, that contains item to be changed/deleted or place to insert a new item. We call this node S. To do balancing we need to decide what we will shift to left/right neighbor, or to a new node, where new item will be etc. To make this analysis simpler we build virtual node. Virtual node is an array of items, that will replace items of node S. (For instance if we are going to delete an item, virtual node does not contain it). Virtual node keeps information about item sizes and types, mergeability of first and last items, sizes of all entries in directory item. We use this array of items when calculating what we can shift to neighbors and how many nodes we have to have if we do not any shiftings, if we shift to left/right neighbor or to both. */ struct virtual_item { unsigned short vi_type; /* item type, mergeability */ unsigned short vi_item_len; /* length of item that it will have after balancing */ __u64 vi_item_offset; /* offset of item that it have before balancing */ short vi_entry_count; /* number of entries in directory item (including the new one if any, or excluding entry if it must be cut) */ unsigned short * vi_entry_sizes; /* array of entry lengths for directory item */ }; struct virtual_node { char * vn_free_ptr; /* this is a pointer to the free space in the buffer */ unsigned short vn_nr_item; /* number of items in virtual node */ short vn_size; /* size of node , that node would have if it has unlimited size and no balancing is performed */ short vn_mode; /* mode of balancing (paste, insert, delete, cut) */ short vn_affected_item_num; short vn_pos_in_item; struct item_head * vn_ins_ih; /* item header of inserted item, 0 for other modes */ struct virtual_item * vn_vi; /* array of items (including a new one, excluding item to be deleted) */ }; /***************************************************************************/ /* TREE BALANCE */ /***************************************************************************/ /* This temporary structure is used in tree balance algorithms, and constructed as we go to the extent that its various parts are needed. It contains arrays of nodes that can potentially be involved in the balancing of node S, and parameters that define how each of the nodes must be balanced. Note that in these algorithms for balancing the worst case is to need to balance the current node S and the left and right neighbors and all of their parents plus create a new node. We implement S1 balancing for the leaf nodes and S0 balancing for the internal nodes (S1 and S0 are defined in our papers.)*/ #define MAX_FREE_BLOCK 7 /* size of the array of buffers to free at end of do_balance */ /* maximum number of FEB blocknrs on a single level */ #define MAX_AMOUNT_NEEDED 2 /* someday somebody will prefix every field in this struct with tb_ */ struct tree_balance { struct reiserfs_transaction_handle *transaction_handle ; reiserfs_filsys_t * tb_fs; struct path * tb_path; struct buffer_head * L[MAX_HEIGHT]; /* array of left neighbors of nodes in the path */ struct buffer_head * R[MAX_HEIGHT]; /* array of right neighbors of nodes in the path*/ struct buffer_head * FL[MAX_HEIGHT]; /* array of fathers of the left neighbors */ struct buffer_head * FR[MAX_HEIGHT]; /* array of fathers of the right neighbors */ struct buffer_head * CFL[MAX_HEIGHT]; /* array of common parents of center node and its left neighbor */ struct buffer_head * CFR[MAX_HEIGHT]; /* array of common parents of center node and its right neighbor */ /* array of blocknr's that are free and are the nearest to the left node that are usable for writing dirty formatted leaves, using the write_next_to algorithm. */ /*unsigned long free_and_near[MAX_DIRTIABLE];*/ struct buffer_head * FEB[MAX_FEB_SIZE]; /* array of empty buffers. Number of buffers in array equals cur_blknum. */ struct buffer_head * used[MAX_FEB_SIZE]; short int lnum[MAX_HEIGHT]; /* array of number of items which must be shifted to the left in order to balance the current node; for leaves includes item that will be partially shifted; for internal nodes, it is the number of child pointers rather than items. It includes the new item being created. For preserve_shifted() purposes the code sometimes subtracts one from this number to get the number of currently existing items being shifted, and even more often for leaves it subtracts one to get the number of wholly shifted items for other purposes. */ short int rnum[MAX_HEIGHT]; /* substitute right for left in comment above */ short int lkey[MAX_HEIGHT]; /* array indexed by height h mapping the key delimiting L[h] and S[h] to its item number within the node CFL[h] */ short int rkey[MAX_HEIGHT]; /* substitute r for l in comment above */ short int insert_size[MAX_HEIGHT]; /* the number of bytes by we are trying to add or remove from S[h]. A negative value means removing. */ short int blknum[MAX_HEIGHT]; /* number of nodes that will replace node S[h] after balancing on the level h of the tree. If 0 then S is being deleted, if 1 then S is remaining and no new nodes are being created, if 2 or 3 then 1 or 2 new nodes is being created */ /* fields that are used only for balancing leaves of the tree */ short int cur_blknum; /* number of empty blocks having been already allocated */ short int s0num; /* number of items that fall into left most node when S[0] splits */ short int s1num; /* number of items that fall into first new node when S[0] splits */ short int s2num; /* number of items that fall into second new node when S[0] splits */ short int lbytes; /* number of bytes which can flow to the left neighbor from the left */ /* most liquid item that cannot be shifted from S[0] entirely */ /* if -1 then nothing will be partially shifted */ short int rbytes; /* number of bytes which will flow to the right neighbor from the right */ /* most liquid item that cannot be shifted from S[0] entirely */ /* if -1 then nothing will be partially shifted */ short int s1bytes; /* number of bytes which flow to the first new node when S[0] splits */ /* note: if S[0] splits into 3 nodes, then items do not need to be cut */ short int s2bytes; struct buffer_head * buf_to_free[MAX_FREE_BLOCK]; /* buffers which are to be freed after do_balance finishes by unfix_nodes */ char * vn_buf; /* kmalloced memory. Used to create virtual node and keep map of dirtied bitmap blocks */ int vn_buf_size; /* size of the vn_buf */ struct virtual_node * tb_vn; /* VN starts after bitmap of bitmap blocks */ } ; /* These are modes of balancing */ /* When inserting an item. */ #define M_INSERT 'i' /* When inserting into (directories only) or appending onto an already existant item. */ #define M_PASTE 'p' /* When deleting an item. */ #define M_DELETE 'd' /* When truncating an item or removing an entry from a (directory) item. */ #define M_CUT 'c' /* used when balancing on leaf level skipped (in reiserfsck) */ #define M_INTERNAL 'n' /* When further balancing is not needed, then do_balance does not need to be called. */ #define M_SKIP_BALANCING 's' #define M_CONVERT 'v' /* modes of leaf_move_items */ #define LEAF_FROM_S_TO_L 0 #define LEAF_FROM_S_TO_R 1 #define LEAF_FROM_R_TO_L 2 #define LEAF_FROM_L_TO_R 3 #define LEAF_FROM_S_TO_SNEW 4 #define FIRST_TO_LAST 0 #define LAST_TO_FIRST 1 /* used in do_balance for passing parent of node information that has been gotten from tb struct */ struct buffer_info { struct buffer_head * bi_bh; struct buffer_head * bi_parent; int bi_position; }; /* there are 4 types of items: stat data, directory item, indirect, direct. FIXME: This table does not describe new key format +-------------------+------------+--------------+------------+ | | k_offset | k_uniqueness | mergeable? | +-------------------+------------+--------------+------------+ | stat data | 0 | 0 | no | +-------------------+------------+--------------+------------+ | 1st directory item| DOT_OFFSET |DIRENTRY_UNIQUENESS| no | | non 1st directory | hash value | | yes | | item | | | | +-------------------+------------+--------------+------------+ | indirect item | offset + 1 |TYPE_INDIRECT | if this is not the first indirect item of the object +-------------------+------------+--------------+------------+ | direct item | offset + 1 |TYPE_DIRECT | if not this is not the first direct item of the object +-------------------+------------+--------------+------------+ */ #define KEY_IS_STAT_DATA_KEY(p_s_key) ( get_type (p_s_key) == TYPE_STAT_DATA ) #define KEY_IS_DIRECTORY_KEY(p_s_key) ( get_type (p_s_key) == TYPE_DIRENTRY ) #define KEY_IS_DIRECT_KEY(p_s_key) ( get_type (p_s_key) == TYPE_DIRECT ) #define KEY_IS_INDIRECT_KEY(p_s_key) ( get_type (p_s_key) == TYPE_INDIRECT ) #define I_IS_STAT_DATA_ITEM(p_s_ih) KEY_IS_STAT_DATA_KEY(&((p_s_ih)->ih_key)) #define I_IS_DIRECTORY_ITEM(p_s_ih) KEY_IS_DIRECTORY_KEY(&((p_s_ih)->ih_key)) #define I_IS_DIRECT_ITEM(p_s_ih) KEY_IS_DIRECT_KEY(&((p_s_ih)->ih_key)) #define I_IS_INDIRECT_ITEM(p_s_ih) KEY_IS_INDIRECT_KEY(&((p_s_ih)->ih_key)) #define is_indirect_ih(ih) I_IS_INDIRECT_ITEM(ih) #define is_direct_ih(ih) I_IS_DIRECT_ITEM(ih) #define is_direntry_ih(ih) I_IS_DIRECTORY_ITEM(ih) #define is_stat_data_ih(ih) I_IS_STAT_DATA_ITEM(ih) #define is_indirect_key(key) KEY_IS_INDIRECT_KEY(key) #define is_direct_key(key) KEY_IS_DIRECT_KEY(key) #define is_direntry_key(key) KEY_IS_DIRECTORY_KEY(key) #define is_stat_data_key(key) KEY_IS_STAT_DATA_KEY(key) #define COMP_KEYS comp_keys //#define COMP_SHORT_KEYS comp_short_keys #define not_of_one_file comp_short_keys /* number of blocks pointed to by the indirect item */ #define I_UNFM_NUM(p_s_ih) ( get_ih_item_len(p_s_ih) / UNFM_P_SIZE ) /* the used space within the unformatted node corresponding to pos within the item pointed to by ih */ #define I_POS_UNFM_SIZE(ih,pos,size) (((pos) == I_UNFM_NUM(ih) - 1 ) ? (size) - ih_free_space (ih) : (size)) /* check whether byte number 'offset' is in this item */ #define I_OFF_BYTE_IN_ITEM(p_s_ih, n_offset, n_blocksize) \ ( get_offset(&(p_s_ih)->ih_key) <= (n_offset) && \ get_offset(&(p_s_ih)->ih_key) + get_bytes_number(p_s_ih,n_blocksize) > (n_offset) ) /* get the item header */ #define B_N_PITEM_HEAD(bh,item_num) ( (struct item_head * )((bh)->b_data + BLKH_SIZE) + (item_num) ) /* get key */ #define B_N_PDELIM_KEY(bh,item_num) ( (struct key * )((bh)->b_data + BLKH_SIZE) + (item_num) ) /* get the key */ #define B_N_PKEY(bh,item_num) ( &(B_N_PITEM_HEAD(bh,item_num)->ih_key) ) /* get item body */ #define B_N_PITEM(bh,item_num) ( (bh)->b_data + get_ih_location (B_N_PITEM_HEAD((bh),(item_num)))) /* get the stat data by the buffer header and the item order */ #define B_N_STAT_DATA(bh,nr) \ ( (struct stat_data *)((bh)->b_data+get_ih_location(B_N_PITEM_HEAD((bh),(nr))) ) ) /* following defines use reiserfs buffer header and item header */ /* get item body */ #define B_I_PITEM(bh,ih) ( (bh)->b_data + get_ih_location(ih)) /* get stat-data */ #define B_I_STAT_DATA(bh, ih) ( (struct stat_data * )B_I_PITEM(bh,ih) ) #define MAX_DIRECT_ITEM_LEN(size) ((size) - BLKH_SIZE - 2*IH_SIZE - SD_SIZE - UNFM_P_SIZE) #define MAX_INDIRECT_ITEM_LEN(size) MAX_ITEM_LEN(size) /* indirect items consist of entries which contain blocknrs, pos indicates which entry, and B_I_POS_UNFM_POINTER resolves to the blocknr contained by the entry pos points to */ #define B_I_POS_UNFM_POINTER(bh,ih,pos) (*(((__u32 *)B_I_PITEM(bh,ih)) + (pos))) /***************************************************************************/ /* FUNCTION DECLARATIONS */ /***************************************************************************/ /* stree.c */ void padd_item (char * item, int total_length, int length); int B_IS_IN_TREE(struct buffer_head *); struct key * get_rkey (struct path * p_s_chk_path, reiserfs_filsys_t *); int bin_search (void * p_v_key, void * p_v_base, int p_n_num, int p_n_width, int * p_n_pos); int search_by_key (reiserfs_filsys_t *, struct key *, struct path *, int); int search_by_entry_key (reiserfs_filsys_t *, struct key *, struct path *); int search_for_position_by_key (reiserfs_filsys_t *, struct key *, struct path *); int search_by_objectid (reiserfs_filsys_t *, struct key *, struct path *, int *); void decrement_counters_in_path (struct path * p_s_search_path); void pathrelse (struct path * p_s_search_path); int is_left_mergeable (reiserfs_filsys_t * s, struct path * path); int is_right_mergeable (reiserfs_filsys_t * s, struct path * path); int are_items_mergeable (struct item_head * left, struct item_head * right, int bsize); /* fix_nodes.c */ void * reiserfs_kmalloc (size_t size, int flags, reiserfs_filsys_t * s); void reiserfs_kfree (/*const*/ void * vp, size_t size, reiserfs_filsys_t * s); int fix_nodes (/*struct reiserfs_transaction_handle *th,*/ int n_op_mode, struct tree_balance * p_s_tb, /*int n_pos_in_item,*/ struct item_head * p_s_ins_ih); void unfix_nodes (/*struct reiserfs_transaction_handle *th,*/ struct tree_balance *); void free_buffers_in_tb (struct tree_balance * p_s_tb); void init_path (struct path *); /* prints.c */ /* options */ #define PRINT_TREE_DETAILS 0x1 /* print all items from internal tree */ #define PRINT_DETAILS 0x2 /* print all items from bitmap */ #define PRINT_ITEM_DETAILS 0x4 /* print contents of directory items and stat data items and indirect items */ #define PRINT_DIRECT_ITEMS 0x8 /* print contents of direct items */ void print_tb (int mode, int item_pos, int pos_in_item, struct tree_balance * tb, char * mes); void print_bmap (FILE * fp, reiserfs_filsys_t * fs, int silent); void print_objectid_map (FILE * fp, reiserfs_filsys_t * fs); /* lbalance.c */ int leaf_move_items (int shift_mode, struct tree_balance * tb, int mov_num, int mov_bytes, struct buffer_head * Snew); int leaf_shift_left (struct tree_balance * tb, int shift_num, int shift_bytes); int leaf_shift_right (struct tree_balance * tb, int shift_num, int shift_bytes); void leaf_delete_items (reiserfs_filsys_t *, struct buffer_info * cur_bi, int last_first, int first, int del_num, int del_bytes); void leaf_insert_into_buf (reiserfs_filsys_t *, struct buffer_info * bi, int before, struct item_head * inserted_item_ih, const char * inserted_item_body, int zeros_number); void leaf_paste_in_buffer (reiserfs_filsys_t *, struct buffer_info * bi, int pasted_item_num, int pos_in_item, int paste_size, const char * body, int zeros_number); void leaf_cut_from_buffer (reiserfs_filsys_t *, struct buffer_info * bi, int cut_item_num, int pos_in_item, int cut_size); void leaf_paste_entries (struct buffer_head * bh, int item_num, int before, int new_entry_count, struct reiserfs_de_head * new_dehs, const char * records, int paste_size); void delete_item (reiserfs_filsys_t *, struct buffer_head * bh, int item_num); void cut_entry (reiserfs_filsys_t *, struct buffer_head * bh, int item_num, int entry_num, int del_count); /* ibalance.c */ int balance_internal (struct tree_balance * , int, int, struct item_head * , struct buffer_head **); /* do_balance.c */ void do_balance (struct tree_balance * tb, struct item_head * ih, const char * body, int flag, int zeros_num); void reiserfs_invalidate_buffer (struct tree_balance * tb, struct buffer_head * bh, int); int get_left_neighbor_position (struct tree_balance * tb, int h); int get_right_neighbor_position (struct tree_balance * tb, int h); void replace_key (reiserfs_filsys_t *, struct buffer_head *, int, struct buffer_head *, int); void replace_lkey (struct tree_balance *, int, struct item_head *); void replace_rkey (struct tree_balance *, int, struct item_head *); void make_empty_node (struct buffer_info *); void make_empty_leaf (struct buffer_head *); struct buffer_head * get_FEB (struct tree_balance *); __u32 get_bytes_number (struct item_head * ih, int blocksize); /* hashes.c */ __u32 keyed_hash (const char *msg, int len); __u32 yura_hash (const char *msg, int len); __u32 r5_hash (const char *msg, int len); /* node_format.c */ extern unsigned int get_journal_old_start_must (reiserfs_filsys_t * fs); extern unsigned int get_journal_new_start_must (reiserfs_filsys_t * fs); extern unsigned int get_journal_start_must (reiserfs_filsys_t * fs); /*extern hashf_t hashes [];*/ /* * Local variables: * c-indentation-style: "bsd" * c-basic-offset: 4 * tab-width: 8 * fill-column: 78 * End: */ reiserfsprogs-3.6.9/version.h0000664000077100007710000000032607665645672012003 /* * Copyright 2002-2003 Hans Reiser, licensing governed by reiserfsprogs/README */ #define print_banner(prog) \ fprintf (stderr, "\n<-------------%s, 2003------------->\nreiserfsprogs %s\n\n", \ prog, VERSION) reiserfsprogs-3.6.9/reiserfsprogs.spec0000644000077100007710000000477407705315454013712 %define reiserfsprogsversion 3.6.9 Vendor: Hans Reiser Distribution: Hans Reiser Name: reiserfsprogs Release: 1 Copyright: 2003 Hans Reiser Group: Unsorted Packager: anthon@mnt.org Version: %{reiserfsprogsversion} Summary: utilities belonging to the Reiser filesystem Source: reiserfsprogs-%{reiserfsprogsversion}.tar.gz BuildRoot: %{_tmppath}/rpmbuildroot-%{name} %description The reiserfsprogs package contains programs for creating (mkreiserfs), checking and correcting any inconsistencies (reiserfsck) and resizing (resize_reiserfs) of a reiserfs filesystem. Authors: -------- Hans Reiser Vitaly Fertman Alexander Zarochentcev Vladimir Saveliev %prep # Jeff Johnson states that RPM doesn't delete obviouse crap like / if # buildroot is set differently since RPM 3.0.4 (rpm mailing list 2001-04-10) rm -rf $RPM_BUILD_ROOT %setup -q -n reiserfsprogs-%{reiserfsprogsversion} # %patch %build MANDIR=$(dirname $(dirname $(man -w fsck | cut -d ' ' -f 1))) ./configure --prefix="" --mandir=$MANDIR %{__make} all %install mkdir -p $RPM_BUILD_ROOT/sbin %{__make} DESTDIR=$RPM_BUILD_ROOT install # do we need this? cd $RPM_BUILD_ROOT/sbin %{__ln_s} -f reiserfsck fsck.reiserfs %{__ln_s} -f mkreiserfs mkfs.reiserfs # __os_install_post is normally executed after %install disable it %define ___build_post %{nil} # explicitly call it now, so manpages get compressed, exec's stripped etc. %{?__os_install_post} %define __os_install_post %{nil} # now we have all the files execpt for docs, but their owner is unimportant cd $RPM_BUILD_ROOT %{__rm} -f rpm-filelist # we do not have special directories to make #find . -type d \ # | sed '1,2d;s,^\.,\%attr(-\,root\,root) \%dir ,' >> rpm-filelist find . -type f \ | sed 's,^\.,\%attr(-\,root\,root) ,' | fgrep -v rpm-filelist >> rpm-filelist find . -type l \ | sed 's,^\.,\%attr(-\,root\,root) ,' >> rpm-filelist %post CONFIG=/usr/src/linux/.config if [ -f $CONFIG ] ; then source $CONFIG fi if [ -z $CONFIG_REISERFS_FS ] ; then echo -e "\nIn $CONFIG , you probably have to set:" if [ "$CONFIG_EXPERIMENTAL" != "y" ] ; then echo -e 'CONFIG_EXPERIMENTAL=y' fi echo -e 'CONFIG_REISERFS_FS=y\n or' echo -e 'CONFIG_REISERFS_FS=m' echo -e 'and recompile and reboot your kernel if you cannot use the\nreiserfsprogs utilities' fi %clean %{__rm} -rf $RPM_BUILD_ROOT %files -f %{buildroot}/rpm-filelist %defattr(-,root,root) %doc README reiserfsprogs-3.6.9/COPYING0000664000077100007710000004311007665645672011176 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. reiserfsprogs-3.6.9/CREDITS0000664000077100007710000001034507705265551011154 /* Copyright 1996-2003 by Hans Reiser, licensing governed by reiserfsprogs/README. */ Hans Reiser was the project initiator, source of all funding for the first 5.5 years. He is the architect and official maintainer. Vladimir Saveliev started as the most junior programmer on the team, and became the lead programmer. He is now an experienced highly productive programmer. He wrote the extent handling code for Reiser4, plus parts of the balancing code and file write and file read. Alexander Zarochentcev (zam) wrote the high low priority locking code, online resizer for V3 and V4, online repacker for V4, block allocation code, and major parts of the flush code, and maintains the transaction manager code. We give him the stuff that we know will be hard to debug, or needs to be very cleanly structured. Nikita Danilov wrote most of the core balancing code, plugin infrastructure, and directory code. He steadily worked long hours, and is the reason so much of the Reiser4 plugin infrastructure is well abstracted in its details. The carry function, and the use of non-recursive balancing, are his idea. Vladimir Demidov wrote the parser for sys_reiser4(), the V3 alpha port, part of the V3 journal relocation code, and helped Hans keep the business side of things running. Chris Mason wrote the journaling code for V3, which was enormously more useful to users than just waiting until we could create a wandering log filesystem as Hans would have unwisely done without him. Jeff Mahoney optimized the bitmap scanning code for V3, and performed the big endian cleanups. Elena Gryaznova performed testing and benchmarking. Oleg Drokin was the debugger for V3 during most of the time that V4 was under development, and was quite skilled and fast at it. He wrote the large write optimization of V3. Edward Shushkin wrote the encryption and compression file plugins, and the V3 journal relocation code. Alexander Lyamin keeps our hardware running, and was very generous to our project in many little ways. Vitaly Fertman wrote fsck for V3 and maintains the reiserfsprogs package now. He wrote librepair, userspace plugins repair code, fsck for V4, and worked on developing libreiser4 and userspace plugins with Umka. Yury Umanets (aka Umka) developed libreiser4, userspace plugins, and all userspace tools (reiser4progs) except of fsck. Joshua Macdonald wrote the first draft of the transaction manager. Yuri Rupasov did testing and benchmarking, plus he invented the r5 hash (also used by the dcache code). Yura Rupasov, Anatoly Pinchuk, Igor Krasheninnikov, Grigory Zaigralin, Mikhail Gilula, Igor Zagorovsky, Roman Pozlevich, Konstantin Shvachko, and Joshua MacDonald are former contributors to the project. Jeremy Fitzhardinge wrote the teahash.c code for V3. Colin Plumb also contributed to that. The Defense Advanced Research Projects Agency (DARPA, www.darpa.mil) is the primary sponsor of Reiser4. DARPA does not endorse this project; it merely sponsors it. Continuing core development of ReiserFS is mostly paid for by Hans Reiser from money made selling licenses in addition to the GPL to companies who don't want it known that they use ReiserFS as a foundation for their proprietary product. And my lawyer asked 'People pay you money for this?'. Yup. Life is good. If you buy ReiserFS, you can focus on your value add rather than reinventing an entire FS. BigStorage (www.bigstorage.com) contributes to our general fund every month, and has done so for quite a long time. SuSE (www.suse.com) pays for continuing work on journaling for version 3, paid for much of the previous version 3 work, and is paying for Chris and Jeff to do V3 maintenance. Reiserfs integration in their distro is consistently solid, and they were key to our becoming widely used. Lycos (www.lycos.com) has a support contract with us that consistently comes in just when we would otherwise miss payroll, and that they keep doubling every year. Much thanks to them. Many persons came to www.namesys.com/support.html, and got a question answered for $25, or just gave us a small donation there. Thanks to all of those sponsors, including the secret ones. Without you, we would each still have that day job. reiserfsprogs-3.6.9/mkreiserfs/0000777000077100007710000000000007705315454012363 5reiserfsprogs-3.6.9/mkreiserfs/Makefile.am0000664000077100007710000000027207665645673014354 sbin_PROGRAMS = mkreiserfs mkreiserfs_SOURCES = mkreiserfs.c man_MANS = mkreiserfs.8 EXTRA_DIST = $(man_MANS) LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a reiserfsprogs-3.6.9/mkreiserfs/Makefile.in0000644000077100007710000003225307705315225014345 # Makefile.in generated by automake 1.7.2 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__quote = @am__quote@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ sbin_PROGRAMS = mkreiserfs mkreiserfs_SOURCES = mkreiserfs.c man_MANS = mkreiserfs.8 EXTRA_DIST = $(man_MANS) LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a subdir = mkreiserfs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = sbin_PROGRAMS = mkreiserfs$(EXEEXT) PROGRAMS = $(sbin_PROGRAMS) am_mkreiserfs_OBJECTS = mkreiserfs.$(OBJEXT) mkreiserfs_OBJECTS = $(am_mkreiserfs_OBJECTS) mkreiserfs_LDADD = $(LDADD) mkreiserfs_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \ $(top_srcdir)/reiserfscore/libcore.a mkreiserfs_LDFLAGS = DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/mkreiserfs.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(mkreiserfs_SOURCES) NROFF = nroff MANS = $(man_MANS) DIST_COMMON = Makefile.am Makefile.in SOURCES = $(mkreiserfs_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu mkreiserfs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(sbindir) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f || exit 1; \ else :; fi; \ done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ rm -f $(DESTDIR)$(sbindir)/$$f; \ done clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) mkreiserfs$(EXEEXT): $(mkreiserfs_OBJECTS) $(mkreiserfs_DEPENDENCIES) @rm -f mkreiserfs$(EXEEXT) $(LINK) $(mkreiserfs_LDFLAGS) $(mkreiserfs_OBJECTS) $(mkreiserfs_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkreiserfs.Po@am__quote@ distclean-depend: -rm -rf ./$(DEPDIR) .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: man8dir = $(mandir)/man8 install-man8: $(man8_MANS) $(man_MANS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(man8dir) @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.8*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ *) ext='8' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ done uninstall-man8: @$(NORMAL_UNINSTALL) @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.8*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ *) ext='8' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ rm -f $(DESTDIR)$(man8dir)/$$inst; \ done ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) installdirs: $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(man8dir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-man install-exec-am: install-sbinPROGRAMS install-info: install-info-am install-man: install-man8 installcheck-am: maintainer-clean: maintainer-clean-am maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am uninstall-man uninstall-sbinPROGRAMS uninstall-man: uninstall-man8 .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-sbinPROGRAMS ctags distclean distclean-compile \ distclean-depend distclean-generic distclean-tags distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-man8 install-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-info-am uninstall-man \ uninstall-man8 uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: reiserfsprogs-3.6.9/mkreiserfs/mkreiserfs.80000664000077100007710000000744007705261642014550 .\" -*- nroff -*- .\" Copyright 1996-2003 Hans Reiser. .\" .TH MKREISERFS 8 "April 2003" "Reiserfsprogs-3.6.9" .SH NAME mkreiserfs \- create a Linux ReiserFS file system .SH SYNOPSIS .B mkreiserfs [ \fB-dfV\fR ] [ \fB-b\fR | \fB--block-size \fIN\fR ] [ \fB-h\fR | \fB--hash \fIHASH\fR ] [ \fB-u\fR | \fB--uuid \fIUUID\fR ] [ \fB-l\fR | \fB--label \fILABEL\fR ] [ \fB--format \fIFORMAT\fR ] [ \fB-q\fR | \fB--quiet\fR ] [ \fB-j\fR | \fB--journal-device \fIFILE\fR ] [ \fB-s\fR | \fB--journal-size \fIN\fR ] [ \fB-o\fR | \fB--journal-offset \fIN\fR ] [ \fB-t\fR | \fB--transaction-max-size\fR \fIN\fR ] \fI device\fR [ \fIfilesystem-size\fR ] .SH DESCRIPTION It creates a Linux ReiserFS file system on a device (usually a disk partition). .TP .I device is the special file corresponding to the device (e.g /dev/hdXX for IDE disk partition or /dev/sdXX for SCSI disk partition). .TP .I filesystem-size size of filesystem in blocks. If omitted, it will be determined by .B mkreiserfs automatically. .SH OPTIONS .TP \fB-b\fR | \fB--block-size \fIN\fR \fIN\fR is block size in bytes. 4096 only for now. .TP \fB-h\fR | \fB--hash \fIHASH\fR \fIHASH\fR specifies the name of hash function file names in directories will be sorted with. Choose one of r5, rupasov, tea. r5 is default .TP \fB--format \fIFORMAT\fR \fIFORMAT\fR specifies a format new filsystem has to be of. Choose one of 3.5 and 3.6. If none is specified \fBmkreiserfs\fR will create format 3.6 if running kernel is 2.4, 3.5 if 2.2 is running, and will refuse creation under other kernels. .TP \fB-u\fR | \fB--uuid \fIUUID\fR Set the universally unique identifier (\fB UUID \fR) of the filesystem to \fIUUID\fR (see also \fBuuidgen(8)\fR). The format of the UUID is a series of hex digits separated by hypthens, like this: "c1b9d5a2-f162-11cf-9ece-0020afc76f16". If the option skipped, \fBmkreiserfs\fR generates a new one. .TP \fB-l\fR | \fB--label \fILABEL\fR Set the volume label of the filesystem. \fILABEL\fR can be at most 16 characters long; if it is longer than 16 characters, \fBmkreiserfs\fR will truncate it. .TP \fB-q\fR | \fB--quiet \fR Make \fBmkreiserfs\fR to work quiet without producing any message, progress and question. It is useful if you run \fBmkreiserfs\fR in a script. For use by end users only. .TP \fB-j\fR | \fB--journal-device \fIFILE\fR \fIFILE\fR is name of block device where the file system is to have journal on. .TP \fB-o\fR | \fB--journal-offset \fIN\fR \fIN\fR is an offset where journal starts when it is to be on a separate device. Default is 0. Makes no effect when journal is to be on a host device .TP \fB-s\fR | \fB--journal-size \fIN \fIN\fR is size of journal in blocks. When journal is to be on a separate device - its size defaults to number of blocks that device has. When journal is to be on a host device - its size defaults 8193 and maximal possible value is 32749 (for blocksize 4k). Minimun is 513 for both cases. .TP \fB-t\fR | \fB--transaction-max-size \fIN \fIN\fR is the maximum transaction size parameter for the journal. The default, and max possible, value is 1024 blocks. It should be less than half the size of the journal. If specifed incorrectly, it will be adjusted. .TP \fB-f\fR This forces \fBmkreiserfs\fR to continue even if device is either whole disk, or looks mounted or is not a block device. Specified more than once allows to avoid asking for confirmation. .TP \fB-d\fR This makes \fBmkreiserfs\fR to print debugging information during \fBmkreiserfs\fR. .TP \fB-V\fR This prints version and exits. .SH AUTHOR This version of .B mkreiserfs has been written by Edward Shishkin . .SH BUGS No other blocksizes but 4k are available. Please, report about other bugs to the ReiserFS mail-list .SH SEE ALSO .BR reiserfsck (8), .BR debugreiserfs (8), .BR reiserfstune (8) reiserfsprogs-3.6.9/mkreiserfs/mkreiserfs.c0000664000077100007710000004725707705315156014635 /* * Copyright 1996-2003 by Hans Reiser, licensing governed by * reiserfsprogs/README */ /* mkreiserfs is very simple. It supports only 4k blocks. It skips first 64k of device, and then writes the super block, the needed amount of bitmap blocks (this amount is calculated based on file system size), and root block. Bitmap policy is primitive: it assumes, that device does not have unreadable blocks, and it occupies first blocks for super, bitmap and root blocks. bitmap blocks are interleaved across the disk, mainly to make resizing faster. */ // // FIXME: not 'not-i386' safe. ? Ed // #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "io.h" #include "misc.h" #include "reiserfs_lib.h" #include "../include/config.h" #include "../version.h" char *program_name; static void message( const char * fmt, ... ) __attribute__ ((format (printf, 1, 2))); static void message( const char * fmt, ... ) { char *buf; va_list args; buf = NULL; va_start( args, fmt ); vasprintf( &buf, fmt, args ); va_end( args ); if( buf ) { fprintf( stderr, "%s: %s\n", program_name, buf ); free( buf ); } } static void print_usage_and_exit(void) { fprintf(stderr, "Usage: %s [options] " " device [block-count]\n" "\n" "Options:\n\n" " -b | --block-size N size of file-system block, in bytes\n" " -j | --journal-device FILE path to separate device to hold journal\n" " -s | --journal-size N size of the journal in blocks\n" " -o | --journal-offset N offset of the journal from the start of\n" " the separate device, in blocks\n" " -t | --transaction-max-size N maximal size of transaction, in blocks\n" " -h | --hash rupasov|tea|r5 hash function to use by default\n" " -u | --uuid UUID store UUID in the superblock\n" " -l | --label LABEL store LABEL in the superblock\n" " --format 3.5|3.6 old 3.5 format or newer 3.6\n" " -f | --force specified once, make mkreiserfs the whole\n" " disk, not block device or mounted partition;\n" " specified twice, do not ask for confirmation\n" " -q | --quiet quiet work without messages, progress and\n" " questions. Useful if run in a script. For use\n" " by end users only.\n" " -d | --debug print debugging information during mkreiser\n" " -V print version and exit\n", program_name); exit (1); } // " -B badblocks-file list of all bad blocks on the fs\n" int Create_default_journal = 1; int Block_size = 4096; /* size of journal + 1 block for journal header */ unsigned long Journal_size = 0; int Max_trans_size = 0; //JOURNAL_TRANS_MAX; int Hash = DEFAULT_HASH; int Offset = 0; char * Format; unsigned char UUID[16]; unsigned char * LABEL = NULL; char * badblocks_file; enum mkfs_mode { DEBUG_MODE = 1 << 0, QUIET_MODE = 1 << 1 }; int mode; /* form super block (old one) */ static void make_super_block (reiserfs_filsys_t * fs) { set_sb_umount_state (fs->fs_ondisk_sb, FS_CLEANLY_UMOUNTED); set_sb_tree_height (fs->fs_ondisk_sb, 2); set_sb_hash_code (fs->fs_ondisk_sb, Hash); if (fs->fs_format == REISERFS_FORMAT_3_6) { if (!uuid_is_correct (UUID) && generate_random_uuid (UUID)) reiserfs_warning (stderr, "failed to genetate UUID\n"); memcpy (fs->fs_ondisk_sb->s_uuid, UUID, 16); if (LABEL != NULL) { if (strlen (LABEL) > 16) reiserfs_warning (stderr, "\nSpecified LABEL is longer then 16 " "characters, will be truncated\n\n"); strncpy (fs->fs_ondisk_sb->s_label, LABEL, 16); } set_sb_v2_flag (fs->fs_ondisk_sb, reiserfs_attrs_cleared); } if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb) || strcmp (fs->fs_file_name, fs->fs_j_file_name)) /* either standard journal (and we leave all new fields to be 0) or journal is created on separate device so there is no space on data device which can be used as a journal */ set_sb_reserved_for_journal (fs->fs_ondisk_sb, 0); else set_sb_reserved_for_journal (fs->fs_ondisk_sb, get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)) + 1); } /* wipe out first 64 k of a device and both possible reiserfs super block */ static void invalidate_other_formats (int dev) { struct buffer_head * bh; bh = bread (dev, 0, 64 * 1024); if (!bh) die ("Unable to read first blocks of the device"); #if defined(__sparc__) || defined(__sparc_v9__) memset (bh->b_data + 1024, 0, bh->b_size - 1024); #else memset (bh->b_data, 0, bh->b_size); #endif mark_buffer_uptodate (bh, 1); mark_buffer_dirty (bh); bwrite (bh); brelse (bh); } void zero_journal (reiserfs_filsys_t * fs) { unsigned long start, len, done; struct buffer_head * bh; unsigned int i; fprintf (stdout, "Initializing journal - "); start = get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb)); len = get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)); done = 0; for (i = 0; i < len; i ++) { print_how_far (stdout, &done, len, 1, 1/*be quiet*/); bh = getblk (fs->fs_journal_dev, start + i, fs->fs_blocksize); if (!bh) die ("zero_journal: getblk failed"); memset (bh->b_data, 0, bh->b_size); mark_buffer_dirty (bh); mark_buffer_uptodate (bh, 1); bwrite (bh); brelse (bh); } fprintf (stdout, "\n"); fflush (stdout); } /* this only sets few first bits in bitmap block. Fills not initialized fields of super block (root block and bitmap block numbers) */ static void make_bitmap (reiserfs_filsys_t * fs) { struct reiserfs_super_block * sb = fs->fs_ondisk_sb; unsigned int i; unsigned long block; int marked; marked = 0; /* mark skipped area and super block */ for (i = 0; i <= fs->fs_super_bh->b_blocknr; i ++) { reiserfs_bitmap_set_bit (fs->fs_bitmap2, i); marked ++; } if (fs->fs_badblocks_bm) { for (i = 0; i < get_sb_block_count (sb); i ++) { if (reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i)) { reiserfs_bitmap_set_bit (fs->fs_bitmap2, i); marked ++; } } } /* mark bitmaps as used */ block = fs->fs_super_bh->b_blocknr + 1; for (i = 0; i < get_sb_bmap_nr (sb); i ++) { reiserfs_bitmap_set_bit (fs->fs_bitmap2, block); marked ++; if (spread_bitmaps (fs)) block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8); else block ++; } if (!get_size_of_journal_or_reserved_area (fs->fs_ondisk_sb)) /* root block follows directly super block and first bitmap */ block = fs->fs_super_bh->b_blocknr + 1 + 1; else { /* makr journal blocks as used */ for (i = 0; i <= get_jp_journal_size (sb_jp (sb)); i ++) { reiserfs_bitmap_set_bit (fs->fs_bitmap2, i + get_jp_journal_1st_block (sb_jp (sb))); marked ++; } block = get_jp_journal_1st_block (sb_jp (sb)) + i; } /*get correct block - not journal nor bitmap*/ while (block_of_journal (fs, block) || block_of_bitmap (fs, block)) { block++; } while ((block < get_sb_block_count (sb)) && reiserfs_bitmap_test_bit (fs->fs_bitmap2, block)) { block++; } if (block >= get_sb_block_count (sb)) die ("mkreiserfs: too many bad blocks"); reiserfs_bitmap_set_bit (fs->fs_bitmap2, block); marked ++; set_sb_root_block (sb, block); set_sb_free_blocks (sb, get_sb_block_count (sb) - marked); } static void set_root_dir_nlink (struct item_head * ih, void * sd) { __u32 nlink; nlink = 3; set_sd_nlink (ih, sd, &nlink); } /* form the root block of the tree (the block head, the item head, the root directory) */ static void make_root_block (reiserfs_filsys_t * fs) { struct reiserfs_super_block * sb; struct buffer_head * bh; sb = fs->fs_ondisk_sb; /* get memory for root block */ bh = getblk (fs->fs_dev, get_sb_root_block (sb), get_sb_block_size (sb)); if (!bh) die ("make_root_block: getblk failed"); mark_buffer_uptodate (bh, 1); make_empty_leaf (bh); make_sure_root_dir_exists (fs, set_root_dir_nlink, 0); brelse (bh); /**/ mark_objectid_used (fs, REISERFS_ROOT_PARENT_OBJECTID); mark_objectid_used (fs, REISERFS_ROOT_OBJECTID); } static void report (reiserfs_filsys_t * fs, char * j_filename) { // print_block (stdout, fs, fs->fs_super_bh); struct reiserfs_super_block * sb = (struct reiserfs_super_block *)(fs->fs_super_bh->b_data); struct stat st; dev_t rdev; if (!is_any_reiserfs_magic_string (sb)) return; if (fstat (fs->fs_super_bh->b_dev, &st) == -1) { /*reiserfs_warning (stderr, "fstat failed: %s\n", strerror(errno));*/ rdev = 0; } else rdev = st.st_rdev; if (mode & DEBUG_MODE) { reiserfs_warning (stdout, "Block %lu (0x%x) contains super block. ", fs->fs_super_bh->b_blocknr, rdev); } switch (get_reiserfs_format (sb)) { case REISERFS_FORMAT_3_5: reiserfs_warning (stdout, " Format 3.5 with "); break; case REISERFS_FORMAT_3_6: reiserfs_warning (stdout, "Format 3.6 with "); break; } if (is_reiserfs_jr_magic_string (sb)) reiserfs_warning (stdout, "non-"); reiserfs_warning (stdout, "standard journal\n"); reiserfs_warning (stdout, "Count of blocks on the device: %u\n", get_sb_block_count (sb)); reiserfs_warning (stdout, "Number of blocks consumed by mkreiserfs " "formatting process: %u\n", get_sb_block_count (sb) - get_sb_free_blocks (sb)); if (mode & DEBUG_MODE) reiserfs_warning (stdout, "Free blocks: %u\n", get_sb_free_blocks (sb)); reiserfs_warning (stdout, "Blocksize: %d\n", get_sb_block_size (sb)); reiserfs_warning (stdout, "Hash function used to sort names: %s\n", code2name (get_sb_hash_code (sb))); if (mode & DEBUG_MODE) { reiserfs_warning (stdout, "Number of bitmaps: %u\n", get_sb_bmap_nr (sb)); reiserfs_warning (stdout, "Root block: %u\n", get_sb_root_block (sb)); reiserfs_warning (stdout, "Tree height: %d\n", get_sb_tree_height (sb)); reiserfs_warning (stdout, "Objectid map size %d, max %d\n", get_sb_oid_cursize (sb), get_sb_oid_maxsize (sb)); reiserfs_warning (stdout, "Journal parameters:\n"); print_journal_params (stdout, sb_jp (sb)); } else { if (j_filename && strcmp (j_filename, fs->fs_file_name)) reiserfs_warning (stdout, "Journal Device [0x%x]\n", get_jp_journal_dev (sb_jp (sb))); reiserfs_warning (stdout, "Journal Size %u blocks (first block %u)\n", get_jp_journal_size (sb_jp (sb)) + 1, get_jp_journal_1st_block (sb_jp (sb))); reiserfs_warning (stdout, "Journal Max transaction length %u\n", get_jp_journal_max_trans_len (sb_jp (sb))); } if (j_filename && strcmp (j_filename, fs->fs_file_name)) { reiserfs_warning (stdout, "Space on this device reserved by journal: %u\n", get_sb_reserved_for_journal (sb)); } if (mode & DEBUG_MODE) { reiserfs_warning (stdout, "Filesystem state 0x%x\n", get_sb_fs_state (sb)); reiserfs_warning (stdout, "sb_version %u\n", get_sb_version (sb)); } if (get_reiserfs_format (sb) == REISERFS_FORMAT_3_6) { reiserfs_warning (stdout, "inode generation number: %u\n", get_sb_v2_inode_generation (sb)); reiserfs_warning (stdout, "UUID: %U\n", sb->s_uuid); if (strcmp (sb->s_label, "")) reiserfs_warning (stdout, "LABEL: %s\n", sb->s_label); } return; } static void set_hash_function (char * str) { if (!strcmp (str, "tea")) Hash = TEA_HASH; else if (!strcmp (str, "rupasov")) Hash = YURA_HASH; else if (!strcmp (str, "r5")) Hash = R5_HASH; else message("wrong hash type specified. Using default"); } static void set_reiserfs_version (char * str) { if (!strcmp (str, "3.5")) Format = "3.5"; else { Format = "3.6"; if (strcmp (str, "3.6")) message("wrong reiserfs version specified. Using default 3.6 format"); } } static int str2int (char * str) { int val; char * tmp; val = (int) strtol (str, &tmp, 0); if (*tmp) die ("%s: strtol is unable to make an integer of %s\n", program_name, str); return val; } static void set_block_size (char * str, int *b_size) { *b_size = str2int (str); if (!is_blocksize_correct (*b_size)) die ("%s: wrong blocksize %s specified, only power of 2 from 512-8192 " "interval are supported", program_name, str); } static void set_transaction_max_size (char * str) { Max_trans_size = str2int( str ); } /* reiserfs_create_journal will check this */ static void set_journal_device_size (char * str) { Journal_size = str2int (str); /* if (Journal_size < JOURNAL_MIN_SIZE) die ("%s: wrong journal size specified: %lu. Should be at least %u", program_name, Journal_size + 1, JOURNAL_MIN_SIZE + 1); */ } /* reiserfs_create_journal will check this */ static void set_offset_in_journal_device (char * str) { Offset = str2int( str ); } static int is_journal_default (char * name, char * jname, int blocksize) { if (jname && strcmp (name, jname)) return 0; if (Journal_size && Journal_size != journal_default_size(REISERFS_DISK_OFFSET_IN_BYTES / blocksize, blocksize) + 1) /* journal size is set and it is not default size */ return 0; if (Max_trans_size && Max_trans_size != JOURNAL_TRANS_MAX) return 0; return 1; } /* if running kernel is 2.2 - mkreiserfs creates 3.5 format, if 2.4 - 3.6, otherwise - mkreiserfs fails */ static int select_format (void) { struct utsname sysinfo; if (Format) { if (!strcmp (Format, "3.5")) return REISERFS_FORMAT_3_5; if (strcmp (Format, "3.6")) { message ("Unknown fromat %s specified\n", Format); exit (1); } return REISERFS_FORMAT_3_6; } reiserfs_warning (stdout, "Guessing about desired format.. "); if (uname (&sysinfo) == -1) { message ("could not get system info: %s", strerror(errno)); exit (1); } reiserfs_warning(stdout, "Kernel %s is running.\n", sysinfo.release); if (!strncmp (sysinfo.release, "2.6", 3)) return REISERFS_FORMAT_3_6; if (!strncmp (sysinfo.release, "2.5", 3)) return REISERFS_FORMAT_3_6; if (!strncmp (sysinfo.release, "2.4", 3)) return REISERFS_FORMAT_3_6; if (strncmp (sysinfo.release, "2.2", 3)) { message( "You should run either 2.2 or 2.4 or higher to be able " "to create reiserfs filesystem or specify desired format with --format"); exit (1); } reiserfs_warning(stdout, "Creating filesystem of format 3.5\n"); return REISERFS_FORMAT_3_5; } int main (int argc, char **argv) { reiserfs_filsys_t * fs; int force = 0; char * device_name = NULL; char * jdevice_name = NULL; unsigned long fs_size = 0; int c; static int flag; program_name = strrchr( argv[ 0 ], '/' ); if (program_name) program_name++; else program_name = argv[ 0 ]; if (argc < 2) { print_banner (program_name); print_usage_and_exit (); } while (1) { static struct option options[] = { {"block-size", required_argument, 0, 'b'}, {"journal-device", required_argument, 0, 'j'}, {"journal-size", required_argument, 0, 's'}, {"transaction-max-size", required_argument, 0, 't'}, {"journal-offset", required_argument, 0, 'o'}, {"hash", required_argument, 0, 'h'}, {"uuid", required_argument, 0, 'u'}, {"label", required_argument, 0, 'l'}, {"format", required_argument, &flag, 1}, {0, 0, 0, 0} }; int option_index; c = getopt_long (argc, argv, "b:j:s:t:o:h:u:l:VfdB:q", options, &option_index); if (c == -1) break; switch (c) { case 0: if (flag) { Format = optarg; flag = 0; } break; case 'b': /* --block-size */ set_block_size (optarg, &Block_size); break; case 'j': /* --journal-device */ Create_default_journal = 0; jdevice_name = optarg; break; case 's': /* --journal-size */ Create_default_journal = 0; set_journal_device_size (optarg); break; case 't': /* --transaction-max-size */ Create_default_journal = 0; set_transaction_max_size (optarg); break; case 'o': /* --offset */ Create_default_journal = 0; set_offset_in_journal_device (optarg); break; case 'B': /* --badblock-list */ asprintf (&badblocks_file, "%s", optarg); break; case 'h': /* --hash */ set_hash_function (optarg); break; case 'v': /* --format */ set_reiserfs_version (optarg); break; case 'V': print_usage_and_exit (); case 'f': force ++; break; case 'd': mode |= DEBUG_MODE; break; case 'u': if (set_uuid (optarg, UUID)) { reiserfs_warning(stderr, "wrong UUID specified\n"); return 1; } break; case 'l': LABEL = optarg; break; case 'q': mode |= QUIET_MODE; fclose(stdout); break; default: print_usage_and_exit(); } } /* device to be formatted */ device_name = argv [optind]; if (optind == argc - 2) { /* number of blocks for filesystem is specified */ fs_size = str2int (argv[optind + 1]); } else if (optind == argc - 1) { /* number of blocks is not specified */ fs_size = count_blocks (device_name, Block_size); } else { print_usage_and_exit (); } if (is_journal_default (device_name, jdevice_name, Block_size)) Create_default_journal = 1; if (!(mode & QUIET_MODE) && !can_we_format_it (device_name, force)) return 1; if (jdevice_name) if (!(mode & QUIET_MODE) && !can_we_format_it (jdevice_name, force)) return 1; fs = reiserfs_create (device_name, select_format(), fs_size, Block_size, Create_default_journal, 1); if (!fs) { return 1; } if (!reiserfs_create_journal (fs, jdevice_name, Offset, Journal_size, Max_trans_size)) { return 1; } if (!reiserfs_create_ondisk_bitmap (fs)) { return 1; } /* these fill buffers (super block, first bitmap, root block) with reiserfs structures */ if (uuid_is_correct (UUID) && fs->fs_format != REISERFS_FORMAT_3_6) { reiserfs_warning(stderr, "UUID can be specified only with 3.6 format\n"); return 1; } if (badblocks_file) create_badblock_bitmap (fs, badblocks_file); make_super_block (fs); make_bitmap (fs); make_root_block (fs); // add_badblock_list (fs, 1); report (fs, jdevice_name); if (!force && !(mode & QUIET_MODE)) { fprintf (stderr, "ATTENTION: YOU SHOULD REBOOT AFTER FDISK!\n" "\tALL DATA WILL BE LOST ON '%s'", device_name); if (jdevice_name && strcmp (jdevice_name, device_name)) fprintf (stderr, " AND ON JOURNAL DEVICE '%s'", jdevice_name); if (!user_confirmed (stderr, "!\nContinue (y/n):", "y\n")) return 1; } invalidate_other_formats (fs->fs_dev); zero_journal (fs); reiserfs_close (fs); printf ("Syncing.."); fflush (stdout); sync (); printf ("ok\n"); if (mode & DEBUG_MODE) return 0; misc_print_credit(stdout); printf("\nTell your friends to use the kernel based on 2.4.18 or later " "when you use\nreiserFS. Have fun.\n\n"); printf("ReiserFS is successfully created on %s.\n", device_name); return 0; } /* * Use BSD fomatting. * Local variables: * c-indentation-style: "bsd" * mode-name: "BSDC" * c-basic-offset: 4 * tab-width: 4 * End: */