Esempio n. 1
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;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
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;
}