static int read_bitmaps (struct super_block * s) { int i, bmp; SB_AP_BITMAP (s) = vmalloc (sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR(s)); if (SB_AP_BITMAP (s) == 0) return 1; memset (SB_AP_BITMAP (s), 0, sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR(s)); for (i = 0, bmp = REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize + 1; i < SB_BMAP_NR(s); i++, bmp = s->s_blocksize * 8 * i) { SB_AP_BITMAP (s)[i].bh = sb_getblk (s, bmp); if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) ll_rw_block(READ, 1, &SB_AP_BITMAP(s)[i].bh); } for (i = 0; i < SB_BMAP_NR(s); i++) { wait_on_buffer(SB_AP_BITMAP (s)[i].bh); if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) { reiserfs_warning("sh-2029: reiserfs read_bitmaps: " "bitmap block (#%lu) reading failed\n", SB_AP_BITMAP(s)[i].bh->b_blocknr); for (i = 0; i < SB_BMAP_NR(s); i++) brelse(SB_AP_BITMAP(s)[i].bh); vfree(SB_AP_BITMAP(s)); SB_AP_BITMAP(s) = NULL; return 1; } load_bitmap_info_data (s, SB_AP_BITMAP (s) + i); } return 0; }
static int read_bitmaps (struct super_block * s) { int i, bmp; SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * SB_BMAP_NR(s), GFP_NOFS, s); if (SB_AP_BITMAP (s) == 0) return 1; for (i = 0, bmp = REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize + 1; i < SB_BMAP_NR(s); i++, bmp = s->s_blocksize * 8 * i) { SB_AP_BITMAP (s)[i] = getblk (s->s_dev, bmp, s->s_blocksize); if (!buffer_uptodate(SB_AP_BITMAP(s)[i])) ll_rw_block(READ, 1, SB_AP_BITMAP(s) + i); } for (i = 0; i < SB_BMAP_NR(s); i++) { wait_on_buffer(SB_AP_BITMAP (s)[i]); if (!buffer_uptodate(SB_AP_BITMAP(s)[i])) { reiserfs_warning("sh-2029: reiserfs read_bitmaps: " "bitmap block (#%lu) reading failed\n", SB_AP_BITMAP(s)[i]->b_blocknr); for (i = 0; i < SB_BMAP_NR(s); i++) brelse(SB_AP_BITMAP(s)[i]); reiserfs_kfree(SB_AP_BITMAP(s), sizeof(struct buffer_head *) * SB_BMAP_NR(s), s); SB_AP_BITMAP(s) = NULL; return 1; } } return 0; }
/* * Read the bitmaps */ static int read_bitmaps(struct reiserfs_mount *rmp) { int i, bmap_nr; struct buf *bp = NULL; struct reiserfs_sb_info *sbi = rmp->rm_reiserfs; /* Allocate memory for the table of bitmaps */ SB_AP_BITMAP(sbi) = malloc(sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(sbi), M_REISERFSMNT, M_WAITOK | M_ZERO); if (!SB_AP_BITMAP(sbi)) return (ENOMEM); /* Read all the bitmaps */ for (i = 0, bmap_nr = (REISERFS_DISK_OFFSET_IN_BYTES / sbi->s_blocksize + 1) * btodb(sbi->s_blocksize); i < SB_BMAP_NR(sbi); i++, bmap_nr = sbi->s_blocksize * 8 * i) { SB_AP_BITMAP(sbi)[i].bp_data = malloc(sbi->s_blocksize, M_REISERFSMNT, M_WAITOK | M_ZERO); if (!SB_AP_BITMAP(sbi)[i].bp_data) return (ENOMEM); bread(rmp->rm_devvp, bmap_nr, sbi->s_blocksize, NOCRED, &bp); bcopy(bp->b_data, SB_AP_BITMAP(sbi)[i].bp_data, sbi->s_blocksize); brelse(bp); bp = NULL; /*if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) ll_rw_block(READ, 1, &SB_AP_BITMAP(s)[i].bh);*/ } for (i = 0; i < SB_BMAP_NR(sbi); i++) { /*if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) { reiserfs_warning(s,"sh-2029: reiserfs read_bitmaps: " "bitmap block (#%lu) reading failed", SB_AP_BITMAP(s)[i].bh->b_blocknr); for (i = 0; i < SB_BMAP_NR(s); i++) brelse(SB_AP_BITMAP(s)[i].bh); vfree(SB_AP_BITMAP(s)); SB_AP_BITMAP(s) = NULL; return 1; }*/ load_bitmap_info_data(sbi, SB_AP_BITMAP(sbi) + i); reiserfs_log(LOG_DEBUG, "%d free blocks (starting at block %ld)\n", SB_AP_BITMAP(sbi)[i].free_count, (long)SB_AP_BITMAP(sbi)[i].first_zero_hint); } return (0); }
int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value) { int i, j; if (block == 0 || block >= SB_BLOCK_COUNT (s)) { reiserfs_warning (s, "vs-4010: is_reusable: block number is out of range %lu (%u)", block, SB_BLOCK_COUNT (s)); return 0; } /* it can't be one of the bitmap blocks */ for (i = 0; i < SB_BMAP_NR (s); i ++) if (block == SB_AP_BITMAP (s)[i].bh->b_blocknr) { reiserfs_warning (s, "vs: 4020: is_reusable: " "bitmap block %lu(%u) can't be freed or reused", block, SB_BMAP_NR (s)); return 0; } get_bit_address (s, block, &i, &j); if (i >= SB_BMAP_NR (s)) { reiserfs_warning (s, "vs-4030: is_reusable: there is no so many bitmap blocks: " "block=%lu, bitmap_nr=%d", block, i); return 0; } if ((bit_value == 0 && reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data)) || (bit_value == 1 && reiserfs_test_le_bit(j, SB_AP_BITMAP (s)[i].bh->b_data) == 0)) { reiserfs_warning (s, "vs-4040: is_reusable: corresponding bit of block %lu does not " "match required value (i==%d, j==%d) test_bit==%d", block, i, j, reiserfs_test_le_bit (j, SB_AP_BITMAP (s)[i].bh->b_data)); return 0; } if (bit_value == 0 && block == SB_ROOT_BLOCK (s)) { reiserfs_warning (s, "vs-4050: is_reusable: this is root block (%u), " "it must be busy", SB_ROOT_BLOCK (s)); return 0; } return 1; }
static int bmap_hash_id(struct super_block *s, u32 id) { char * hash_in = NULL; unsigned long hash; unsigned bm; if (id <= 2) { bm = 1; } else { hash_in = (char *)(&id); hash = keyed_hash(hash_in, 4); bm = hash % SB_BMAP_NR(s); if (!bm) bm = 1; } /* this can only be true when SB_BMAP_NR = 1 */ if (bm >= SB_BMAP_NR(s)) bm = 0; return bm; }
// // a portion of this function, particularly the VFS interface portion, // was derived from minix or ext2's analog and evolved as the // prototype did. You should be able to tell which portion by looking // at the ext2 code and comparing. It's subfunctions contain no code // used as a template unless they are so labeled. // static void reiserfs_put_super (struct super_block * s) { int i; struct reiserfs_transaction_handle th ; /* change file system state to current state if it was mounted with read-write permissions */ if (!(s->s_flags & MS_RDONLY)) { journal_begin(&th, s, 10) ; reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ; set_sb_state( SB_DISK_SUPER_BLOCK(s), s->u.reiserfs_sb.s_mount_state ); journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s)); } /* note, journal_release checks for readonly mount, and can decide not ** to do a journal_end */ journal_release(&th, s) ; for (i = 0; i < SB_BMAP_NR (s); i ++) brelse (SB_AP_BITMAP (s)[i]); reiserfs_kfree (SB_AP_BITMAP (s), sizeof (struct buffer_head *) * SB_BMAP_NR (s), s); brelse (SB_BUFFER_WITH_SB (s)); print_statistics (s); if (s->u.reiserfs_sb.s_kmallocs != 0) { reiserfs_warning ("vs-2004: reiserfs_put_super: allocated memory left %d\n", s->u.reiserfs_sb.s_kmallocs); } reiserfs_proc_unregister( s, "journal" ); reiserfs_proc_unregister( s, "oidmap" ); reiserfs_proc_unregister( s, "on-disk-super" ); reiserfs_proc_unregister( s, "bitmap" ); reiserfs_proc_unregister( s, "per-level" ); reiserfs_proc_unregister( s, "super" ); reiserfs_proc_unregister( s, "version" ); reiserfs_proc_info_done( s ); return; }
void reiserfs_free_bitmap_blocks (reiserfs_filsys_t fs) { int i; /* release bitmaps if they were read */ if (SB_AP_BITMAP (fs)) { for (i = 0; i < SB_BMAP_NR (fs); i ++) brelse (SB_AP_BITMAP (fs) [i]); freemem (SB_AP_BITMAP (fs)); } }
/* after journal replay, reread all bitmap and super blocks */ static int reread_meta_blocks(struct super_block *s) { int i ; ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s))) ; wait_on_buffer(SB_BUFFER_WITH_SB(s)) ; if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) { printk("reread_meta_blocks, error reading the super\n") ; return 1 ; } for (i = 0; i < SB_BMAP_NR(s) ; i++) { ll_rw_block(READ, 1, &(SB_AP_BITMAP(s)[i].bh)) ; wait_on_buffer(SB_AP_BITMAP(s)[i].bh) ; if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) { printk("reread_meta_blocks, error reading bitmap block number %d at %ld\n", i, SB_AP_BITMAP(s)[i].bh->b_blocknr) ; return 1 ; } }
int data_block (struct super_block * s, __u32 block) { int i; if (block == REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize) /* super block, not data block */ return 0; for (i = 0; i < SB_BMAP_NR (s); i ++) if (block == SB_AP_BITMAP (s)[i]->b_blocknr) /* bitmap block, not data block */ return 0; if (journal_block (s, block)) return 0; return 1; }
static int get_total_block_number (void) { int i, j; int retval = 0; retval = 0; if (opt_pack_all) retval = SB_BLOCK_COUNT (&g_sb); else { for (i = 0; i < SB_BMAP_NR (&g_sb); i ++) { for (j = 0; j < g_sb.s_blocksize * 8; j ++) if (i * g_sb.s_blocksize * 8 + j < SB_BLOCK_COUNT (&g_sb) && test_bit (j, SB_AP_BITMAP (&g_sb)[i]->b_data)) retval ++; } } return retval; }
int shrink_fs(reiserfs_filsys_t reiserfs, unsigned long blocks) { unsigned long n_root_block; unsigned int bmap_nr_new; unsigned long int i; fs = reiserfs; rs = fs->s_rs; /* 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]:" ); c = getchar(); if (c != 'y' && c != 'Y') exit(1); } bmap_nr_new = (blocks - 1) / (8 * fs->s_blocksize) + 1; /* is shrinking possible ? */ if (rs_block_count(rs) - blocks > rs_free_blocks(rs) + rs_bmap_nr(rs) - bmap_nr_new) { fprintf(stderr, "resize_reiserfs: can\'t shrink fs; too many blocks already allocated\n"); return -1; } reiserfs_reopen(fs, O_RDWR); set_state (fs->s_rs, REISERFS_ERROR_FS); mark_buffer_uptodate(SB_BUFFER_WITH_SB(fs), 1); mark_buffer_dirty(SB_BUFFER_WITH_SB(fs)); bwrite(SB_BUFFER_WITH_SB(fs)); /* calculate number of data blocks */ blocks_used = SB_BLOCK_COUNT(fs) - SB_FREE_BLOCKS(fs) - SB_BMAP_NR(fs) - SB_JOURNAL_SIZE(fs) - REISERFS_DISK_OFFSET_IN_BYTES / fs->s_blocksize - 2; /* superblock itself and 1 descriptor after the journal */ bmp = reiserfs_create_bitmap(rs_block_count(rs)); reiserfs_fetch_disk_bitmap(bmp, fs); unused_block = 1; if (opt_verbose) { printf("Processing the tree: "); fflush(stdout); } n_root_block = move_formatted_block(rs_root_block(rs), blocks, 0); if (n_root_block) { set_root_block (rs, 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 0 printf("check for used blocks in truncated region\n"); { unsigned long l; for (l = blocks; l < rs_block_count(rs); l++) if (is_block_used(bmp, l)) printf("<%lu>", l); printf("\n"); } #endif /* 0 */ reiserfs_free_bitmap_blocks(fs); set_free_blocks (rs, rs_free_blocks(rs) - (rs_block_count(rs) - blocks) + (rs_bmap_nr(rs) - bmap_nr_new)); set_block_count (rs, blocks); set_bmap_nr (rs, bmap_nr_new); reiserfs_read_bitmap_blocks(fs); for (i = blocks; i < bmap_nr_new * fs->s_blocksize; i++) reiserfs_bitmap_set_bit(bmp, i); #if 0 PUT_SB_FREE_BLOCKS(s, SB_FREE_BLOCKS(s) - (SB_BLOCK_COUNT(s) - blocks) + (SB_BMAP_NR(s) - bmap_nr_new)); PUT_SB_BLOCK_COUNT(s, blocks); PUT_SB_BMAP_NR(s, bmap_nr_new); #endif reiserfs_flush_bitmap(bmp, fs); return 0; }
/* it searches for a window of zero bits with given minimum and maximum lengths in one bitmap * block; */ static int scan_bitmap_block (struct reiserfs_transaction_handle *th, int bmap_n, int *beg, int boundary, int min, int max, int unfm) { struct super_block *s = th->t_super; struct reiserfs_bitmap_info *bi=&SB_AP_BITMAP(s)[bmap_n]; int end, next; int org = *beg; BUG_ON (!th->t_trans_id); RFALSE(bmap_n >= SB_BMAP_NR (s), "Bitmap %d is out of range (0..%d)",bmap_n, SB_BMAP_NR (s) - 1); PROC_INFO_INC( s, scan_bitmap.bmap ); /* this is unclear and lacks comments, explain how journal bitmaps work here for the reader. Convey a sense of the design here. What is a window? */ /* - I mean `a window of zero bits' as in description of this function - Zam. */ if ( !bi ) { reiserfs_warning (s, "NULL bitmap info pointer for bitmap %d", bmap_n); return 0; } if (buffer_locked (bi->bh)) { PROC_INFO_INC( s, scan_bitmap.wait ); __wait_on_buffer (bi->bh); } while (1) { cont: if (bi->free_count < min) return 0; // No free blocks in this bitmap /* search for a first zero bit -- beggining of a window */ *beg = reiserfs_find_next_zero_le_bit ((unsigned long*)(bi->bh->b_data), boundary, *beg); if (*beg + min > boundary) { /* search for a zero bit fails or the rest of bitmap block * cannot contain a zero window of minimum size */ return 0; } if (unfm && is_block_in_journal(s,bmap_n, *beg, beg)) continue; /* first zero bit found; we check next bits */ for (end = *beg + 1;; end ++) { if (end >= *beg + max || end >= boundary || reiserfs_test_le_bit (end, bi->bh->b_data)) { next = end; break; } /* finding the other end of zero bit window requires looking into journal structures (in * case of searching for free blocks for unformatted nodes) */ if (unfm && is_block_in_journal(s, bmap_n, end, &next)) break; } /* now (*beg) points to beginning of zero bits window, * (end) points to one bit after the window end */ if (end - *beg >= min) { /* it seems we have found window of proper size */ int i; reiserfs_prepare_for_journal (s, bi->bh, 1); /* try to set all blocks used checking are they still free */ for (i = *beg; i < end; i++) { /* It seems that we should not check in journal again. */ if (reiserfs_test_and_set_le_bit (i, bi->bh->b_data)) { /* bit was set by another process * while we slept in prepare_for_journal() */ PROC_INFO_INC( s, scan_bitmap.stolen ); if (i >= *beg + min) { /* we can continue with smaller set of allocated blocks, * if length of this set is more or equal to `min' */ end = i; break; } /* otherwise we clear all bit were set ... */ while (--i >= *beg) reiserfs_test_and_clear_le_bit (i, bi->bh->b_data); reiserfs_restore_prepared_buffer (s, bi->bh); *beg = org; /* ... and search again in current block from beginning */ goto cont; } } bi->free_count -= (end - *beg); journal_mark_dirty (th, s, bi->bh); /* free block count calculation */ reiserfs_prepare_for_journal (s, SB_BUFFER_WITH_SB(s), 1); PUT_SB_FREE_BLOCKS(s, SB_FREE_BLOCKS(s) - (end - *beg)); journal_mark_dirty (th, s, SB_BUFFER_WITH_SB(s)); return end - (*beg); } else { *beg = next; } } }
int reiserfs_resize (struct super_block * s, unsigned long block_count_new) { struct reiserfs_super_block * sb; struct reiserfs_bitmap_info *bitmap; struct buffer_head * bh; struct reiserfs_transaction_handle th; unsigned int bmap_nr_new, bmap_nr; unsigned int block_r_new, block_r; struct reiserfs_list_bitmap * jb; struct reiserfs_list_bitmap jbitmap[JOURNAL_NUM_BITMAPS]; unsigned long int block_count, free_blocks; int i; int copy_size ; sb = SB_DISK_SUPER_BLOCK(s); if (SB_BLOCK_COUNT(s) >= block_count_new) { printk("can\'t shrink filesystem on-line\n"); return -EINVAL; } /* check the device size */ bh = sb_bread(s, block_count_new - 1); if (!bh) { printk("reiserfs_resize: can\'t read last block\n"); return -EINVAL; } bforget(bh); /* old disk layout detection; those partitions can be mounted, but * cannot be resized */ if (SB_BUFFER_WITH_SB(s)->b_blocknr * SB_BUFFER_WITH_SB(s)->b_size != REISERFS_DISK_OFFSET_IN_BYTES ) { printk("reiserfs_resize: unable to resize a reiserfs without distributed bitmap (fs version < 3.5.12)\n"); return -ENOTSUPP; } /* count used bits in last bitmap block */ block_r = SB_BLOCK_COUNT(s) - (SB_BMAP_NR(s) - 1) * s->s_blocksize * 8; /* count bitmap blocks in new fs */ bmap_nr_new = block_count_new / ( s->s_blocksize * 8 ); block_r_new = block_count_new - bmap_nr_new * s->s_blocksize * 8; if (block_r_new) bmap_nr_new++; else block_r_new = s->s_blocksize * 8; /* save old values */ block_count = SB_BLOCK_COUNT(s); bmap_nr = SB_BMAP_NR(s); /* resizing of reiserfs bitmaps (journal and real), if needed */ if (bmap_nr_new > bmap_nr) { /* reallocate journal bitmaps */ if (reiserfs_allocate_list_bitmaps(s, jbitmap, bmap_nr_new) < 0) { printk("reiserfs_resize: unable to allocate memory for journal bitmaps\n"); unlock_super(s) ; return -ENOMEM ; } /* the new journal bitmaps are zero filled, now we copy in the bitmap ** node pointers from the old journal bitmap structs, and then ** transfer the new data structures into the journal struct. ** ** using the copy_size var below allows this code to work for ** both shrinking and expanding the FS. */ copy_size = bmap_nr_new < bmap_nr ? bmap_nr_new : bmap_nr ; copy_size = copy_size * sizeof(struct reiserfs_list_bitmap_node *) ; for (i = 0 ; i < JOURNAL_NUM_BITMAPS ; i++) { struct reiserfs_bitmap_node **node_tmp ; jb = SB_JOURNAL(s)->j_list_bitmap + i ; memcpy(jbitmap[i].bitmaps, jb->bitmaps, copy_size) ; /* just in case vfree schedules on us, copy the new ** pointer into the journal struct before freeing the ** old one */ node_tmp = jb->bitmaps ; jb->bitmaps = jbitmap[i].bitmaps ; vfree(node_tmp) ; } /* allocate additional bitmap blocks, reallocate array of bitmap * block pointers */ bitmap = vmalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new); if (!bitmap) { printk("reiserfs_resize: unable to allocate memory.\n"); return -ENOMEM; } memset (bitmap, 0, sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR(s)); for (i = 0; i < bmap_nr; i++) bitmap[i] = SB_AP_BITMAP(s)[i]; for (i = bmap_nr; i < bmap_nr_new; i++) { bitmap[i].bh = sb_getblk(s, i * s->s_blocksize * 8); memset(bitmap[i].bh->b_data, 0, sb_blocksize(sb)); reiserfs_test_and_set_le_bit(0, bitmap[i].bh->b_data); set_buffer_uptodate(bitmap[i].bh); mark_buffer_dirty(bitmap[i].bh) ; sync_dirty_buffer(bitmap[i].bh); // update bitmap_info stuff bitmap[i].first_zero_hint=1; bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; } /* free old bitmap blocks array */ vfree(SB_AP_BITMAP(s)); SB_AP_BITMAP(s) = bitmap; } /* begin transaction */ journal_begin(&th, s, 10); /* correct last bitmap blocks in old and new disk layout */ reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr - 1].bh, 1); for (i = block_r; i < s->s_blocksize * 8; i++) reiserfs_test_and_clear_le_bit(i, SB_AP_BITMAP(s)[bmap_nr - 1].bh->b_data); SB_AP_BITMAP(s)[bmap_nr - 1].free_count += s->s_blocksize * 8 - block_r; if ( !SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint) SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint = block_r; journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1].bh); reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh, 1); for (i = block_r_new; i < s->s_blocksize * 8; i++) reiserfs_test_and_set_le_bit(i, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh->b_data); journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh); SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count -= s->s_blocksize * 8 - block_r_new; /* Extreme case where last bitmap is the only valid block in itself. */ if ( !SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count ) SB_AP_BITMAP(s)[bmap_nr_new - 1].first_zero_hint = 0; /* update super */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ; free_blocks = SB_FREE_BLOCKS(s); PUT_SB_FREE_BLOCKS(s, free_blocks + (block_count_new - block_count - (bmap_nr_new - bmap_nr))); PUT_SB_BLOCK_COUNT(s, block_count_new); PUT_SB_BMAP_NR(s, bmap_nr_new); s->s_dirt = 1; journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); SB_JOURNAL(s)->j_must_wait = 1; journal_end(&th, s, 10); return 0; }
// // a portion of this function, particularly the VFS interface portion, // was derived from minix or ext2's analog and evolved as the // prototype did. You should be able to tell which portion by looking // at the ext2 code and comparing. It's subfunctions contain no code // used as a template unless they are so labeled. // static struct super_block * reiserfs_read_super (struct super_block * s, void * data, int silent) { int size; struct inode *root_inode; kdev_t dev = s->s_dev; int j; extern int *blksize_size[]; struct reiserfs_transaction_handle th ; int old_format = 0; unsigned long blocks; int jinit_done = 0 ; struct reiserfs_iget4_args args ; int old_magic; struct reiserfs_super_block * rs; memset (&s->u.reiserfs_sb, 0, sizeof (struct reiserfs_sb_info)); if (parse_options ((char *) data, &(s->u.reiserfs_sb.s_mount_opt), &blocks) == 0) { return NULL; } if (blocks) { printk("reserfs: resize option for remount only\n"); return NULL; } if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)] != 0) { /* as blocksize is set for partition we use it */ size = blksize_size[MAJOR(dev)][MINOR(dev)]; } else { size = BLOCK_SIZE; set_blocksize (s->s_dev, BLOCK_SIZE); } /* read block (64-th 1k block), which can contain reiserfs super block */ if (read_super_block (s, size, REISERFS_DISK_OFFSET_IN_BYTES)) { // try old format (undistributed bitmap, super block in 8-th 1k block of a device) if (read_super_block (s, size, REISERFS_OLD_DISK_OFFSET_IN_BYTES)) goto error; else old_format = 1; } rs = SB_DISK_SUPER_BLOCK (s); s->u.reiserfs_sb.s_mount_state = SB_REISERFS_STATE(s); s->u.reiserfs_sb.s_mount_state = REISERFS_VALID_FS ; if (old_format ? read_old_bitmaps(s) : read_bitmaps(s)) { printk ("reiserfs_read_super: unable to read bitmap\n"); goto error; } #ifdef CONFIG_REISERFS_CHECK printk("reiserfs:warning: CONFIG_REISERFS_CHECK is set ON\n"); printk("reiserfs:warning: - it is slow mode for debugging.\n"); #endif // set_device_ro(s->s_dev, 1) ; if (journal_init(s)) { printk("reiserfs_read_super: unable to initialize journal space\n") ; goto error ; } else { jinit_done = 1 ; /* once this is set, journal_release must be called ** if we error out of the mount */ } if (reread_meta_blocks(s)) { printk("reiserfs_read_super: unable to reread meta blocks after journal init\n") ; goto error ; } if (replay_only (s)) goto error; if (is_read_only(s->s_dev) && !(s->s_flags & MS_RDONLY)) { printk("clm-7000: Detected readonly device, marking FS readonly\n") ; s->s_flags |= MS_RDONLY ; } args.objectid = REISERFS_ROOT_PARENT_OBJECTID ; root_inode = iget4 (s, REISERFS_ROOT_OBJECTID, 0, (void *)(&args)); if (!root_inode) { printk ("reiserfs_read_super: get root inode failed\n"); goto error; } s->s_root = d_alloc_root(root_inode); if (!s->s_root) { iput(root_inode); goto error; } // define and initialize hash function s->u.reiserfs_sb.s_hash_function = hash_function (s); if (s->u.reiserfs_sb.s_hash_function == NULL) { dput(s->s_root) ; s->s_root = NULL ; goto error ; } rs = SB_DISK_SUPER_BLOCK (s); old_magic = strncmp (rs->s_magic, REISER2FS_SUPER_MAGIC_STRING, strlen ( REISER2FS_SUPER_MAGIC_STRING)); if (!old_magic) set_bit(REISERFS_3_6, &(s->u.reiserfs_sb.s_properties)); else set_bit(REISERFS_3_5, &(s->u.reiserfs_sb.s_properties)); if (!(s->s_flags & MS_RDONLY)) { journal_begin(&th, s, 1) ; reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ; set_sb_state( rs, REISERFS_ERROR_FS ); if ( old_magic ) { // filesystem created under 3.5.x found if (convert_reiserfs (s)) { reiserfs_warning("reiserfs: converting 3.5.x filesystem to the new format\n") ; // after this 3.5.x will not be able to mount this partition memcpy (rs->s_magic, REISER2FS_SUPER_MAGIC_STRING, sizeof (REISER2FS_SUPER_MAGIC_STRING)); reiserfs_convert_objectid_map_v1(s) ; set_bit(REISERFS_3_6, &(s->u.reiserfs_sb.s_properties)); clear_bit(REISERFS_3_5, &(s->u.reiserfs_sb.s_properties)); } else { reiserfs_warning("reiserfs: using 3.5.x disk format\n") ; } } journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s)); journal_end(&th, s, 1) ; /* look for files which were to be removed in previous session */ finish_unfinished (s); s->s_dirt = 0; } else { if ( old_magic ) { reiserfs_warning("reiserfs: using 3.5.x disk format\n") ; } } // mark hash in super block: it could be unset. overwrite should be ok set_sb_hash_function_code( rs, function2code(s->u.reiserfs_sb.s_hash_function ) ); handle_attrs( s ); reiserfs_proc_info_init( s ); reiserfs_proc_register( s, "version", reiserfs_version_in_proc ); reiserfs_proc_register( s, "super", reiserfs_super_in_proc ); reiserfs_proc_register( s, "per-level", reiserfs_per_level_in_proc ); reiserfs_proc_register( s, "bitmap", reiserfs_bitmap_in_proc ); reiserfs_proc_register( s, "on-disk-super", reiserfs_on_disk_super_in_proc ); reiserfs_proc_register( s, "oidmap", reiserfs_oidmap_in_proc ); reiserfs_proc_register( s, "journal", reiserfs_journal_in_proc ); init_waitqueue_head (&(s->u.reiserfs_sb.s_wait)); printk("%s\n", reiserfs_get_version_string()) ; return s; error: if (jinit_done) { /* kill the commit thread, free journal ram */ journal_release_error(NULL, s) ; } if (SB_DISK_SUPER_BLOCK (s)) { for (j = 0; j < SB_BMAP_NR (s); j ++) { if (SB_AP_BITMAP (s)) brelse (SB_AP_BITMAP (s)[j]); } if (SB_AP_BITMAP (s)) reiserfs_kfree (SB_AP_BITMAP (s), sizeof (struct buffer_head *) * SB_BMAP_NR (s), s); } if (SB_BUFFER_WITH_SB (s)) brelse(SB_BUFFER_WITH_SB (s)); return NULL; }
struct super_block * reiserfs_read_super (struct super_block * s, void * data, int silent) { int size; struct inode *root_inode; kdev_t dev = s->s_dev; int j; extern int *blksize_size[]; struct reiserfs_transaction_handle th ; int old_format = 0; unsigned long blocks; int jinit_done = 0 ; memset (&s->u.reiserfs_sb, 0, sizeof (struct reiserfs_sb_info)); if (parse_options ((char *) data, &(s->u.reiserfs_sb.s_mount_opt), &blocks) == 0) { s->s_dev = 0; return NULL; } if (blocks) { printk("reserfs: resize option for remount only\n"); return NULL; } MOD_INC_USE_COUNT; lock_super (s); if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)] != 0) { /* as blocksize is set for partition we use it */ size = blksize_size[MAJOR(dev)][MINOR(dev)]; } else { size = BLOCK_SIZE; set_blocksize (s->s_dev, BLOCK_SIZE); } /* read block, containing reiserfs super block (it is stored at REISERFS_FIRST_BLOCK-th 1K block) */ if (read_super_block (s, size)) { if(read_old_super_block(s,size)) goto error; else old_format = 1; } s->u.reiserfs_sb.s_mount_state = le16_to_cpu (SB_DISK_SUPER_BLOCK (s)->s_state); /* journal victim */ s->u.reiserfs_sb.s_mount_state = REISERFS_VALID_FS ; /* reiserfs can not be mounted when it propably contains errors */ #if 0 /* journal victim */ if (le16_to_cpu (SB_DISK_SUPER_BLOCK (s)->s_state) != REISERFS_VALID_FS) { printk ("reiserfs_read_super: mounting unchecked fs, run reiserfsck first\n"); goto error; } #endif if (old_format ? read_old_bitmaps(s) : read_bitmaps(s)) { printk ("reiserfs_read_super: unable to read bitmap\n"); goto error; } if (journal_init(s)) { printk("reiserfs_read_super: unable to initialize journal space\n") ; goto error ; } else { jinit_done = 1 ; /* once this is set, journal_release must be called ** if we error out of the mount */ } if (reread_meta_blocks(s)) { printk("reiserfs_read_super: unable to reread meta blocks after journal init\n") ; goto error ; } if (replay_only (s)) goto error; /*s->s_op = &reiserfs_sops;*/ /* get root directory inode */ store_key (s, &root_key); root_inode = iget (s, root_key.k_objectid); forget_key (s, &root_key); if (!root_inode) { printk ("reiserfs_read_super: get root inode failed\n"); goto error; } s->s_root = d_alloc_root(root_inode, NULL); if (!s->s_root) { iput(root_inode); goto error; } if (!(s->s_flags & MS_RDONLY)) { SB_DISK_SUPER_BLOCK (s)->s_state = cpu_to_le16 (REISERFS_ERROR_FS); /* mark_buffer_dirty (SB_BUFFER_WITH_SB (s), 1); */ journal_begin(&th, s, 1) ; journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s)); journal_end(&th, s, 1) ; s->s_dirt = 0; } /*s->u.reiserfs_sb.unpreserve = dont_preserve (s) ? 0 : unpreserve;*/ /* we have to do this to make journal writes work correctly */ SB_BUFFER_WITH_SB(s)->b_end_io = reiserfs_end_buffer_io_sync ; unlock_super (s); print_credits() ; printk("%s\n", reiserfs_get_version_string()) ; return s; error: if (jinit_done) { /* kill the commit thread, free journal ram */ journal_release_error(NULL, s) ; } if (SB_DISK_SUPER_BLOCK (s)) { for (j = 0; j < le16_to_cpu (SB_DISK_SUPER_BLOCK (s)->s_bmap_nr); j ++) { if (SB_AP_BITMAP (s)) brelse (SB_AP_BITMAP (s)[j]); /* if (SB_AP_CAUTIOUS_BITMAP (s)) brelse (SB_AP_CAUTIOUS_BITMAP (s)[j]); */ } if (SB_AP_BITMAP (s)) reiserfs_kfree (SB_AP_BITMAP (s), sizeof (struct buffer_head *) * SB_BMAP_NR (s), s); /* if (SB_AP_CAUTIOUS_BITMAP (s)) reiserfs_kfree (SB_AP_CAUTIOUS_BITMAP (s), sizeof (struct buffer_head *) * SB_BMAP_NR (s), s); */ } if (SB_BUFFER_WITH_SB (s)) brelse(SB_BUFFER_WITH_SB (s)); s->s_dev = 0; unlock_super(s); MOD_DEC_USE_COUNT; return NULL; }
void reiserfs_put_super (struct super_block * s) { int i; kdev_t dev = s->s_dev; struct reiserfs_transaction_handle th ; journal_begin(&th, s, 10) ; if (s->u.reiserfs_sb.lock_preserve) reiserfs_panic (s, "vs-2000: reiserfs_put_super: lock_preserve == %d", s->u.reiserfs_sb.lock_preserve); /* change file system state to current state if it was mounted with read-write permissions */ if (!(s->s_flags & MS_RDONLY)) { SB_REISERFS_STATE (s) = le16_to_cpu (s->u.reiserfs_sb.s_mount_state); /* mark_buffer_dirty (SB_BUFFER_WITH_SB (s), 1); */ journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s)); } #if 0 if (maybe_free_preserve_list (s) == 0) { reiserfs_warning ("vs-2003: reiserfs_put_super: there are %ld buffers to write\n", s->u.reiserfs_sb.s_suspected_recipient_count); #ifdef REISERFS_CHECK preserve_trace_print_srs (s); #endif /* mark_suspected_recipients_dirty (&th, dev); journal victim */ fsync_dev (dev); s->u.reiserfs_sb.s_suspected_recipient_count = 0; #ifdef REISERFS_CHECK preserve_trace_reset_suspected_recipients (s); #endif maybe_free_preserve_list (s); } #endif #if 0 /* journal victim */ for (i = 0; i < SB_BMAP_NR (s); i ++) { /* update cautious bitmap */ if (memcmp (SB_AP_BITMAP (s)[i]->b_data, SB_AP_CAUTIOUS_BITMAP (s)[i], SB_AP_BITMAP (s)[i]->b_size)) { memcpy (SB_AP_CAUTIOUS_BITMAP (s)[i]->b_data, SB_AP_BITMAP (s)[i]->b_data, SB_AP_BITMAP (s)[i]->b_size); mark_buffer_dirty (SB_AP_CAUTIOUS_BITMAP (s)[i], 1); ll_rw_block (WRITE, 1, &SB_AP_CAUTIOUS_BITMAP (s)[i]); } } #endif /* journal victim */ journal_release(&th, s) ; /* reiserfs_sync_all_buffers(s->s_dev, 1) ; journal does not need this any more */ /* wait on write completion */ for (i = 0; i < SB_BMAP_NR (s); i ++) { /* wait_on_buffer (SB_AP_CAUTIOUS_BITMAP (s)[i]); */ /* brelse (SB_AP_CAUTIOUS_BITMAP (s)[i]); */ brelse (SB_AP_BITMAP (s)[i]); } reiserfs_kfree (SB_AP_BITMAP (s), sizeof (struct buffer_head *) * SB_BMAP_NR (s), s); /* reiserfs_kfree (SB_AP_CAUTIOUS_BITMAP (s), sizeof (struct buffer_head *) * SB_BMAP_NR (s), s); */ brelse (SB_BUFFER_WITH_SB (s)); print_statistics (s); if (s->u.reiserfs_sb.s_kmallocs != 0) { reiserfs_warning ("vs-2004: reiserfs_put_super: aloocated memory left %d\n", s->u.reiserfs_sb.s_kmallocs); } s->s_dev = 0; fixup_reiserfs_buffers (dev); MOD_DEC_USE_COUNT; return; }
/* * Common code for mount and mountroot */ static int reiserfs_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td) { int error, old_format = 0; struct reiserfs_mount *rmp; struct reiserfs_sb_info *sbi; struct reiserfs_super_block *rs; struct cdev *dev; struct g_consumer *cp; struct bufobj *bo; //ronly = (mp->mnt_flag & MNT_RDONLY) != 0; dev = devvp->v_rdev; dev_ref(dev); DROP_GIANT(); g_topology_lock(); error = g_vfs_open(devvp, &cp, "reiserfs", /* read-only */ 0); g_topology_unlock(); PICKUP_GIANT(); VOP_UNLOCK(devvp, 0); if (error) { dev_rel(dev); return (error); } bo = &devvp->v_bufobj; bo->bo_private = cp; bo->bo_ops = g_vfs_bufops; if (devvp->v_rdev->si_iosize_max != 0) mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max; if (mp->mnt_iosize_max > MAXPHYS) mp->mnt_iosize_max = MAXPHYS; rmp = NULL; sbi = NULL; /* rmp contains any information about this specific mount */ rmp = malloc(sizeof *rmp, M_REISERFSMNT, M_WAITOK | M_ZERO); if (!rmp) { error = (ENOMEM); goto out; } sbi = malloc(sizeof *sbi, M_REISERFSMNT, M_WAITOK | M_ZERO); if (!sbi) { error = (ENOMEM); goto out; } rmp->rm_reiserfs = sbi; rmp->rm_mountp = mp; rmp->rm_devvp = devvp; rmp->rm_dev = dev; rmp->rm_bo = &devvp->v_bufobj; rmp->rm_cp = cp; /* Set default values for options: non-aggressive tails */ REISERFS_SB(sbi)->s_mount_opt = (1 << REISERFS_SMALLTAIL); REISERFS_SB(sbi)->s_rd_only = 1; REISERFS_SB(sbi)->s_devvp = devvp; /* Read the super block */ if ((error = read_super_block(rmp, REISERFS_OLD_DISK_OFFSET)) == 0) { /* The read process succeeded, it's an old format */ old_format = 1; } else if ((error = read_super_block(rmp, REISERFS_DISK_OFFSET)) != 0) { reiserfs_log(LOG_ERR, "can not find a ReiserFS filesystem\n"); goto out; } rs = SB_DISK_SUPER_BLOCK(sbi); /* * Let's do basic sanity check to verify that underlying device is * not smaller than the filesystem. If the check fails then abort and * scream, because bad stuff will happen otherwise. */ #if 0 if (s->s_bdev && s->s_bdev->bd_inode && i_size_read(s->s_bdev->bd_inode) < sb_block_count(rs) * sb_blocksize(rs)) { reiserfs_log(LOG_ERR, "reiserfs: filesystem cannot be mounted because it is " "bigger than the device.\n"); reiserfs_log(LOG_ERR, "reiserfs: you may need to run fsck " "rr may be you forgot to reboot after fdisk when it " "told you to.\n"); goto out; } #endif /* * XXX This is from the original Linux code, but why affecting 2 values * to the same variable? */ sbi->s_mount_state = SB_REISERFS_STATE(sbi); sbi->s_mount_state = REISERFS_VALID_FS; if ((error = (old_format ? read_old_bitmaps(rmp) : read_bitmaps(rmp)))) { reiserfs_log(LOG_ERR, "unable to read bitmap\n"); goto out; } /* Make data=ordered the default */ if (!reiserfs_data_log(sbi) && !reiserfs_data_ordered(sbi) && !reiserfs_data_writeback(sbi)) { REISERFS_SB(sbi)->s_mount_opt |= (1 << REISERFS_DATA_ORDERED); } if (reiserfs_data_log(sbi)) { reiserfs_log(LOG_INFO, "using journaled data mode\n"); } else if (reiserfs_data_ordered(sbi)) { reiserfs_log(LOG_INFO, "using ordered data mode\n"); } else { reiserfs_log(LOG_INFO, "using writeback data mode\n"); } /* TODO Not yet supported */ #if 0 if(journal_init(sbi, jdev_name, old_format, commit_max_age)) { reiserfs_log(LOG_ERR, "unable to initialize journal space\n"); goto out; } else { jinit_done = 1 ; /* once this is set, journal_release must be called if we error out of the mount */ } if (reread_meta_blocks(sbi)) { reiserfs_log(LOG_ERR, "unable to reread meta blocks after journal init\n"); goto out; } #endif /* Define and initialize hash function */ sbi->s_hash_function = hash_function(rmp); if (sbi->s_hash_function == NULL) { reiserfs_log(LOG_ERR, "couldn't determined hash function\n"); error = (EINVAL); goto out; } if (is_reiserfs_3_5(rs) || (is_reiserfs_jr(rs) && SB_VERSION(sbi) == REISERFS_VERSION_1)) bit_set(&(sbi->s_properties), REISERFS_3_5); else bit_set(&(sbi->s_properties), REISERFS_3_6); mp->mnt_data = rmp; mp->mnt_stat.f_fsid.val[0] = dev2udev(dev); mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; MNT_ILOCK(mp); mp->mnt_flag |= MNT_LOCAL; mp->mnt_kern_flag |= MNTK_MPSAFE; MNT_IUNLOCK(mp); #if defined(si_mountpoint) devvp->v_rdev->si_mountpoint = mp; #endif return (0); out: reiserfs_log(LOG_INFO, "*** error during mount ***\n"); if (sbi) { if (SB_AP_BITMAP(sbi)) { int i; for (i = 0; i < SB_BMAP_NR(sbi); i++) { if (!SB_AP_BITMAP(sbi)[i].bp_data) break; free(SB_AP_BITMAP(sbi)[i].bp_data, M_REISERFSMNT); } free(SB_AP_BITMAP(sbi), M_REISERFSMNT); } if (sbi->s_rs) { free(sbi->s_rs, M_REISERFSMNT); sbi->s_rs = NULL; } } if (cp != NULL) { DROP_GIANT(); g_topology_lock(); g_vfs_close(cp); g_topology_unlock(); PICKUP_GIANT(); } if (sbi) free(sbi, M_REISERFSMNT); if (rmp) free(rmp, M_REISERFSMNT); dev_rel(dev); return (error); }
int reiserfs_resize(struct super_block *s, unsigned long block_count_new) { int err = 0; struct reiserfs_super_block *sb; struct reiserfs_bitmap_info *bitmap; struct reiserfs_bitmap_info *info; struct reiserfs_bitmap_info *old_bitmap = SB_AP_BITMAP(s); struct buffer_head *bh; struct reiserfs_transaction_handle th; unsigned int bmap_nr_new, bmap_nr; unsigned int block_r_new, block_r; struct reiserfs_list_bitmap *jb; struct reiserfs_list_bitmap jbitmap[JOURNAL_NUM_BITMAPS]; unsigned long int block_count, free_blocks; int i; int copy_size; sb = SB_DISK_SUPER_BLOCK(s); if (SB_BLOCK_COUNT(s) >= block_count_new) { printk("can\'t shrink filesystem on-line\n"); return -EINVAL; } /* check the device size */ bh = sb_bread(s, block_count_new - 1); if (!bh) { printk("reiserfs_resize: can\'t read last block\n"); return -EINVAL; } bforget(bh); /* old disk layout detection; those partitions can be mounted, but * cannot be resized */ if (SB_BUFFER_WITH_SB(s)->b_blocknr * SB_BUFFER_WITH_SB(s)->b_size != REISERFS_DISK_OFFSET_IN_BYTES) { printk ("reiserfs_resize: unable to resize a reiserfs without distributed bitmap (fs version < 3.5.12)\n"); return -ENOTSUPP; } /* count used bits in last bitmap block */ block_r = SB_BLOCK_COUNT(s) - (SB_BMAP_NR(s) - 1) * s->s_blocksize * 8; /* count bitmap blocks in new fs */ bmap_nr_new = block_count_new / (s->s_blocksize * 8); block_r_new = block_count_new - bmap_nr_new * s->s_blocksize * 8; if (block_r_new) bmap_nr_new++; else block_r_new = s->s_blocksize * 8; /* save old values */ block_count = SB_BLOCK_COUNT(s); bmap_nr = SB_BMAP_NR(s); /* resizing of reiserfs bitmaps (journal and real), if needed */ if (bmap_nr_new > bmap_nr) { /* reallocate journal bitmaps */ if (reiserfs_allocate_list_bitmaps(s, jbitmap, bmap_nr_new) < 0) { printk ("reiserfs_resize: unable to allocate memory for journal bitmaps\n"); unlock_super(s); return -ENOMEM; } /* the new journal bitmaps are zero filled, now we copy in the bitmap ** node pointers from the old journal bitmap structs, and then ** transfer the new data structures into the journal struct. ** ** using the copy_size var below allows this code to work for ** both shrinking and expanding the FS. */ copy_size = bmap_nr_new < bmap_nr ? bmap_nr_new : bmap_nr; copy_size = copy_size * sizeof(struct reiserfs_list_bitmap_node *); for (i = 0; i < JOURNAL_NUM_BITMAPS; i++) { struct reiserfs_bitmap_node **node_tmp; jb = SB_JOURNAL(s)->j_list_bitmap + i; memcpy(jbitmap[i].bitmaps, jb->bitmaps, copy_size); /* just in case vfree schedules on us, copy the new ** pointer into the journal struct before freeing the ** old one */ node_tmp = jb->bitmaps; jb->bitmaps = jbitmap[i].bitmaps; vfree(node_tmp); } /* allocate additional bitmap blocks, reallocate array of bitmap * block pointers */ bitmap = vmalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new); if (!bitmap) { /* Journal bitmaps are still supersized, but the memory isn't * leaked, so I guess it's ok */ printk("reiserfs_resize: unable to allocate memory.\n"); return -ENOMEM; } memset(bitmap, 0, sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s)); for (i = 0; i < bmap_nr; i++) bitmap[i] = old_bitmap[i]; /* This doesn't go through the journal, but it doesn't have to. * The changes are still atomic: We're synced up when the journal * transaction begins, and the new bitmaps don't matter if the * transaction fails. */ for (i = bmap_nr; i < bmap_nr_new; i++) { /* don't use read_bitmap_block since it will cache * the uninitialized bitmap */ bh = sb_bread(s, i * s->s_blocksize * 8); memset(bh->b_data, 0, sb_blocksize(sb)); reiserfs_test_and_set_le_bit(0, bh->b_data); reiserfs_cache_bitmap_metadata(s, bh, bitmap + i); set_buffer_uptodate(bh); mark_buffer_dirty(bh); sync_dirty_buffer(bh); // update bitmap_info stuff bitmap[i].first_zero_hint = 1; bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; brelse(bh); } /* free old bitmap blocks array */ SB_AP_BITMAP(s) = bitmap; vfree(old_bitmap); } /* begin transaction, if there was an error, it's fine. Yes, we have * incorrect bitmaps now, but none of it is ever going to touch the * disk anyway. */ err = journal_begin(&th, s, 10); if (err) return err; /* Extend old last bitmap block - new blocks have been made available */ info = SB_AP_BITMAP(s) + bmap_nr - 1; bh = reiserfs_read_bitmap_block(s, bmap_nr - 1); if (!bh) { int jerr = journal_end(&th, s, 10); if (jerr) return jerr; return -EIO; } reiserfs_prepare_for_journal(s, bh, 1); for (i = block_r; i < s->s_blocksize * 8; i++) reiserfs_test_and_clear_le_bit(i, bh->b_data); info->free_count += s->s_blocksize * 8 - block_r; if (!info->first_zero_hint) info->first_zero_hint = block_r; journal_mark_dirty(&th, s, bh); brelse(bh); /* Correct new last bitmap block - It may not be full */ info = SB_AP_BITMAP(s) + bmap_nr_new - 1; bh = reiserfs_read_bitmap_block(s, bmap_nr_new - 1); if (!bh) { int jerr = journal_end(&th, s, 10); if (jerr) return jerr; return -EIO; } reiserfs_prepare_for_journal(s, bh, 1); for (i = block_r_new; i < s->s_blocksize * 8; i++) reiserfs_test_and_set_le_bit(i, bh->b_data); journal_mark_dirty(&th, s, bh); brelse(bh); info->free_count -= s->s_blocksize * 8 - block_r_new; /* Extreme case where last bitmap is the only valid block in itself. */ if (!info->free_count) info->first_zero_hint = 0; /* update super */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); free_blocks = SB_FREE_BLOCKS(s); PUT_SB_FREE_BLOCKS(s, free_blocks + (block_count_new - block_count - (bmap_nr_new - bmap_nr))); PUT_SB_BLOCK_COUNT(s, block_count_new); PUT_SB_BMAP_NR(s, bmap_nr_new); s->s_dirt = 1; journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); SB_JOURNAL(s)->j_must_wait = 1; return journal_end(&th, s, 10); }
/* Tries to find contiguous zero bit window (given size) in given region of * bitmap and place new blocks there. Returns number of allocated blocks. */ static int scan_bitmap (struct reiserfs_transaction_handle *th, b_blocknr_t *start, b_blocknr_t finish, int min, int max, int unfm, unsigned long file_block) { int nr_allocated=0; struct super_block * s = th->t_super; /* find every bm and bmap and bmap_nr in this file, and change them all to bitmap_blocknr * - Hans, it is not a block number - Zam. */ int bm, off; int end_bm, end_off; int off_max = s->s_blocksize << 3; BUG_ON (!th->t_trans_id); PROC_INFO_INC( s, scan_bitmap.call ); if ( SB_FREE_BLOCKS(s) <= 0) return 0; // No point in looking for more free blocks get_bit_address (s, *start, &bm, &off); get_bit_address (s, finish, &end_bm, &end_off); if (bm > SB_BMAP_NR(s)) return 0; if (end_bm > SB_BMAP_NR(s)) end_bm = SB_BMAP_NR(s); /* When the bitmap is more than 10% free, anyone can allocate. * When it's less than 10% free, only files that already use the * bitmap are allowed. Once we pass 80% full, this restriction * is lifted. * * We do this so that files that grow later still have space close to * their original allocation. This improves locality, and presumably * performance as a result. * * This is only an allocation policy and does not make up for getting a * bad hint. Decent hinting must be implemented for this to work well. */ if ( TEST_OPTION(skip_busy, s) && SB_FREE_BLOCKS(s) > SB_BLOCK_COUNT(s)/20 ) { for (; bm < end_bm; bm++, off = 0) { if ( ( off && (!unfm || (file_block != 0))) || SB_AP_BITMAP(s)[bm].free_count > (s->s_blocksize << 3) / 10 ) nr_allocated = scan_bitmap_block(th, bm, &off, off_max, min, max, unfm); if (nr_allocated) goto ret; } /* we know from above that start is a reasonable number */ get_bit_address (s, *start, &bm, &off); } for (; bm < end_bm; bm++, off = 0) { nr_allocated = scan_bitmap_block(th, bm, &off, off_max, min, max, unfm); if (nr_allocated) goto ret; } nr_allocated = scan_bitmap_block(th, bm, &off, end_off + 1, min, max, unfm); ret: *start = bm * off_max + off; return nr_allocated; }
int main (int argc, char * argv[]) { char * file_name; int dev, i; #if 1 if (1) { /* ???? */ schedule (); iput (0); } #endif fprintf (stderr, "\n<-----------dumpreiserfs, version 0.99, 2000----------->\n"); file_name = parse_options (argc, argv); dev = open (file_name, O_RDONLY); if (dev == -1) die ("dumpreiserfs: Can not open device %s: %s\n", file_name, strerror (errno)); g_sb.s_dev = dev; if (uread_super_block (&g_sb)) die ("dumpreiserfs: no reiserfs found on %s", file_name); if (uread_bitmaps (&g_sb)) die ("dumpreiserfs: read_bitmap failed"); if (opt_pack || opt_pack_all) { pack_partition (&g_sb); } else { /* dump file system to stdout */ if (opt_block_to_print != -1) { print_one_block (opt_block_to_print); goto end; } print_block (SB_BUFFER_WITH_SB (&g_sb)); if (opt_print_journal) print_journal (&g_sb); if (opt_print_objectid_map == 1) print_objectid_map (&g_sb); if (opt_print_block_map) { print_bmap (&g_sb, opt_print_block_map == 1 ? 1 : 0); } if (opt_print_regular_file_content || opt_print_directory_contents || opt_print_leaf_items) { print_disk_tree (SB_ROOT_BLOCK (&g_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); } } end: /* brelse bitmaps */ if (SB_AP_BITMAP (&g_sb)) { for (i = 0; i < SB_BMAP_NR (&g_sb); i ++) { brelse (SB_AP_BITMAP (&g_sb)[i]); } freemem (SB_AP_BITMAP (&g_sb)); } /* brelse buffer containing super block */ brelse (SB_BUFFER_WITH_SB (&g_sb)); check_and_free_buffer_mem (); return 0; }
void pack_partition (struct super_block * s) { int i, j, k; uint32_t blocknumber32; uint16_t reclen16, data16; __u32 done = 0; char * data; long long bytes_to_transfer = 0; struct buffer_head * bh; int total_block_number; total_block_number = get_total_block_number (); /* write filesystem's block size to stdout as 16 bit number */ reclen16 = htons (s->s_blocksize); if (opt_pack == 'p' || opt_pack_all == 'p') write (1, &reclen16, sizeof (uint16_t)); bytes_to_transfer = sizeof (uint16_t); /* go through blocks which are marked used in cautious bitmap */ for (i = 0; i < SB_BMAP_NR (s); i ++) { for (j = 0; j < s->s_blocksize; j ++) { /* make sure, that we are not out of the device */ if (i * s->s_blocksize * 8 + j * 8 == SB_BLOCK_COUNT (s)) goto out_of_bitmap; if (i * s->s_blocksize * 8 + j * 8 + 8 > SB_BLOCK_COUNT (s)) die ("build_the_tree: Out of bitmap"); if (opt_pack_all == 0) if (SB_AP_BITMAP (s)[i]->b_data[j] == 0) { /* skip busy block if 'a' not specified */ continue; } /* read 8 blocks at once */ bh = bread (s->s_dev, i * s->s_blocksize + j, s->s_blocksize * 8); for (k = 0; k < 8; k ++) { __u32 block; block = i * s->s_blocksize * 8 + j * 8 + k; if (opt_pack_all == 0 && (SB_AP_BITMAP (s)[i]->b_data[j] & (1 << k)) == 0) continue; #if 0 if ((SB_AP_BITMAP (s)[i]->b_data[j] & (1 << k)) == 0 || /* k-th block is free */ block < SB_BUFFER_WITH_SB (s)->b_blocknr) /* is in skipped for drive manager area */ continue; #endif print_how_far (&done, total_block_number); data = bh->b_data + k * s->s_blocksize; if (not_formatted_node (data, s->s_blocksize)) { /* ok, could not find formatted node here. But this can be commit block, or bitmap which has to be transferred */ if (!not_data_block (s, block)) { /* this is usual unformatted node. Transfer its number only to erase previously existed formatted nodes on the partition we will apply transferred metadata to */ /* size of following record in network byte order */ reclen16 = htons (2); /* the record record */ data16 = htons (MAX_HEIGHT + 1);/*?*/ data = (char *)&data16; } else { /* write super block and bitmap block must be transferred as are */ /* size of record */ reclen16 = htons (s->s_blocksize); /* the record itself */ data = data; } } else { /* any kind of formatted nodes gets here (super block, desc block of journal): FIXME: it would be useful to be able to find commit blocks */ zero_direct_items (data); /* FIXME: do other packing */ /* write size of following record */ reclen16 = htons (s->s_blocksize); /* the record itself */ data = data; #if 0 if (blkh->blk_level > DISK_LEAF_NODE_LEVEL) { /* block must look like internal node on the target partition. But (currently) fsck do not consider internal nodes, therefore we do not have to transfer contents of internal nodes */ /* size of following record in network byte order */ reclen16 = htons (2); /* the record itself */ data16 = htons (DISK_LEAF_NODE_LEVEL + 1); data = (char *)&data16; } else { /* leaf node found */ ih = (struct item_head *)(blkh + 1); /* fill direct items with 0s */ for (l = 0; l < blkh->blk_nr_item; l ++, ih ++) if (I_IS_DIRECT_ITEM (ih)) { direct_items ++; direct_item_total_length += ih->ih_item_len; memset ((char *)blkh + ih->ih_item_location, 0, ih->ih_item_len); } /* write size of following record */ reclen16 = htons (s->s_blocksize); /* the record itself */ data = (char *)blkh; } #endif } /*fprintf (stderr, "block %d, reclen %d\n", block, ntohs (reclen16));*/ /* write block number */ blocknumber32 = htonl (block); bytes_to_transfer += sizeof (uint32_t) + sizeof (uint16_t) + ntohs (reclen16); if (opt_pack == 'p' || opt_pack_all == 'p') { write (1, &blocknumber32, sizeof (uint32_t)); /* write record len */ write (1, &reclen16, sizeof (uint16_t)); /* write the record */ write (1, data, ntohs (reclen16)); } } bforget (bh); } } out_of_bitmap: fprintf (stderr, "done\n"); if (opt_pack == 'c' || opt_pack_all == 'c') fprintf (stderr, "Bytes to transfer %Ld, sequential 0s %d in %d sequeneces (%items (%d unreacable))\n", bytes_to_transfer, direct_item_total_length, direct_items, items, unreachable_items); else fprintf (stderr, "Bytes dumped %Ld, sequential 0s %d in %d sequeneces\n", bytes_to_transfer, direct_item_total_length, direct_items); }
/* * Unmount system call */ static int reiserfs_unmount(struct mount *mp, int mntflags) { int error, flags = 0; struct reiserfs_mount *rmp; struct reiserfs_sb_info *sbi; reiserfs_log(LOG_DEBUG, "get private data\n"); rmp = VFSTOREISERFS(mp); sbi = rmp->rm_reiserfs; /* Flangs handling */ reiserfs_log(LOG_DEBUG, "handle mntflags\n"); if (mntflags & MNT_FORCE) flags |= FORCECLOSE; /* Flush files -> vflush */ reiserfs_log(LOG_DEBUG, "flush vnodes\n"); if ((error = vflush(mp, 0, flags, curthread))) return (error); /* XXX Super block update */ if (sbi) { if (SB_AP_BITMAP(sbi)) { int i; reiserfs_log(LOG_DEBUG, "release bitmap buffers (total: %d)\n", SB_BMAP_NR(sbi)); for (i = 0; i < SB_BMAP_NR(sbi); i++) { if (SB_AP_BITMAP(sbi)[i].bp_data) { free(SB_AP_BITMAP(sbi)[i].bp_data, M_REISERFSMNT); SB_AP_BITMAP(sbi)[i].bp_data = NULL; } } reiserfs_log(LOG_DEBUG, "free bitmaps structure\n"); free(SB_AP_BITMAP(sbi), M_REISERFSMNT); SB_AP_BITMAP(sbi) = NULL; } if (sbi->s_rs) { reiserfs_log(LOG_DEBUG, "free super block data\n"); free(sbi->s_rs, M_REISERFSMNT); sbi->s_rs = NULL; } } reiserfs_log(LOG_DEBUG, "close device\n"); #if defined(si_mountpoint) rmp->rm_devvp->v_rdev->si_mountpoint = NULL; #endif DROP_GIANT(); g_topology_lock(); g_vfs_close(rmp->rm_cp); g_topology_unlock(); PICKUP_GIANT(); vrele(rmp->rm_devvp); dev_rel(rmp->rm_dev); if (sbi) { reiserfs_log(LOG_DEBUG, "free sbi\n"); free(sbi, M_REISERFSMNT); sbi = rmp->rm_reiserfs = NULL; } if (rmp) { reiserfs_log(LOG_DEBUG, "free rmp\n"); free(rmp, M_REISERFSMNT); rmp = NULL; } mp->mnt_data = 0; MNT_ILOCK(mp); mp->mnt_flag &= ~MNT_LOCAL; MNT_IUNLOCK(mp); reiserfs_log(LOG_DEBUG, "done\n"); return (error); }
/* The function is NOT SCHEDULE-SAFE! */ static int find_forward (struct super_block * s, int * bmap_nr, int * offset, int for_unformatted) { int i, j; struct buffer_head * bh; unsigned long block_to_try = 0; unsigned long next_block_to_try = 0 ; PROC_INFO_INC( s, find_forward.call ); for (i = *bmap_nr; i < SB_BMAP_NR (s); i ++, *offset = 0, PROC_INFO_INC( s, find_forward.bmap )) { /* get corresponding bitmap block */ bh = SB_AP_BITMAP (s)[i]; if (buffer_locked (bh)) { PROC_INFO_INC( s, find_forward.wait ); __wait_on_buffer (bh); } retry: j = reiserfs_find_next_zero_le_bit ((unsigned long *)bh->b_data, s->s_blocksize << 3, *offset); /* wow, this really needs to be redone. We can't allocate a block if ** it is in the journal somehow. reiserfs_in_journal makes a suggestion ** for a good block if the one you ask for is in the journal. Note, ** reiserfs_in_journal might reject the block it suggests. The big ** gain from the suggestion is when a big file has been deleted, and ** many blocks show free in the real bitmap, but are all not free ** in the journal list bitmaps. ** ** this whole system sucks. The bitmaps should reflect exactly what ** can and can't be allocated, and the journal should update them as ** it goes. TODO. */ if (j < (s->s_blocksize << 3)) { block_to_try = (i * (s->s_blocksize << 3)) + j; /* the block is not in the journal, we can proceed */ if (!(reiserfs_in_journal(s, s->s_dev, block_to_try, s->s_blocksize, for_unformatted, &next_block_to_try))) { *bmap_nr = i; *offset = j; return 1; } /* the block is in the journal */ else if ((j+1) < (s->s_blocksize << 3)) { /* try again */ /* reiserfs_in_journal suggested a new block to try */ if (next_block_to_try > 0) { int new_i ; get_bit_address (s, next_block_to_try, &new_i, offset); PROC_INFO_INC( s, find_forward.in_journal_hint ); /* block is not in this bitmap. reset i and continue ** we only reset i if new_i is in a later bitmap. */ if (new_i > i) { i = (new_i - 1 ); /* i gets incremented by the for loop */ PROC_INFO_INC( s, find_forward.in_journal_out ); continue ; } } else { /* no suggestion was made, just try the next block */ *offset = j+1 ; } PROC_INFO_INC( s, find_forward.retry ); goto retry ; } } } /* zero bit not found */ return 0; }