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; }
// // 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; }
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; }
// // 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; }
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; }
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; }
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; }