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; }
static int read_bitmaps (struct super_block * s) { int i, bmp, dl ; struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK(s); SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * sb_bmap_nr(rs), GFP_NOFS, s); if (SB_AP_BITMAP (s) == 0) return 1; memset (SB_AP_BITMAP (s), 0, sizeof (struct buffer_head *) * sb_bmap_nr(rs)); /* reiserfs leaves the first 64k unused so that any partition labeling scheme currently used will have enough space. Then we need one block for the super. -Hans */ bmp = (REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1; /* first of bitmap blocks */ SB_AP_BITMAP (s)[0] = reiserfs_bread (s, bmp, s->s_blocksize); if(!SB_AP_BITMAP(s)[0]) return 1; for (i = 1, bmp = dl = s->s_blocksize * 8; i < sb_bmap_nr(rs); i ++) { SB_AP_BITMAP (s)[i] = reiserfs_bread (s, bmp, s->s_blocksize); if (!SB_AP_BITMAP (s)[i]) return 1; bmp += dl; } return 0; }
static int read_old_bitmaps (struct super_block * s) { int i ; struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK(s); int bmp1 = (REISERFS_OLD_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1; /* first of bitmap blocks */ /* read true bitmap */ SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * sb_bmap_nr(rs), GFP_NOFS, s); if (SB_AP_BITMAP (s) == 0) return 1; memset (SB_AP_BITMAP (s), 0, sizeof (struct buffer_head *) * sb_bmap_nr(rs)); for (i = 0; i < sb_bmap_nr(rs); i ++) { SB_AP_BITMAP (s)[i] = reiserfs_bread (s, bmp1 + i, s->s_blocksize); if (!SB_AP_BITMAP (s)[i]) return 1; } return 0; }
static int read_old_bitmaps (struct super_block * s) { int i, repeat ; struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK(s); int bmp1 = (REISERFS_OLD_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1; /* first of bitmap blocks */ repeat = 0 ; /* read true bitmap */ SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * le16_to_cpu (rs->s_bmap_nr), GFP_KERNEL, s); if (SB_AP_BITMAP (s) == 0) return 1; memset (SB_AP_BITMAP (s), 0, sizeof (struct buffer_head *) * le16_to_cpu (rs->s_bmap_nr)); for (i = 0; i < le16_to_cpu (rs->s_bmap_nr); i ++) { SB_AP_BITMAP (s)[i] = reiserfs_bread (s->s_dev, bmp1 + i, s->s_blocksize, &repeat); if (!SB_AP_BITMAP (s)[i]) return 1; } return 0; }
static int reiserfs_readdir (struct file * filp, void * dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ INITIALIZE_PATH (path_to_entry); struct buffer_head * bh; int item_num, entry_num; const struct key * rkey; struct item_head * ih, tmp_ih; int search_res; char * local_buf; loff_t next_pos; char small_buf[32] ; /* avoid kmalloc if we can */ struct reiserfs_dir_entry de; reiserfs_check_lock_depth("readdir") ; /* form key for search the next directory entry using f_pos field of file structure */ make_cpu_key (&pos_key, inode, (filp->f_pos) ? (filp->f_pos) : DOT_OFFSET, TYPE_DIRENTRY, 3); next_pos = cpu_key_k_offset (&pos_key); /* reiserfs_warning ("reiserfs_readdir 1: f_pos = %Ld\n", filp->f_pos);*/ while (1) { research: /* search the directory item, containing entry with specified key */ search_res = search_by_entry_key (inode->i_sb, &pos_key, &path_to_entry, &de); if (search_res == IO_ERROR) { // FIXME: we could just skip part of directory which could // not be read return -EIO; } entry_num = de.de_entry_num; bh = de.de_bh; item_num = de.de_item_num; ih = de.de_ih; store_ih (&tmp_ih, ih); /* we must have found item, that is item of this directory, */ RFALSE( COMP_SHORT_KEYS (&(ih->ih_key), &pos_key), "vs-9000: found item %h does not match to dir we readdir %K", ih, &pos_key); RFALSE( item_num > B_NR_ITEMS (bh) - 1, "vs-9005 item_num == %d, item amount == %d", item_num, B_NR_ITEMS (bh)); /* and entry must be not more than number of entries in the item */ RFALSE( I_ENTRY_COUNT (ih) < entry_num, "vs-9010: entry number is too big %d (%d)", entry_num, I_ENTRY_COUNT (ih)); if (search_res == POSITION_FOUND || entry_num < I_ENTRY_COUNT (ih)) { /* go through all entries in the directory item beginning from the entry, that has been found */ struct reiserfs_de_head * deh = B_I_DEH (bh, ih) + entry_num; for (; entry_num < I_ENTRY_COUNT (ih); entry_num ++, deh ++) { int d_reclen; char * d_name; off_t d_off; ino_t d_ino; if (!de_visible (deh)) /* it is hidden entry */ continue; d_reclen = entry_length (bh, ih, entry_num); d_name = B_I_DEH_ENTRY_FILE_NAME (bh, ih, deh); if (!d_name[d_reclen - 1]) d_reclen = strlen (d_name); if (d_reclen > REISERFS_MAX_NAME_LEN(inode->i_sb->s_blocksize)){ /* too big to send back to VFS */ continue ; } d_off = deh_offset (deh); filp->f_pos = d_off ; d_ino = deh_objectid (deh); if (d_reclen <= 32) { local_buf = small_buf ; } else { local_buf = reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb) ; if (!local_buf) { pathrelse (&path_to_entry); return -ENOMEM ; } if (item_moved (&tmp_ih, &path_to_entry)) { reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ; goto research; } } // Note, that we copy name to user space via temporary // buffer (local_buf) because filldir will block if // user space buffer is swapped out. At that time // entry can move to somewhere else memcpy (local_buf, d_name, d_reclen); if (filldir (dirent, local_buf, d_reclen, d_off, d_ino, DT_UNKNOWN) < 0) { if (local_buf != small_buf) { reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ; } goto end; } if (local_buf != small_buf) { reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ; } // next entry should be looked for with such offset next_pos = deh_offset (deh) + 1; if (item_moved (&tmp_ih, &path_to_entry)) { goto research; } } /* for */ } if (item_num != B_NR_ITEMS (bh) - 1) // end of directory has been reached goto end; /* item we went through is last item of node. Using right delimiting key check is it directory end */ rkey = get_rkey (&path_to_entry, inode->i_sb); if (! comp_le_keys (rkey, &MIN_KEY)) { /* set pos_key to key, that is the smallest and greater that key of the last entry in the item */ set_cpu_key_k_offset (&pos_key, next_pos); continue; } if ( COMP_SHORT_KEYS (rkey, &pos_key)) { // end of directory has been reached goto end; } /* directory continues in the right neighboring block */ set_cpu_key_k_offset (&pos_key, le_key_k_offset (KEY_FORMAT_3_5, rkey)); } /* while */ end: // FIXME: ext2_readdir does not reset f_pos filp->f_pos = next_pos; pathrelse (&path_to_entry); reiserfs_check_path(&path_to_entry) ; UPDATE_ATIME(inode) ; return 0; }
/* add entry to the directory (entry can be hidden). Does not mark dir inode dirty, do it after successesfull call to it */ static int reiserfs_add_entry (struct reiserfs_transaction_handle *th, struct inode * dir, const char * name, int namelen, struct key * object_key, struct reiserfs_dir_entry * de, int visible ) { struct key entry_key; char * buffer; int buflen; struct reiserfs_de_head * deh; struct path path; char bit_string [MAX_GEN_NUMBER / 8 + 1]; int gen_number; int repeat; #ifdef REISERFS_ALIGNED int aligned_namelen = (namelen+3) & ~3; #endif init_path (&path); if (!dir || !dir->i_sb) return -ENOENT; if ((unsigned int)namelen > REISERFS_MAX_NAME_LEN (dir->i_sb->s_blocksize)) return -ENAMETOOLONG; /* each entry has unique key. compose it */ copy_key (&entry_key, INODE_PKEY(dir)); entry_key.k_offset = get_third_component (name, namelen); entry_key.k_uniqueness = DIRENTRY_UNIQUENESS; /* get memory for composing the entry */ #ifdef REISERFS_ALIGNED buflen = DEH_SIZE + aligned_namelen; #else buflen = DEH_SIZE + namelen; #endif buffer = reiserfs_kmalloc (buflen, GFP_KERNEL, dir->i_sb); if (buffer == 0) return -ENOMEM; /* fill buffer : directory entry head, name[, dir objectid | , stat data | ,stat data, dir objectid ] */ deh = (struct reiserfs_de_head *)buffer; deh->deh_location = 0; deh->deh_offset = entry_key.k_offset; deh->deh_state = 0; /* put key (ino analog) to de */ deh->deh_dir_id = object_key->k_dir_id; deh->deh_objectid = object_key->k_objectid; /* copy name */ #ifdef REISERFS_ALIGNED memset( (char*)(deh+1), '\0', aligned_namelen ); #endif memcpy ((char *)(deh + 1), name, namelen); /* entry is ready to be pasted into tree, set 'visibility' and 'stat data in entry' attributes */ mark_de_without_sd (deh); visible ? mark_de_visible (deh) : mark_de_hidden (deh); /* find the proper place for the new entry */ memset (bit_string, 0, sizeof (bit_string)); de->de_gen_number_bit_string = bit_string; if (reiserfs_find_entry (dir, name, namelen, &path, de) == POSITION_FOUND) { reiserfs_panic (dir->i_sb, "vs-7030: reiserfs_add_entry: entry with this key %k already exists", &entry_key); } if (find_first_nonzero_bit (bit_string, MAX_GEN_NUMBER + 1) < MAX_GEN_NUMBER + 1) { /* there are few names with given hash value */ gen_number = find_first_zero_bit (bit_string, MAX_GEN_NUMBER + 1); if (gen_number > MAX_GEN_NUMBER) { /* there is no free generation number */ reiserfs_kfree (buffer, buflen, dir->i_sb); pathrelse (&path); return -EHASHCOLLISION; } /* adjust offset of directory enrty */ deh->deh_offset = SET_GENERATION_NUMBER (deh->deh_offset, gen_number); entry_key.k_offset = deh->deh_offset; /* find place for new entry */ if (search_by_entry_key (dir->i_sb, &entry_key, &path, &(de->de_entry_num), &repeat)) { reiserfs_panic (dir->i_sb, "reiserfs_add_entry: 7032: entry with this key (%k) already exists", &entry_key); } } else { deh->deh_offset = SET_GENERATION_NUMBER (deh->deh_offset, 0); entry_key.k_offset = deh->deh_offset; } /* perform the insertion of the entry that we have prepared */ if (reiserfs_paste_into_item (th, dir->i_sb, &path, &(de->de_entry_num), &entry_key, buffer, buflen, REISERFS_KERNEL_MEM, 0) == -1) { reiserfs_kfree (buffer, buflen, dir->i_sb); return -ENOSPC; } reiserfs_kfree (buffer, buflen, dir->i_sb); dir->i_size += buflen; dir->i_mtime = dir->i_ctime = CURRENT_TIME; return 0; }
static int reiserfs_symlink (struct inode * parent_dir, struct dentry * dentry, const char * symname) { int retval; struct inode * inode; char * name; int item_len; struct reiserfs_transaction_handle th ; int mode = S_IFLNK | S_IRWXUGO; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); if (!(inode = new_inode(parent_dir->i_sb))) { return -ENOMEM ; } new_inode_init(inode, parent_dir, mode); reiserfs_write_lock(parent_dir->i_sb); item_len = ROUND_UP (strlen (symname)); if (item_len > MAX_DIRECT_ITEM_LEN (parent_dir->i_sb->s_blocksize)) { retval = -ENAMETOOLONG; drop_new_inode(inode); goto out_failed; } name = reiserfs_kmalloc (item_len, GFP_NOFS, parent_dir->i_sb); if (!name) { drop_new_inode(inode); retval = -ENOMEM; goto out_failed; } memcpy (name, symname, strlen (symname)); padd_item (name, item_len, strlen (symname)); /* We would inherit the default ACL here, but symlinks don't get ACLs */ retval = journal_begin(&th, parent_dir->i_sb, jbegin_count) ; if (retval) { drop_new_inode (inode); reiserfs_kfree (name, item_len, parent_dir->i_sb); goto out_failed; } retval = reiserfs_new_inode (&th, parent_dir, mode, name, strlen (symname), dentry, inode); reiserfs_kfree (name, item_len, parent_dir->i_sb); if (retval) { /* reiserfs_new_inode iputs for us */ goto out_failed; } reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(parent_dir) ; inode->i_op = &reiserfs_symlink_inode_operations; inode->i_mapping->a_ops = &reiserfs_address_space_operations; // must be sure this inode is written with this transaction // //reiserfs_update_sd (&th, inode, READ_BLOCKS); retval = reiserfs_add_entry (&th, parent_dir, dentry->d_name.name, dentry->d_name.len, inode, 1/*visible*/); if (retval) { int err; inode->i_nlink--; reiserfs_update_sd (&th, inode); err = journal_end(&th, parent_dir->i_sb, jbegin_count) ; if (err) retval = err; iput (inode); goto out_failed; } d_instantiate(dentry, inode); retval = journal_end(&th, parent_dir->i_sb, jbegin_count) ; out_failed: reiserfs_write_unlock(parent_dir->i_sb); return retval; }
static int reiserfs_add_entry (struct reiserfs_transaction_handle *th, struct inode * dir, const char * name, int namelen, struct inode * inode, int visible) { struct cpu_key entry_key; struct reiserfs_de_head * deh; INITIALIZE_PATH (path); struct reiserfs_dir_entry de; int bit_string [MAX_GENERATION_NUMBER / (sizeof(int) * 8) + 1]; int gen_number; char small_buf[32+DEH_SIZE] ; /* 48 bytes now and we avoid kmalloc if we create file with short name */ char * buffer; int buflen, paste_size; int retval; BUG_ON (!th->t_trans_id); /* cannot allow items to be added into a busy deleted directory */ if (!namelen) return -EINVAL; if (namelen > REISERFS_MAX_NAME (dir->i_sb->s_blocksize)) return -ENAMETOOLONG; /* each entry has unique key. compose it */ make_cpu_key (&entry_key, dir, get_third_component (dir->i_sb, name, namelen), TYPE_DIRENTRY, 3); /* get memory for composing the entry */ buflen = DEH_SIZE + ROUND_UP (namelen); if (buflen > sizeof (small_buf)) { buffer = reiserfs_kmalloc (buflen, GFP_NOFS, dir->i_sb); if (buffer == 0) return -ENOMEM; } else buffer = small_buf; paste_size = (get_inode_sd_version (dir) == STAT_DATA_V1) ? (DEH_SIZE + namelen) : buflen; /* fill buffer : directory entry head, name[, dir objectid | , stat data | ,stat data, dir objectid ] */ deh = (struct reiserfs_de_head *)buffer; deh->deh_location = 0; /* JDM Endian safe if 0 */ put_deh_offset( deh, cpu_key_k_offset( &entry_key ) ); deh->deh_state = 0; /* JDM Endian safe if 0 */ /* put key (ino analog) to de */ deh->deh_dir_id = INODE_PKEY (inode)->k_dir_id; /* safe: k_dir_id is le */ deh->deh_objectid = INODE_PKEY (inode)->k_objectid; /* safe: k_objectid is le */ /* copy name */ memcpy ((char *)(deh + 1), name, namelen); /* padd by 0s to the 4 byte boundary */ padd_item ((char *)(deh + 1), ROUND_UP (namelen), namelen); /* entry is ready to be pasted into tree, set 'visibility' and 'stat data in entry' attributes */ mark_de_without_sd (deh); visible ? mark_de_visible (deh) : mark_de_hidden (deh); /* find the proper place for the new entry */ memset (bit_string, 0, sizeof (bit_string)); de.de_gen_number_bit_string = (char *)bit_string; retval = reiserfs_find_entry (dir, name, namelen, &path, &de); if( retval != NAME_NOT_FOUND ) { if (buffer != small_buf) reiserfs_kfree (buffer, buflen, dir->i_sb); pathrelse (&path); if ( retval == IO_ERROR ) { return -EIO; } if (retval != NAME_FOUND) { reiserfs_warning (dir->i_sb, "zam-7002:%s: \"reiserfs_find_entry\" " "has returned unexpected value (%d)", __FUNCTION__, retval); } return -EEXIST; } gen_number = find_first_zero_bit ((unsigned long *)bit_string, MAX_GENERATION_NUMBER + 1); if (gen_number > MAX_GENERATION_NUMBER) { /* there is no free generation number */ reiserfs_warning (dir->i_sb, "reiserfs_add_entry: Congratulations! we have got hash function screwed up"); if (buffer != small_buf) reiserfs_kfree (buffer, buflen, dir->i_sb); pathrelse (&path); return -EBUSY; } /* adjust offset of directory enrty */ put_deh_offset(deh, SET_GENERATION_NUMBER(deh_offset(deh), gen_number)); set_cpu_key_k_offset (&entry_key, deh_offset(deh)); /* update max-hash-collisions counter in reiserfs_sb_info */ PROC_INFO_MAX( th -> t_super, max_hash_collisions, gen_number ); if (gen_number != 0) { /* we need to re-search for the insertion point */ if (search_by_entry_key (dir->i_sb, &entry_key, &path, &de) != NAME_NOT_FOUND) { reiserfs_warning (dir->i_sb, "vs-7032: reiserfs_add_entry: " "entry with this key (%K) already exists", &entry_key); if (buffer != small_buf) reiserfs_kfree (buffer, buflen, dir->i_sb); pathrelse (&path); return -EBUSY; } } /* perform the insertion of the entry that we have prepared */ retval = reiserfs_paste_into_item (th, &path, &entry_key, dir, buffer, paste_size); if (buffer != small_buf) reiserfs_kfree (buffer, buflen, dir->i_sb); if (retval) { reiserfs_check_path(&path) ; return retval; } dir->i_size += paste_size; dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; if (!S_ISDIR (inode->i_mode) && visible) // reiserfs_mkdir or reiserfs_rename will do that by itself reiserfs_update_sd (th, dir); reiserfs_check_path(&path) ; return 0; }
int reiserfs_resize (struct super_block * s, unsigned long block_count_new) { struct reiserfs_super_block * sb; struct buffer_head ** bitmap, * 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 = reiserfs_kmalloc(sizeof(struct buffer_head *) * bmap_nr_new, GFP_KERNEL, s); if (!bitmap) { printk("reiserfs_resize: unable to allocate memory.\n"); return -ENOMEM; } 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] = getblk(s->s_dev, i * s->s_blocksize * 8, s->s_blocksize); memset(bitmap[i]->b_data, 0, sb->s_blocksize); reiserfs_test_and_set_le_bit(0, bitmap[i]->b_data); mark_buffer_dirty(bitmap[i]) ; mark_buffer_uptodate(bitmap[i], 1); ll_rw_block(WRITE, 1, bitmap + i); wait_on_buffer(bitmap[i]); } /* free old bitmap blocks array */ reiserfs_kfree(SB_AP_BITMAP(s), sizeof(struct buffer_head *) * bmap_nr, 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], 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]->b_data); journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1]); reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1], 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]->b_data); journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr_new - 1]); /* 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; }