コード例 #1
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 int reiserfs_remount (struct super_block * s, int * flags, char * data)
{
  struct reiserfs_super_block * rs;
  struct reiserfs_transaction_handle th ;
  unsigned long blocks;
  unsigned long mount_options = 0;
#ifdef CONFIG_REISERFS_IMMUTABLE_HACK
  int do_update_suidimmu;
#endif

  rs = SB_DISK_SUPER_BLOCK (s);

  if (!parse_options(data, &mount_options, &blocks))
  	return 0;

#ifdef CONFIG_REISERFS_IMMUTABLE_HACK
    if (reiserfs_suid_immutable(s) && !capable(CAP_LINUX_IMMUTABLE))
	return -EPERM;
    do_update_suidimmu = 0;
    if (test_bit(SUID_IMMUTABLE, &mount_options)) {
      if (!capable(CAP_LINUX_IMMUTABLE))
	return -EPERM;
#ifdef CONFIG_REISERFS_IMMUTABLE_HACK_DEBUG
	printk("reiserfs: suidimmu ON\n");
#endif /* CONFIG_REISERFS_IMMUTABLE_HACK_DEBUG */
      if (!reiserfs_suid_immutable(s))
	do_update_suidimmu = 1;
      set_bit(SUID_IMMUTABLE, &(s->u.reiserfs_sb.s_mount_opt));
    } else {
#ifdef CONFIG_REISERFS_IMMUTABLE_HACK_DEBUG
	printk("reiserfs: suidimmu OFF\n");
#endif /* CONFIG_REISERFS_IMMUTABLE_HACK_DEBUG */
      if (reiserfs_suid_immutable(s))
	do_update_suidimmu = 1;
      clear_bit(SUID_IMMUTABLE, &(s->u.reiserfs_sb.s_mount_opt));
    }

    /*
     * update S_IMMUTABLE bit on inode->i_flags
     */
    if (do_update_suidimmu)
      update_suidimmu(s, reiserfs_suid_immutable(s));
#endif /* CONFIG_REISERFS_IMMUTABLE_HACK */

#define SET_OPT( opt, bits, super )					\
    if( ( bits ) & ( 1 << ( opt ) ) )					\
	    ( super ) -> u.reiserfs_sb.s_mount_opt |= ( 1 << ( opt ) )

  /* set options in the super-block bitmask */
  SET_OPT( NOTAIL, mount_options, s );
  SET_OPT( REISERFS_NO_BORDER, mount_options, s );
  SET_OPT( REISERFS_NO_UNHASHED_RELOCATION, mount_options, s );
  SET_OPT( REISERFS_HASHED_RELOCATION, mount_options, s );
  SET_OPT( REISERFS_TEST4, mount_options, s );
#undef SET_OPT

  if(blocks) {
      int rc = reiserfs_resize(s, blocks);
      if (rc != 0)
	  return rc;
  }

  if ((unsigned long)(*flags & MS_RDONLY) == (s->s_flags & MS_RDONLY)) {
    /* there is nothing to do to remount read-only fs as read-only fs */
    return 0;
  }
  
  if (*flags & MS_RDONLY) {
    /* try to remount file system with read-only permissions */
    if (sb_state(rs) == REISERFS_VALID_FS || s->u.reiserfs_sb.s_mount_state != REISERFS_VALID_FS) {
      return 0;
    }

    journal_begin(&th, s, 10) ;
    /* Mounting a rw partition read-only. */
    reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
    set_sb_state( rs, s->u.reiserfs_sb.s_mount_state );
    journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
    s->s_dirt = 0;
  } else {
    s->u.reiserfs_sb.s_mount_state = sb_state(rs) ;
    s->s_flags &= ~MS_RDONLY ; /* now it is safe to call journal_begin */
    journal_begin(&th, s, 10) ;

    /* Mount a partition which is read-only, read-write */
    reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
    s->u.reiserfs_sb.s_mount_state = sb_state(rs);
    s->s_flags &= ~MS_RDONLY;
    set_sb_state( rs, REISERFS_ERROR_FS );
    /* mark_buffer_dirty (SB_BUFFER_WITH_SB (s), 1); */
    journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
    s->s_dirt = 0;
    s->u.reiserfs_sb.s_mount_state = REISERFS_VALID_FS ;
  }
  /* this will force a full flush of all journal lists */
  SB_JOURNAL(s)->j_must_wait = 1 ;
  journal_end(&th, s, 10) ;

  if (!( *flags & MS_RDONLY ) )
    finish_unfinished( s );

  return 0;
}
コード例 #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 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;
    }
#ifdef CONFIG_REISERFS_IMMUTABLE_HACK
    if (reiserfs_suid_immutable(s) && !capable(CAP_LINUX_IMMUTABLE))
	return NULL;
#ifdef CONFIG_REISERFS_IMMUTABLE_HACK_DEBUG
    if (reiserfs_suid_immutable(s))
	printk("reiserfs: suidimmu\n");
#endif /* CONFIG_REISERFS_IMMUTABLE_HACK_DEBUG */
#endif /* CONFIG_REISERFS_IMMUTABLE_HACK */

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

    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 ) );

    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;
}
コード例 #3
0
static int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
    struct inode *inode = dentry->d_inode ;
    int error ;
    if (attr->ia_valid & ATTR_SIZE) {
	/* version 2 items will be caught by the s_maxbytes check
	** done for us in vmtruncate
	*/
	if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 &&
	    attr->ia_size > MAX_NON_LFS)
            return -EFBIG ;

	/* fill in hole pointers in the expanding truncate case. */
        if (attr->ia_size > inode->i_size) {
	    error = generic_cont_expand(inode, attr->ia_size) ;
	    if (inode->u.reiserfs_i.i_prealloc_count > 0) {
		struct reiserfs_transaction_handle th ;
		/* we're changing at most 2 bitmaps, inode + super */
		journal_begin(&th, inode->i_sb, 4) ;
		reiserfs_discard_prealloc (&th, inode);
		journal_end(&th, inode->i_sb, 4) ;
	    }
	    if (error)
	        return error ;
	}
    }

    if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) ||
	 ((attr->ia_valid & ATTR_GID) && (attr->ia_gid & ~0xffff))) &&
	(get_inode_sd_version (inode) == STAT_DATA_V1))
		/* stat data of format v3.5 has 16 bit uid and gid */
	    return -EINVAL;

#ifdef CONFIG_REISERFS_IMMUTABLE_HACK 
    if (reiserfs_suid_immutable(inode->i_sb)) {
	uid_t uid;
	umode_t mode;

	uid = (attr->ia_valid & ATTR_UID) ? attr->ia_uid : inode->i_uid;
	mode = (attr->ia_valid & ATTR_MODE) ? attr->ia_mode : inode->i_mode;
	if (uid == 0 && (mode & S_ISUID) && !capable(CAP_LINUX_IMMUTABLE))
	    return -EPERM;
    }
#endif /* COCONFIG_REISERFS_IMMUTABLE_HACK */

    error = inode_change_ok(inode, attr) ;
#ifdef CONFIG_REISERFS_IMMUTABLE_HACK 
    if (!error && reiserfs_suid_immutable(inode->i_sb)) {
	uid_t uid;
	umode_t mode;

	uid = (attr->ia_valid & ATTR_UID) ? attr->ia_uid : inode->i_uid;
	mode = (attr->ia_valid & ATTR_MODE) ? attr->ia_mode : inode->i_mode;
	inode->i_flags &= ~S_IMMUTABLE;
	if (uid == 0 && (mode & S_ISUID)) {
	    inode->i_flags |= S_IMMUTABLE;
#ifdef CONFIG_REISERFS_IMMUTABLE_HACK_DEBUG 
	    printk("set IMMUTABLE, inode %p\n", inode); 
#endif /* CONFIG_REISERFS_IMMUTABLE_HACK_DEBUG */ 
	}
    }
#endif /* COCONFIG_REISERFS_IMMUTABLE_HACK */
    if (!error)
        inode_setattr(inode, attr) ;

    return error ;
}