Пример #1
0
void ext_free_inode(struct inode * inode)
{
	struct buffer_head * bh;
	struct ext_free_inode * efi;
	struct super_block * sb;
	unsigned long block;
	unsigned long ino;
	kdev_t dev;

	if (!inode)
		return;
	if (!inode->i_dev) {
		printk("free_inode: inode has no device\n");
		return;
	}
	if (inode->i_count != 1) {
		printk("free_inode: inode has count=%d\n",inode->i_count);
		return;
	}
	if (inode->i_nlink) {
		printk("free_inode: inode has nlink=%d\n",inode->i_nlink);
		return;
	}
	if (!inode->i_sb) {
		printk("free_inode: inode on non-existent device\n");
		return;
	}
	sb = inode->i_sb;
	ino = inode->i_ino;
	dev = inode->i_dev;
	clear_inode(inode);
	lock_super (sb);
	if (ino < 1 || ino > sb->u.ext_sb.s_ninodes) {
		printk("free_inode: inode 0 or non-existent inode\n");
		unlock_super (sb);
		return;
	}
	if (sb->u.ext_sb.s_firstfreeinodeblock)
		efi = ((struct ext_free_inode *) sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
			(sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
	if (!sb->u.ext_sb.s_firstfreeinodeblock || efi->count == 14) {
#ifdef EXTFS_DEBUG
printk("ext_free_inode: inode full, skipping to %d\n", ino);
#endif
		if (sb->u.ext_sb.s_firstfreeinodeblock)
			brelse (sb->u.ext_sb.s_firstfreeinodeblock);
		block = 2 + (ino - 1) / EXT_INODES_PER_BLOCK;
		if (!(bh = bread(dev, block, sb->s_blocksize)))
			panic("ext_free_inode: unable to read inode block\n");
		efi = ((struct ext_free_inode *) bh->b_data) +
			(ino - 1) % EXT_INODES_PER_BLOCK;
		efi->next = sb->u.ext_sb.s_firstfreeinodenumber;
		efi->count = 0;
		sb->u.ext_sb.s_firstfreeinodenumber = ino;
		sb->u.ext_sb.s_firstfreeinodeblock = bh;
	} else {
		efi->free[efi->count++] = ino;
	}
	sb->u.ext_sb.s_freeinodescount ++;
	sb->s_dirt = 1;
	mark_buffer_dirty(sb->u.ext_sb.s_firstfreeinodeblock, 1);
	unlock_super (sb);
}
Пример #2
0
struct super_block *
affs_read_super(struct super_block *s,void *data, int silent)
{
	struct buffer_head	*bh = NULL;
	struct buffer_head	*bb;
	kdev_t			 dev = s->s_dev;
	int			 root_block;
	int			 size;
	__u32			 chksum;
	__u32			*bm;
	int			 ptype, stype;
	int			 mapidx;
	int			 num_bm;
	int			 i, j;
	int			 key;
	int			 blocksize;
	uid_t			 uid;
	gid_t			 gid;
	int			 reserved;
	int			 az_no;
	unsigned long		 mount_flags;
	unsigned long		 offset;

	pr_debug("affs_read_super(%s)\n",data ? (const char *)data : "no options");

	MOD_INC_USE_COUNT;

	if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
	    &blocksize,&s->u.affs_sb.s_prefix,s->u.affs_sb.s_volume,&mount_flags)) {
		s->s_dev = 0;
		printk("AFFS: error parsing options.\n");
		MOD_DEC_USE_COUNT;
		return NULL;
	}
	lock_super(s);

	/* Get the size of the device in 512-byte blocks.
	 * If we later see that the partition uses bigger
	 * blocks, we will have to change it.
	 */

	size = blksize_size[MAJOR(dev)][MINOR(dev)];
	size = (size ? size : BLOCK_SIZE) / 512 * blk_size[MAJOR(dev)][MINOR(dev)];

	s->u.affs_sb.s_bitmap  = NULL;
	s->u.affs_sb.s_root_bh = NULL;
	s->u.affs_sb.s_flags   = mount_flags;
	s->u.affs_sb.s_mode    = i;
	s->u.affs_sb.s_uid     = uid;
	s->u.affs_sb.s_gid     = gid;

	if (size == 0) {
		s->s_dev = 0;
		unlock_super(s);
		printk("affs_read_super: could not determine device size\n");
		goto out;
	}
	s->u.affs_sb.s_partition_size = size;
	s->u.affs_sb.s_reserved       = reserved;

	/* Try to find root block. Its location may depend on the block size. */

	s->u.affs_sb.s_hashsize = 0;
	if (blocksize > 0) {
		i = blocksize;
		j = blocksize;
	} else {
		i = 512;
		j = 4096;
	}
	for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) {
		if (root_block < 0)
			s->u.affs_sb.s_root_block = (reserved + size - 1) / 2;
		else
			s->u.affs_sb.s_root_block = root_block;
		set_blocksize(dev,blocksize);

		/* The root block location that was calculated above is not
		 * correct if the partition size is an odd number of 512-
		 * byte blocks, which will be rounded down to a number of
		 * 1024-byte blocks, and if there were an even number of
		 * reserved blocks. Ideally, all partition checkers should
		 * report the real number of blocks of the real blocksize,
		 * but since this just cannot be done, we have to try to
		 * find the root block anyways. In the above case, it is one
		 * block behind the calculated one. So we check this one, too.
		 */
		for (num_bm = 0; num_bm < 2; num_bm++) {
			pr_debug("AFFS: Dev %s - trying bs=%d bytes, root at %d, "
				 "size=%d blocks, %d reserved\n",kdevname(dev),blocksize,
				 s->u.affs_sb.s_root_block + num_bm,size,reserved);
			bh = affs_bread(dev,s->u.affs_sb.s_root_block + num_bm,blocksize);
			if (!bh) {
				printk("AFFS: unable to read root block\n");
				goto out;
			}
			if (!affs_checksum_block(blocksize,bh->b_data,&ptype,&stype) &&
			    ptype == T_SHORT && stype == ST_ROOT) {
				s->s_blocksize             = blocksize;
				s->u.affs_sb.s_hashsize    = blocksize / 4 - 56;
				s->u.affs_sb.s_root_block += num_bm;
				key                        = 1;
				break;
			}
		}
		if (key)
			break;
		affs_brelse(bh);
		bh = NULL;
	}
	if (!key) {
		affs_brelse(bh);
		if (!silent)
			printk("AFFS: Can't find a valid root block on device %s\n",kdevname(dev));
		goto out;
	}
	root_block = s->u.affs_sb.s_root_block;

	s->u.affs_sb.s_partition_size   = size;
	s->s_blocksize_bits             = blocksize == 512 ? 9 :
					  blocksize == 1024 ? 10 :
					  blocksize == 2048 ? 11 : 12;

	/* Find out which kind of FS we have */
	bb = affs_bread(dev,0,s->s_blocksize);
	if (bb) {
		chksum = htonl(*(__u32 *)bb->b_data);
		switch (chksum) {
			case MUFS_FS:
			case MUFS_INTLFFS:
				s->u.affs_sb.s_flags |= SF_MUFS;
				/* fall thru */
			case FS_INTLFFS:
				s->u.affs_sb.s_flags |= SF_INTL;
				break;
			case MUFS_DCFFS:
			case MUFS_FFS:
				s->u.affs_sb.s_flags |= SF_MUFS;
				break;
			case FS_DCFFS:
			case FS_FFS:
				break;
			case MUFS_OFS:
				s->u.affs_sb.s_flags |= SF_MUFS;
				/* fall thru */
			case FS_OFS:
				s->u.affs_sb.s_flags |= SF_OFS;
				break;
			case MUFS_DCOFS:
				if (!(s->s_flags & MS_RDONLY)) {
					printk("AFFS: Dircache FS - mounting %s read only.\n",
					       kdevname(dev));
				}
				/* fall thru */
			case MUFS_INTLOFS:
				s->u.affs_sb.s_flags |= SF_MUFS;
				if (0)
				/* fall thru */
			case FS_DCOFS:
				if (!(s->s_flags & MS_RDONLY)) {
					printk("AFFS: Dircache FS - mounting %s read only.\n",
					       kdevname(dev));
				}
				/* fall thru */
			case FS_INTLOFS:
				s->u.affs_sb.s_flags |= SF_INTL | SF_OFS;
				break;
			default:
				printk("AFFS: Unknown filesystem on device %s: %08X\n",
				       kdevname(dev),chksum);
				affs_brelse(bb);
				goto out;
		}
		affs_brelse(bb);
	} else {
		printk("AFFS: Can't get boot block.\n");
		goto out;
	}
	if (mount_flags & SF_VERBOSE) {
		chksum = ntohl(chksum);
		printk("AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n",
		       GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0],
		       &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1],
		       (char *)&chksum,((char *)&chksum)[3] + '0',blocksize);
	}
Пример #3
0
struct super_block *minix_read_super(struct super_block *s,void *data)
{
	struct buffer_head *bh;
	struct minix_super_block *ms;
	int i,dev=s->s_dev,block;

	lock_super(s);
	if (!(bh = bread(dev,1,BLOCK_SIZE))) {
		s->s_dev=0;
		free_super(s);
		printk("bread failed\n");
		return NULL;
	}
	ms = (struct minix_super_block *) bh->b_data;
	s->s_blocksize = 1024;
	s->u.minix_sb.s_ninodes = ms->s_ninodes;
	s->u.minix_sb.s_nzones = ms->s_nzones;
	s->u.minix_sb.s_imap_blocks = ms->s_imap_blocks;
	s->u.minix_sb.s_zmap_blocks = ms->s_zmap_blocks;
	s->u.minix_sb.s_firstdatazone = ms->s_firstdatazone;
	s->u.minix_sb.s_log_zone_size = ms->s_log_zone_size;
	s->u.minix_sb.s_max_size = ms->s_max_size;
	s->s_magic = ms->s_magic;
	brelse(bh);
	if (s->s_magic != MINIX_SUPER_MAGIC) {
		s->s_dev = 0;
		free_super(s);
		printk("magic match failed\n");
		return NULL;
	}
	for (i=0;i < MINIX_I_MAP_SLOTS;i++)
		s->u.minix_sb.s_imap[i] = NULL;
	for (i=0;i < MINIX_Z_MAP_SLOTS;i++)
		s->u.minix_sb.s_zmap[i] = NULL;
	block=2;
	for (i=0 ; i < s->u.minix_sb.s_imap_blocks ; i++)
		if (s->u.minix_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE))
			block++;
		else
			break;
	for (i=0 ; i < s->u.minix_sb.s_zmap_blocks ; i++)
		if (s->u.minix_sb.s_zmap[i]=bread(dev,block,BLOCK_SIZE))
			block++;
		else
			break;
	if (block != 2+s->u.minix_sb.s_imap_blocks+s->u.minix_sb.s_zmap_blocks) {
		for(i=0;i<MINIX_I_MAP_SLOTS;i++)
			brelse(s->u.minix_sb.s_imap[i]);
		for(i=0;i<MINIX_Z_MAP_SLOTS;i++)
			brelse(s->u.minix_sb.s_zmap[i]);
		s->s_dev=0;
		free_super(s);
		printk("block failed\n");
		return NULL;
	}
	s->u.minix_sb.s_imap[0]->b_data[0] |= 1;
	s->u.minix_sb.s_zmap[0]->b_data[0] |= 1;
	free_super(s);
	/* set up enough so that it can read an inode */
	s->s_dev = dev;
	s->s_op = &minix_sops;
	if (!(s->s_mounted = iget(dev,MINIX_ROOT_INO))) {
		s->s_dev=0;
		printk("get root inode failed\n");
		return NULL;
	}
	return s;
}
Пример #4
0
void proc_put_super(struct super_block *sb)
{
	lock_super(sb);
	sb->s_dev = 0;
	unlock_super(sb);
}
Пример #5
0
/*
 * There are two policies for allocating an inode.  If the new inode is
 * a directory, then a forward search is made for a block group with both
 * free space and a low directory-to-inode ratio; if that fails, then of
 * the groups with above-average free space, that group with the fewest
 * directories already is chosen.
 *
 * For other inodes, search forward from the parent directory's block
 * group to find a free inode.
 */
struct inode * ufs_new_inode(struct inode * dir, int mode)
{
	struct super_block * sb;
	struct ufs_sb_info * sbi;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	struct ufs_cg_private_info * ucpi;
	struct ufs_cylinder_group * ucg;
	struct inode * inode;
	unsigned cg, bit, i, j, start;
	struct ufs_inode_info *ufsi;
	int err = -ENOSPC;

	UFSD("ENTER\n");
	
	/* Cannot create files in a deleted directory */
	if (!dir || !dir->i_nlink)
		return ERR_PTR(-EPERM);
	sb = dir->i_sb;
	inode = new_inode(sb);
	if (!inode)
		return ERR_PTR(-ENOMEM);
	ufsi = UFS_I(inode);
	sbi = UFS_SB(sb);
	uspi = sbi->s_uspi;
	usb1 = ubh_get_usb_first(uspi);

	lock_super (sb);

	/*
	 * Try to place the inode in its parent directory
	 */
	i = ufs_inotocg(dir->i_ino);
	if (sbi->fs_cs(i).cs_nifree) {
		cg = i;
		goto cg_found;
	}

	/*
	 * Use a quadratic hash to find a group with a free inode
	 */
	for ( j = 1; j < uspi->s_ncg; j <<= 1 ) {
		i += j;
		if (i >= uspi->s_ncg)
			i -= uspi->s_ncg;
		if (sbi->fs_cs(i).cs_nifree) {
			cg = i;
			goto cg_found;
		}
	}

	/*
	 * That failed: try linear search for a free inode
	 */
	i = ufs_inotocg(dir->i_ino) + 1;
	for (j = 2; j < uspi->s_ncg; j++) {
		i++;
		if (i >= uspi->s_ncg)
			i = 0;
		if (sbi->fs_cs(i).cs_nifree) {
			cg = i;
			goto cg_found;
		}
	}

	goto failed;

cg_found:
	ucpi = ufs_load_cylinder (sb, cg);
	if (!ucpi) {
		err = -EIO;
		goto failed;
	}
	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
	if (!ufs_cg_chkmagic(sb, ucg)) 
		ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number");

	start = ucpi->c_irotor;
	bit = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, uspi->s_ipg, start);
	if (!(bit < uspi->s_ipg)) {
		bit = ubh_find_first_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, start);
		if (!(bit < start)) {
			ufs_error (sb, "ufs_new_inode",
			    "cylinder group %u corrupted - error in inode bitmap\n", cg);
			err = -EIO;
			goto failed;
		}
	}
	UFSD("start = %u, bit = %u, ipg = %u\n", start, bit, uspi->s_ipg);
	if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit))
		ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit);
	else {
		ufs_panic (sb, "ufs_new_inode", "internal error");
		err = -EIO;
		goto failed;
	}

	if (uspi->fs_magic == UFS2_MAGIC) {
		u32 initediblk = fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk);

		if (bit + uspi->s_inopb > initediblk &&
		    initediblk < fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_niblk))
			ufs2_init_inodes_chunk(sb, ucpi, ucg);
	}

	fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1);
	uspi->cs_total.cs_nifree--;
	fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1);
	
	if (S_ISDIR(mode)) {
		fs32_add(sb, &ucg->cg_cs.cs_ndir, 1);
		uspi->cs_total.cs_ndir++;
		fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1);
	}
	ubh_mark_buffer_dirty (USPI_UBH(uspi));
	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
	if (sb->s_flags & MS_SYNCHRONOUS) {
		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
		ubh_wait_on_buffer (UCPI_UBH(ucpi));
	}
	sb->s_dirt = 1;

	inode->i_ino = cg * uspi->s_ipg + bit;
	inode->i_mode = mode;
	inode->i_uid = current_fsuid();
	if (dir->i_mode & S_ISGID) {
		inode->i_gid = dir->i_gid;
		if (S_ISDIR(mode))
			inode->i_mode |= S_ISGID;
	} else
		inode->i_gid = current_fsgid();

	inode->i_blocks = 0;
	inode->i_generation = 0;
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
	ufsi->i_flags = UFS_I(dir)->i_flags;
	ufsi->i_lastfrag = 0;
	ufsi->i_shadow = 0;
	ufsi->i_osync = 0;
	ufsi->i_oeftflag = 0;
	ufsi->i_dir_start_lookup = 0;
	memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1));
	insert_inode_hash(inode);
	mark_inode_dirty(inode);

	if (uspi->fs_magic == UFS2_MAGIC) {
		struct buffer_head *bh;
		struct ufs2_inode *ufs2_inode;

		/*
		 * setup birth date, we do it here because of there is no sense
		 * to hold it in struct ufs_inode_info, and lose 64 bit
		 */
		bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
		if (!bh) {
			ufs_warning(sb, "ufs_read_inode",
				    "unable to read inode %lu\n",
				    inode->i_ino);
			err = -EIO;
			goto fail_remove_inode;
		}
		lock_buffer(bh);
		ufs2_inode = (struct ufs2_inode *)bh->b_data;
		ufs2_inode += ufs_inotofsbo(inode->i_ino);
		ufs2_inode->ui_birthtime = cpu_to_fs64(sb, CURRENT_TIME.tv_sec);
		ufs2_inode->ui_birthnsec = cpu_to_fs32(sb, CURRENT_TIME.tv_nsec);
		mark_buffer_dirty(bh);
		unlock_buffer(bh);
		if (sb->s_flags & MS_SYNCHRONOUS)
			sync_dirty_buffer(bh);
		brelse(bh);
	}

	unlock_super (sb);

	if (DQUOT_ALLOC_INODE(inode)) {
		DQUOT_DROP(inode);
		err = -EDQUOT;
		goto fail_without_unlock;
	}

	UFSD("allocating inode %lu\n", inode->i_ino);
	UFSD("EXIT\n");
	return inode;

fail_remove_inode:
	unlock_super(sb);
fail_without_unlock:
	inode->i_flags |= S_NOQUOTA;
	inode->i_nlink = 0;
	iput(inode);
	UFSD("EXIT (FAILED): err %d\n", err);
	return ERR_PTR(err);
failed:
	unlock_super (sb);
	make_bad_inode(inode);
	iput (inode);
	UFSD("EXIT (FAILED): err %d\n", err);
	return ERR_PTR(err);
}
Пример #6
0
u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
                      u64 goal, unsigned count, int *err,
                      struct page *locked_page)
{
    struct super_block * sb;
    struct ufs_sb_private_info * uspi;
    struct ufs_super_block_first * usb1;
    unsigned cgno, oldcount, newcount;
    u64 tmp, request, result;

    UFSD("ENTER, ino %lu, fragment %llu, goal %llu, count %u\n",
         inode->i_ino, (unsigned long long)fragment,
         (unsigned long long)goal, count);

    sb = inode->i_sb;
    uspi = UFS_SB(sb)->s_uspi;
    usb1 = ubh_get_usb_first(uspi);
    *err = -ENOSPC;

    lock_super (sb);
    tmp = ufs_data_ptr_to_cpu(sb, p);

    if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
        ufs_warning(sb, "ufs_new_fragments", "internal warning"
                    " fragment %llu, count %u",
                    (unsigned long long)fragment, count);
        count = uspi->s_fpb - ufs_fragnum(fragment);
    }
    oldcount = ufs_fragnum (fragment);
    newcount = oldcount + count;

    /*
     * Somebody else has just allocated our fragments
     */
    if (oldcount) {
        if (!tmp) {
            ufs_error(sb, "ufs_new_fragments", "internal error, "
                      "fragment %llu, tmp %llu\n",
                      (unsigned long long)fragment,
                      (unsigned long long)tmp);
            unlock_super(sb);
            return INVBLOCK;
        }
        if (fragment < UFS_I(inode)->i_lastfrag) {
            UFSD("EXIT (ALREADY ALLOCATED)\n");
            unlock_super (sb);
            return 0;
        }
    }
    else {
        if (tmp) {
            UFSD("EXIT (ALREADY ALLOCATED)\n");
            unlock_super(sb);
            return 0;
        }
    }

    /*
     * There is not enough space for user on the device
     */
    if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) {
        unlock_super (sb);
        UFSD("EXIT (FAILED)\n");
        return 0;
    }

    if (goal >= uspi->s_size)
        goal = 0;
    if (goal == 0)
        cgno = ufs_inotocg (inode->i_ino);
    else
        cgno = ufs_dtog(uspi, goal);

    /*
     * allocate new fragment
     */
    if (oldcount == 0) {
        result = ufs_alloc_fragments (inode, cgno, goal, count, err);
        if (result) {
            ufs_cpu_to_data_ptr(sb, p, result);
            *err = 0;
            UFS_I(inode)->i_lastfrag =
                max_t(u32, UFS_I(inode)->i_lastfrag,
                      fragment + count);
            ufs_clear_frags(inode, result + oldcount,
                            newcount - oldcount, locked_page != NULL);
        }
        unlock_super(sb);
        UFSD("EXIT, result %llu\n", (unsigned long long)result);
        return result;
    }

    /*
     * resize block
     */
    result = ufs_add_fragments (inode, tmp, oldcount, newcount, err);
    if (result) {
        *err = 0;
        UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
        ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
                        locked_page != NULL);
        unlock_super(sb);
        UFSD("EXIT, result %llu\n", (unsigned long long)result);
        return result;
    }

    /*
     * allocate new block and move data
     */
    switch (fs32_to_cpu(sb, usb1->fs_optim)) {
    case UFS_OPTSPACE:
        request = newcount;
        if (uspi->s_minfree < 5 || uspi->cs_total.cs_nffree
                > uspi->s_dsize * uspi->s_minfree / (2 * 100))
            break;
        usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
        break;
    default:
        usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);

    case UFS_OPTTIME:
        request = uspi->s_fpb;
        if (uspi->cs_total.cs_nffree < uspi->s_dsize *
                (uspi->s_minfree - 2) / 100)
            break;
        usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
        break;
    }
    result = ufs_alloc_fragments (inode, cgno, goal, request, err);
    if (result) {
        ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
                        locked_page != NULL);
        ufs_change_blocknr(inode, fragment - oldcount, oldcount,
                           uspi->s_sbbase + tmp,
                           uspi->s_sbbase + result, locked_page);
        ufs_cpu_to_data_ptr(sb, p, result);
        *err = 0;
        UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
        unlock_super(sb);
        if (newcount < request)
            ufs_free_fragments (inode, result + newcount, request - newcount);
        ufs_free_fragments (inode, tmp, oldcount);
        UFSD("EXIT, result %llu\n", (unsigned long long)result);
        return result;
    }

    unlock_super(sb);
    UFSD("EXIT (FAILED)\n");
    return 0;
}
Пример #7
0
struct super_block *sysv_read_super(struct super_block *sb,void *data,
				     int silent)
{
	struct buffer_head *bh;
	const char *found;
	kdev_t dev = sb->s_dev;
	struct inode *root_inode;
	unsigned long blocknr;
	
	if (1024 != sizeof (struct xenix_super_block))
		panic("Xenix FS: bad super-block size");
	if ((512 != sizeof (struct sysv4_super_block))
            || (512 != sizeof (struct sysv2_super_block)))
		panic("SystemV FS: bad super-block size");
	if (500 != sizeof (struct coh_super_block))
		panic("Coherent FS: bad super-block size");
	if (64 != sizeof (struct sysv_inode))
		panic("sysv fs: bad i-node size");
	MOD_INC_USE_COUNT;
	lock_super(sb);
	set_blocksize(dev,BLOCK_SIZE);
	sb->sv_block_base = 0;

	/* Try to read Xenix superblock */
	if ((bh = bread(dev, 1, BLOCK_SIZE)) != NULL) {
		if ((found = detect_xenix(sb,bh)) != NULL)
			goto ok;
		brelse(bh);
	}
	if ((bh = bread(dev, 0, BLOCK_SIZE)) != NULL) {
		/* Try to recognize SystemV superblock */
		if ((found = detect_sysv4(sb,bh)) != NULL)
			goto ok;
		if ((found = detect_sysv2(sb,bh)) != NULL)
			goto ok;
		/* Try to recognize Coherent superblock */
		if ((found = detect_coherent(sb,bh)) != NULL)
			goto ok;
		brelse(bh);
	}
	/* Try to recognize SystemV superblock */
	/* Offset by 1 track, i.e. most probably 9, 15, or 18 kilobytes. */
	/* 2kB blocks with offset of 9 and 15 kilobytes are not supported. */
	/* Maybe we should also check the device geometry ? */
	{	static int offsets[] = { 9, 15, 18, };
		int i;
		for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++)
			if ((bh = bread(dev, offsets[i], BLOCK_SIZE)) != NULL) {
				/* Try to recognize SystemV superblock */
				if ((found = detect_sysv4(sb,bh)) != NULL) {
					if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2))
						goto bad_shift;
					sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
					goto ok;
				}
				if ((found = detect_sysv2(sb,bh)) != NULL) {
					if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2))
						goto bad_shift;
					sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
					goto ok;
				}
				brelse(bh);
			}
	}
	bad_shift:
	sb->s_dev = 0;
	unlock_super(sb);
	if (!silent)
		printk("VFS: unable to read Xenix/SystemV/Coherent superblock on device "
		       "%s\n", kdevname(dev));
	failed:
	MOD_DEC_USE_COUNT;
	return NULL;

	ok:
	if (sb->sv_block_size >= BLOCK_SIZE) {
		if (sb->sv_block_size != BLOCK_SIZE) {
			brelse(bh);
			set_blocksize(dev, sb->sv_block_size);
			blocknr = (bh->b_blocknr << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
			if ((bh = bread(dev, blocknr, sb->sv_block_size)) == NULL)
				goto bad_superblock;
		}
		switch (sb->sv_type) {
			case FSTYPE_XENIX:
				if (!detected_xenix(sb,bh,bh))
					goto bad_superblock;
				break;
			case FSTYPE_SYSV4:
				if (!detected_sysv4(sb,bh))
					goto bad_superblock;
				break;
			case FSTYPE_SYSV2:
				if (!detected_sysv2(sb,bh))
					goto bad_superblock;
				break;
			default: goto bad_superblock;
		goto superblock_ok;
		bad_superblock:
			brelse(bh);
			sb->s_dev = 0;
			unlock_super(sb);
			printk("SysV FS: cannot read superblock in %d byte mode\n", sb->sv_block_size);
			goto failed;
		superblock_ok:
		}
	} else {
Пример #8
0
struct super_block *
ncp_read_super(struct super_block *sb, void *raw_data, int silent)
{
	struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
	struct ncp_server *server;
	struct file *ncp_filp;
	struct inode *root_inode;
	kdev_t dev = sb->s_dev;
	int error;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
	int options;
#endif
	struct ncpfs_inode_info finfo;

	MOD_INC_USE_COUNT;
	if (data == NULL)
		goto out_no_data;
	if (data->version != NCP_MOUNT_VERSION)
		goto out_bad_mount;
	ncp_filp = fget(data->ncp_fd);
	if (!ncp_filp)
		goto out_bad_file;
	if (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))
		goto out_bad_file2;

	lock_super(sb);

	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
	sb->s_blocksize_bits = 10;
	sb->s_magic = NCP_SUPER_MAGIC;
	sb->s_dev = dev;
	sb->s_op = &ncp_sops;

	/* We must malloc our own super-block info */
	server = (struct ncp_server *) ncp_kmalloc(sizeof(struct ncp_server),
						   GFP_KERNEL);
	if (server == NULL)
		goto out_no_server;
	NCP_SBP(sb) = server;

	server->ncp_filp = ncp_filp;
	server->lock = 0;
	server->wait = NULL;
	server->packet = NULL;
	server->buffer_size = 0;
	server->conn_status = 0;
	server->root_dentry = NULL;
	server->root_setuped = 0;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
	server->sign_wanted = 0;
	server->sign_active = 0;
#endif
	server->auth.auth_type = NCP_AUTH_NONE;
	server->auth.object_name_len = 0;
	server->auth.object_name = NULL;
	server->auth.object_type = 0;
	server->priv.len = 0;
	server->priv.data = NULL;

	server->m = *data;
	/* Althought anything producing this is buggy, it happens
	   now because of PATH_MAX changes.. */
	if (server->m.time_out < 10) {
		server->m.time_out = 10;
		printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
	}
	server->m.file_mode = (server->m.file_mode &
			       (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
	server->m.dir_mode = (server->m.dir_mode &
			      (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;

	server->packet_size = NCP_PACKET_SIZE;
	server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
	if (server->packet == NULL)
		goto out_no_packet;

	ncp_lock_server(server);
	error = ncp_connect(server);
	ncp_unlock_server(server);
	if (error < 0)
		goto out_no_connect;
	DPRINTK(KERN_DEBUG "ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));

#ifdef CONFIG_NCPFS_PACKET_SIGNING
	if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE,
		NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
	{
		if (options != NCP_DEFAULT_OPTIONS)
		{
			if (ncp_negotiate_size_and_options(server, 
				NCP_DEFAULT_BUFSIZE,
				options & 2, 
				&(server->buffer_size), &options) != 0)
				
			{
				goto out_no_bufsize;
			}
		}
		if (options & 2)
			server->sign_wanted = 1;
	}
	else 
#endif	/* CONFIG_NCPFS_PACKET_SIGNING */
	if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
  				     &(server->buffer_size)) != 0)
		goto out_no_bufsize;
	DPRINTK(KERN_DEBUG "ncpfs: bufsize = %d\n", server->buffer_size);

	ncp_init_root(server, &finfo);
	server->name_space[finfo.nw_info.i.volNumber] = NW_NS_DOS;
        root_inode = ncp_iget(sb, &finfo);
        if (!root_inode)
		goto out_no_root;
	DPRINTK(KERN_DEBUG "ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
        server->root_dentry = sb->s_root = d_alloc_root(root_inode, NULL);
        if (!sb->s_root)
		goto out_no_root;
	server->root_dentry->d_op = &ncp_dentry_operations;
	unlock_super(sb);
	return sb;

out_no_root:
	printk(KERN_ERR "ncp_read_super: get root inode failed\n");
	iput(root_inode);
	goto out_disconnect;
out_no_bufsize:
	printk(KERN_ERR "ncp_read_super: could not get bufsize\n");
out_disconnect:
	ncp_lock_server(server);
	ncp_disconnect(server);
	ncp_unlock_server(server);
	goto out_free_packet;
out_no_connect:
	printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error);
out_free_packet:
	ncp_kfree_s(server->packet, server->packet_size);
	goto out_free_server;
out_no_packet:
	printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
out_free_server:
	ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
	goto out_unlock;
out_no_server:
	printk(KERN_ERR "ncp_read_super: could not alloc ncp_server\n");
out_unlock:
	/* 23/12/1998 Marcin Dalecki <*****@*****.**>:
	 * 
	 * The previously used put_filp(ncp_filp); was bogous, since
	 * it doesn't proper unlocking.
	 */
	fput(ncp_filp);
	unlock_super(sb);
	goto out;

out_bad_file2:
	fput(ncp_filp);
out_bad_file:
	printk(KERN_ERR "ncp_read_super: invalid ncp socket\n");
	goto out;
out_bad_mount:
	printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n",
		NCP_MOUNT_VERSION);
	goto out;
out_no_data:
	printk(KERN_ERR "ncp_read_super: missing data argument\n");
out:
	sb->s_dev = 0;
	MOD_DEC_USE_COUNT;
	return NULL;
}
Пример #9
0
/*
 * NOTE! When we get the inode, we're the only people
 * that have access to it, and as such there are no
 * race conditions we have to worry about. The inode
 * is not on the hash-lists, and it cannot be reached
 * through the filesystem because the directory entry
 * has been deleted earlier.
 *
 * HOWEVER: we must make sure that we get no aliases,
 * which means that we have to call "clear_inode()"
 * _before_ we mark the inode not in use in the inode
 * bitmaps. Otherwise a newly created file might use
 * the same inode number (not actually the same pointer
 * though), and then we'd have two inodes sharing the
 * same inode number and space on the harddisk.
 */
void ext2_free_inode (struct inode * inode)
{
	struct super_block * sb = inode->i_sb;
	int is_directory;
	unsigned long ino;
	struct buffer_head * bh;
	struct buffer_head * bh2;
	unsigned long block_group;
	unsigned long bit;
	int bitmap_nr;
	struct ext2_group_desc * gdp;
	struct ext2_super_block * es;

	if (!inode->i_dev) {
		printk ("ext2_free_inode: inode has no device\n");
		return;
	}
	if (inode->i_count > 1) {
		printk ("ext2_free_inode: inode has count=%d\n", inode->i_count);
		return;
	}
	if (inode->i_nlink) {
		printk ("ext2_free_inode: inode has nlink=%d\n",
			(int) inode->i_nlink);
		return;
	}
	if (!sb) {
		printk("ext2_free_inode: inode on nonexistent device\n");
		return;
	}

	ino = inode->i_ino;
	ext2_debug ("freeing inode %lu\n", ino);

	/*
	 * Note: we must free any quota before locking the superblock,
	 * as writing the quota to disk may need the lock as well.
	 */
	DQUOT_FREE_INODE(sb, inode);
	DQUOT_DROP(inode);

	lock_super (sb);
	es = sb->u.ext2_sb.s_es;
	if (ino < EXT2_FIRST_INO(sb) || 
	    ino > le32_to_cpu(es->s_inodes_count)) {
		ext2_error (sb, "free_inode",
			    "reserved inode or nonexistent inode");
		goto error_return;
	}
	block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb);
	bit = (ino - 1) % EXT2_INODES_PER_GROUP(sb);
	bitmap_nr = load_inode_bitmap (sb, block_group);
	if (bitmap_nr < 0)
		goto error_return;
	
	bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];

	is_directory = S_ISDIR(inode->i_mode);

	/* Do this BEFORE marking the inode not in use */
	clear_inode (inode);

	/* Ok, now we can actually update the inode bitmaps.. */
	if (!ext2_clear_bit (bit, bh->b_data))
		ext2_warning (sb, "ext2_free_inode",
			      "bit already cleared for inode %lu", ino);
	else {
		gdp = ext2_get_group_desc (sb, block_group, &bh2);
		if (gdp) {
			gdp->bg_free_inodes_count =
				cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) + 1);
			if (is_directory)
				gdp->bg_used_dirs_count =
					cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) - 1);
		}
		mark_buffer_dirty(bh2, 1);
		es->s_free_inodes_count =
			cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
		mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
	}
	mark_buffer_dirty(bh, 1);
	if (sb->s_flags & MS_SYNCHRONOUS) {
		ll_rw_block (WRITE, 1, &bh);
		wait_on_buffer (bh);
	}
	sb->s_dirt = 1;
error_return:
	unlock_super (sb);
}
Пример #10
0
static void presto_put_super(struct super_block *sb)
{
        struct presto_cache *cache;
        struct upc_channel *channel;
        struct super_operations *sops;
        struct list_head *lh;
        int err;

        ENTRY;
        cache = presto_cache_find(sb->s_dev);
        if (!cache) {
                EXIT;
                goto exit;
        }
        channel = &izo_channels[presto_c2m(cache)];
        sops = filter_c2csops(cache->cache_filter);
        err = izo_clear_all_fsetroots(cache); 
        if (err) { 
                CERROR("%s: err %d\n", __FUNCTION__, err);
        }
        PRESTO_FREE(cache->cache_vfsmount, sizeof(struct vfsmount));

        /* look at kill_super - fsync_super is not exported GRRR but 
           probably not needed */ 
        unlock_super(sb);
        shrink_dcache_parent(cache->cache_root); 
        dput(cache->cache_root); 
        //fsync_super(sb); 
        lock_super(sb);

        if (sops->write_super)
                sops->write_super(sb); 

        if (sops->put_super)
                sops->put_super(sb);

        /* free any remaining async upcalls when the filesystem is unmounted */
        spin_lock(&channel->uc_lock);
        lh = channel->uc_pending.next;
        while ( lh != &channel->uc_pending) {
                struct upc_req *req;
                req = list_entry(lh, struct upc_req, rq_chain);

                /* assignment must be here: we are about to free &lh */
                lh = lh->next;
                if ( ! (req->rq_flags & REQ_ASYNC) ) 
                        continue;
                list_del(&(req->rq_chain));
                PRESTO_FREE(req->rq_data, req->rq_bufsize);
                PRESTO_FREE(req, sizeof(struct upc_req));
        }
        list_del(&cache->cache_channel_list); 
        spin_unlock(&channel->uc_lock);

        presto_free_cache(cache);

exit:
        CDEBUG(D_MALLOC, "after umount: kmem %ld, vmem %ld\n",
               presto_kmemory, presto_vmemory);
        MOD_DEC_USE_COUNT;
        return ;
}
Пример #11
0
struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
{
	struct super_block *sb;
	struct inode * inode;
	int block;
	uint32_t start = UDF_I_LOCATION(dir).logicalBlockNum;

	sb = dir->i_sb;
	inode = new_inode(sb);

	if (!inode)
	{
		*err = -ENOMEM;
		return NULL;
	}
	*err = -ENOSPC;

	block = udf_new_block(dir->i_sb, NULL, UDF_I_LOCATION(dir).partitionReferenceNum,
		start, err);
	if (*err)
	{
		iput(inode);
		return NULL;
	}
	lock_super(sb);

	if (UDF_SB_LVIDBH(sb))
	{
		struct logicalVolHeaderDesc *lvhd;
		uint64_t uniqueID;
		lvhd = (struct logicalVolHeaderDesc *)(UDF_SB_LVID(sb)->logicalVolContentsUse);
		if (S_ISDIR(mode))
			UDF_SB_LVIDIU(sb)->numDirs =
				cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs) + 1);
		else
			UDF_SB_LVIDIU(sb)->numFiles =
				cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) + 1);
		UDF_I_UNIQUE(inode) = uniqueID = le64_to_cpu(lvhd->uniqueID);
		if (!(++uniqueID & 0x00000000FFFFFFFFUL))
			uniqueID += 16;
		lvhd->uniqueID = cpu_to_le64(uniqueID);
		mark_buffer_dirty(UDF_SB_LVIDBH(sb));
	}
	inode->i_mode = mode;
	inode->i_uid = current->fsuid;
	if (dir->i_mode & S_ISGID)
	{
		inode->i_gid = dir->i_gid;
		if (S_ISDIR(mode))
			mode |= S_ISGID;
	}
	else
		inode->i_gid = current->fsgid;

	UDF_I_LOCATION(inode).logicalBlockNum = block;
	UDF_I_LOCATION(inode).partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
	inode->i_ino = udf_get_lb_pblock(sb, UDF_I_LOCATION(inode), 0);
	inode->i_blksize = PAGE_SIZE;
	inode->i_blocks = 0;
	UDF_I_LENEATTR(inode) = 0;
	UDF_I_LENALLOC(inode) = 0;
	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE))
	{
		UDF_I_EXTENDED_FE(inode) = 1;
		UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE);
	}
	else
		UDF_I_EXTENDED_FE(inode) = 0;
	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
	else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
	else
		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
	inode->i_mtime = inode->i_atime = inode->i_ctime =
		UDF_I_CRTIME(inode) = CURRENT_TIME;
	UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) =
		UDF_I_UCRTIME(inode) = CURRENT_UTIME;
	UDF_I_NEW_INODE(inode) = 1;
	insert_inode_hash(inode);
	mark_inode_dirty(inode);

	unlock_super(sb);
	if (DQUOT_ALLOC_INODE(inode))
	{
		DQUOT_DROP(inode);
		inode->i_flags |= S_NOQUOTA;
		inode->i_nlink = 0;
		iput(inode);
		*err = -EDQUOT;
		return NULL;
	}

	*err = 0;
	return inode;
}
Пример #12
0
struct super_block * ext2_read_super (struct super_block * sb, void * data,
				      int silent)
{
	struct buffer_head * bh;
	struct ext2_super_block * es;
	unsigned long sb_block = 1;
	unsigned short resuid = EXT2_DEF_RESUID;
	unsigned short resgid = EXT2_DEF_RESGID;
	unsigned long logic_sb_block = 1;
	kdev_t dev = sb->s_dev;
	int db_count;
	int i, j;

	set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
	if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
	    &sb->u.ext2_sb.s_mount_opt)) {
		sb->s_dev = 0;
		return NULL;
	}

	MOD_INC_USE_COUNT;
	lock_super (sb);
	set_blocksize (dev, BLOCK_SIZE);
	if (!(bh = bread (dev, sb_block, BLOCK_SIZE))) {
		sb->s_dev = 0;
		unlock_super (sb);
		printk ("EXT2-fs: unable to read superblock\n");
		MOD_DEC_USE_COUNT;
		return NULL;
	}
	/*
	 * Note: s_es must be initialized s_es as soon as possible because
	 * some ext2 macro-instructions depend on its value
	 */
	es = (struct ext2_super_block *) bh->b_data;
	sb->u.ext2_sb.s_es = es;
	sb->s_magic = es->s_magic;
	if (sb->s_magic != EXT2_SUPER_MAGIC) {
		if (!silent)
			printk ("VFS: Can't find an ext2 filesystem on dev "
				"%s.\n", kdevname(dev));
	failed_mount:
		sb->s_dev = 0;
		unlock_super (sb);
		if (bh)
			brelse(bh);
		MOD_DEC_USE_COUNT;
		return NULL;
	}
	if (es->s_rev_level > EXT2_GOOD_OLD_REV) {
		if (es->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP) {
			printk("EXT2-fs: %s: couldn't mount because of "
			       "unsupported optional features.\n", 
			       kdevname(dev));
			goto failed_mount;
		}
		if (!(sb->s_flags & MS_RDONLY) &&
		    (es->s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPP)) {
			printk("EXT2-fs: %s: couldn't mount RDWR because of "
			       "unsupported optional features.\n", 
			       kdevname(dev));
			goto failed_mount;
		}
	}
	sb->s_blocksize_bits = sb->u.ext2_sb.s_es->s_log_block_size + 10;
	sb->s_blocksize = 1 << sb->s_blocksize_bits;
	if (sb->s_blocksize != BLOCK_SIZE && 
	    (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||  
	     sb->s_blocksize == 4096)) {
		unsigned long offset;

		brelse (bh);
		set_blocksize (dev, sb->s_blocksize);
		logic_sb_block = (sb_block*BLOCK_SIZE) / sb->s_blocksize;
		offset = (sb_block*BLOCK_SIZE) % sb->s_blocksize;
		bh = bread (dev, logic_sb_block, sb->s_blocksize);
		if(!bh) {
			printk("EXT2-fs: Couldn't read superblock on "
			       "2nd try.\n");
			goto failed_mount;
		}
		es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
		sb->u.ext2_sb.s_es = es;
		if (es->s_magic != EXT2_SUPER_MAGIC) {
			printk ("EXT2-fs: Magic mismatch, very weird !\n");
			goto failed_mount;
		}
	}
	if (es->s_rev_level == EXT2_GOOD_OLD_REV) {
		sb->u.ext2_sb.s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
		sb->u.ext2_sb.s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
	} else {
		sb->u.ext2_sb.s_inode_size = es->s_inode_size;
		sb->u.ext2_sb.s_first_ino = es->s_first_ino;
		if (sb->u.ext2_sb.s_inode_size != EXT2_GOOD_OLD_INODE_SIZE) {
			printk ("EXT2-fs: unsupported inode size: %d\n",
				sb->u.ext2_sb.s_inode_size);
			goto failed_mount;
		}
	}
	sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
				   es->s_log_frag_size;
	if (sb->u.ext2_sb.s_frag_size)
		sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize /
						  sb->u.ext2_sb.s_frag_size;
	else
		sb->s_magic = 0;
	sb->u.ext2_sb.s_blocks_per_group = es->s_blocks_per_group;
	sb->u.ext2_sb.s_frags_per_group = es->s_frags_per_group;
	sb->u.ext2_sb.s_inodes_per_group = es->s_inodes_per_group;
	sb->u.ext2_sb.s_inodes_per_block = sb->s_blocksize /
					   EXT2_INODE_SIZE(sb);
	sb->u.ext2_sb.s_itb_per_group = sb->u.ext2_sb.s_inodes_per_group /
				        sb->u.ext2_sb.s_inodes_per_block;
	sb->u.ext2_sb.s_desc_per_block = sb->s_blocksize /
					 sizeof (struct ext2_group_desc);
	sb->u.ext2_sb.s_sbh = bh;
	if (resuid != EXT2_DEF_RESUID)
		sb->u.ext2_sb.s_resuid = resuid;
	else
		sb->u.ext2_sb.s_resuid = es->s_def_resuid;
	if (resgid != EXT2_DEF_RESGID)
		sb->u.ext2_sb.s_resgid = resgid;
	else
		sb->u.ext2_sb.s_resgid = es->s_def_resgid;
	sb->u.ext2_sb.s_mount_state = es->s_state;
	sb->u.ext2_sb.s_rename_lock = 0;
	sb->u.ext2_sb.s_rename_wait = NULL;
	sb->u.ext2_sb.s_addr_per_block_bits =
		log2 (EXT2_ADDR_PER_BLOCK(sb));
	sb->u.ext2_sb.s_desc_per_block_bits =
		log2 (EXT2_DESC_PER_BLOCK(sb));
	if (sb->s_magic != EXT2_SUPER_MAGIC) {
		if (!silent)
			printk ("VFS: Can't find an ext2 filesystem on dev "
				"%s.\n",
				kdevname(dev));
		goto failed_mount;
	}
	if (sb->s_blocksize != bh->b_size) {
		if (!silent)
			printk ("VFS: Unsupported blocksize on dev "
				"%s.\n", kdevname(dev));
		goto failed_mount;
	}

	if (sb->s_blocksize != sb->u.ext2_sb.s_frag_size) {
		printk ("EXT2-fs: fragsize %lu != blocksize %lu (not supported yet)\n",
			sb->u.ext2_sb.s_frag_size, sb->s_blocksize);
		goto failed_mount;
	}

	if (sb->u.ext2_sb.s_blocks_per_group > sb->s_blocksize * 8) {
		printk ("EXT2-fs: #blocks per group too big: %lu\n",
			sb->u.ext2_sb.s_blocks_per_group);
		goto failed_mount;
	}
	if (sb->u.ext2_sb.s_frags_per_group > sb->s_blocksize * 8) {
		printk ("EXT2-fs: #fragments per group too big: %lu\n",
			sb->u.ext2_sb.s_frags_per_group);
		goto failed_mount;
	}
	if (sb->u.ext2_sb.s_inodes_per_group > sb->s_blocksize * 8) {
		printk ("EXT2-fs: #inodes per group too big: %lu\n",
			sb->u.ext2_sb.s_inodes_per_group);
		goto failed_mount;
	}

	sb->u.ext2_sb.s_groups_count = (es->s_blocks_count -
				        es->s_first_data_block +
				       EXT2_BLOCKS_PER_GROUP(sb) - 1) /
				       EXT2_BLOCKS_PER_GROUP(sb);
	db_count = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
		   EXT2_DESC_PER_BLOCK(sb);
	sb->u.ext2_sb.s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL);
	if (sb->u.ext2_sb.s_group_desc == NULL) {
		printk ("EXT2-fs: not enough memory\n");
		goto failed_mount;
	}
	for (i = 0; i < db_count; i++) {
		sb->u.ext2_sb.s_group_desc[i] = bread (dev, logic_sb_block + i + 1,
						       sb->s_blocksize);
		if (!sb->u.ext2_sb.s_group_desc[i]) {
			for (j = 0; j < i; j++)
				brelse (sb->u.ext2_sb.s_group_desc[j]);
			kfree_s (sb->u.ext2_sb.s_group_desc,
				 db_count * sizeof (struct buffer_head *));
			printk ("EXT2-fs: unable to read group descriptors\n");
			goto failed_mount;
		}
	}
	if (!ext2_check_descriptors (sb)) {
		for (j = 0; j < db_count; j++)
			brelse (sb->u.ext2_sb.s_group_desc[j]);
		kfree_s (sb->u.ext2_sb.s_group_desc,
			 db_count * sizeof (struct buffer_head *));
		printk ("EXT2-fs: group descriptors corrupted !\n");
		goto failed_mount;
	}
	for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
		sb->u.ext2_sb.s_inode_bitmap_number[i] = 0;
		sb->u.ext2_sb.s_inode_bitmap[i] = NULL;
		sb->u.ext2_sb.s_block_bitmap_number[i] = 0;
		sb->u.ext2_sb.s_block_bitmap[i] = NULL;
	}
	sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
	sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
	sb->u.ext2_sb.s_db_per_group = db_count;
	unlock_super (sb);
	/*
	 * set up enough so that it can read an inode
	 */
	sb->s_dev = dev;
	sb->s_op = &ext2_sops;
	if (!(sb->s_mounted = iget (sb, EXT2_ROOT_INO))) {
		sb->s_dev = 0;
		for (i = 0; i < db_count; i++)
			if (sb->u.ext2_sb.s_group_desc[i])
				brelse (sb->u.ext2_sb.s_group_desc[i]);
		kfree_s (sb->u.ext2_sb.s_group_desc,
			 db_count * sizeof (struct buffer_head *));
		brelse (bh);
		printk ("EXT2-fs: get root inode failed\n");
		MOD_DEC_USE_COUNT;
		return NULL;
	}
	ext2_setup_super (sb, es);
	return sb;
}
Пример #13
0
struct super_block *minix_read_super(struct super_block *s,void *data, 
				     int silent)
{
	struct buffer_head *bh;
	struct minix_super_block *ms;
	int i,dev=s->s_dev,block;

	if (32 != sizeof (struct minix_inode))
		panic("bad i-node size");
	lock_super(s);
	if (!(bh = bread(dev,1,BLOCK_SIZE))) {
		s->s_dev=0;
		unlock_super(s);
		printk("MINIX-fs: unable to read superblock\n");
		return NULL;
	}
	ms = (struct minix_super_block *) bh->b_data;
	s->u.minix_sb.s_ms = ms;
	s->u.minix_sb.s_sbh = bh;
	s->u.minix_sb.s_mount_state = ms->s_state;
	s->s_blocksize = 1024;
	s->s_blocksize_bits = 10;
	s->u.minix_sb.s_ninodes = ms->s_ninodes;
	s->u.minix_sb.s_nzones = ms->s_nzones;
	s->u.minix_sb.s_imap_blocks = ms->s_imap_blocks;
	s->u.minix_sb.s_zmap_blocks = ms->s_zmap_blocks;
	s->u.minix_sb.s_firstdatazone = ms->s_firstdatazone;
	s->u.minix_sb.s_log_zone_size = ms->s_log_zone_size;
	s->u.minix_sb.s_max_size = ms->s_max_size;
	s->s_magic = ms->s_magic;
	if (s->s_magic == MINIX_SUPER_MAGIC) {
		s->u.minix_sb.s_dirsize = 16;
		s->u.minix_sb.s_namelen = 14;
	} else if (s->s_magic == MINIX_SUPER_MAGIC2) {
		s->u.minix_sb.s_dirsize = 32;
		s->u.minix_sb.s_namelen = 30;
	} else {
		s->s_dev = 0;
		unlock_super(s);
		brelse(bh);
		if (!silent)
			printk("VFS: Can't find a minix filesystem on dev 0x%04x.\n", dev);
		return NULL;
	}
	for (i=0;i < MINIX_I_MAP_SLOTS;i++)
		s->u.minix_sb.s_imap[i] = NULL;
	for (i=0;i < MINIX_Z_MAP_SLOTS;i++)
		s->u.minix_sb.s_zmap[i] = NULL;
	block=2;
	for (i=0 ; i < s->u.minix_sb.s_imap_blocks ; i++)
		if ((s->u.minix_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE)) != NULL)
			block++;
		else
			break;
	for (i=0 ; i < s->u.minix_sb.s_zmap_blocks ; i++)
		if ((s->u.minix_sb.s_zmap[i]=bread(dev,block,BLOCK_SIZE)) != NULL)
			block++;
		else
			break;
	if (block != 2+s->u.minix_sb.s_imap_blocks+s->u.minix_sb.s_zmap_blocks) {
		for(i=0;i<MINIX_I_MAP_SLOTS;i++)
			brelse(s->u.minix_sb.s_imap[i]);
		for(i=0;i<MINIX_Z_MAP_SLOTS;i++)
			brelse(s->u.minix_sb.s_zmap[i]);
		s->s_dev=0;
		unlock_super(s);
		brelse(bh);
		printk("MINIX-fs: bad superblock or unable to read bitmaps\n");
		return NULL;
	}
	set_bit(0,s->u.minix_sb.s_imap[0]->b_data);
	set_bit(0,s->u.minix_sb.s_zmap[0]->b_data);
	unlock_super(s);
	/* set up enough so that it can read an inode */
	s->s_dev = dev;
	s->s_op = &minix_sops;
	s->s_mounted = iget(s,MINIX_ROOT_INO);
	if (!s->s_mounted) {
		s->s_dev = 0;
		brelse(bh);
		printk("MINIX-fs: get root inode failed\n");
		return NULL;
	}
	if (!(s->s_flags & MS_RDONLY)) {
		ms->s_state &= ~MINIX_VALID_FS;
		mark_buffer_dirty(bh, 1);
		s->s_dirt = 1;
	}
	if (!(s->u.minix_sb.s_mount_state & MINIX_VALID_FS))
		printk ("MINIX-fs: mounting unchecked file system, "
			"running fsck is recommended.\n");
 	else if (s->u.minix_sb.s_mount_state & MINIX_ERROR_FS)
		printk ("MINIX-fs: mounting file system with errors, "
			"running fsck is recommended.\n");
	return s;
}
Пример #14
0
struct super_block *isofs_read_super(struct super_block *s,void *data,
				     int silent)
{
	struct buffer_head *bh;
	int iso_blknum;
	unsigned int blocksize_bits;
	int high_sierra;
	int dev=s->s_dev;
	struct iso_volume_descriptor *vdp;
	struct hs_volume_descriptor *hdp;

	struct iso_primary_descriptor *pri = NULL;
	struct hs_primary_descriptor *h_pri = NULL;

	struct iso_directory_record *rootp;

	struct iso9660_options opt;

	if (!parse_options((char *) data,&opt)) {
		s->s_dev = 0;
		return NULL;
	}

#if 0
	printk("map = %c\n", opt.map);
	printk("rock = %c\n", opt.rock);
	printk("cruft = %c\n", opt.cruft);
	printk("conversion = %c\n", opt.conversion);
	printk("blocksize = %d\n", opt.blocksize);
	printk("gid = %d\n", opt.gid);
	printk("uid = %d\n", opt.uid);
#endif
	
	blocksize_bits = 0;
	{
	  int i = opt.blocksize;
	  while (i != 1){
	    blocksize_bits++;
	    i >>=1;
	  };
	};
	set_blocksize(dev, opt.blocksize);

	lock_super(s);

	s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */

	for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
		if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits), opt.blocksize))) {
			s->s_dev=0;
			printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n",
			       dev, iso_blknum);
			unlock_super(s);
			return NULL;
		}

		vdp = (struct iso_volume_descriptor *)bh->b_data;
		hdp = (struct hs_volume_descriptor *)bh->b_data;

		
		if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
		  if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
			goto out;
		  if (isonum_711 (hdp->type) == ISO_VD_END)
		        goto out;
		
		        s->u.isofs_sb.s_high_sierra = 1;
			high_sierra = 1;
		        opt.rock = 'n';
		        h_pri = (struct hs_primary_descriptor *)vdp;
			break;
		};
		
		if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
		  if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
			goto out;
		  if (isonum_711 (vdp->type) == ISO_VD_END)
			goto out;
		
		        pri = (struct iso_primary_descriptor *)vdp;
			break;
	        };

		brelse(bh);
	      }
	if(iso_blknum == 100) {
		if (!silent)
			printk("Unable to identify CD-ROM format.\n");
		s->s_dev = 0;
		unlock_super(s);
		return NULL;
	};
	
	
	if(high_sierra){
	  rootp = (struct iso_directory_record *) h_pri->root_directory_record;
	  if (isonum_723 (h_pri->volume_set_size) != 1) {
	    printk("Multi-volume disks not (yet) supported.\n");
	    goto out;
	  };
	  s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
	  s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
	  s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
	} else {
	  rootp = (struct iso_directory_record *) pri->root_directory_record;
	  if (isonum_723 (pri->volume_set_size) != 1) {
	    printk("Multi-volume disks not (yet) supported.\n");
	    goto out;
	  };
	  s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
	  s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
	  s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
	}
	
	s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */
	
	s->u.isofs_sb.s_firstdatazone = isonum_733( rootp->extent) << 
		(ISOFS_BLOCK_BITS - blocksize_bits);
	s->s_magic = ISOFS_SUPER_MAGIC;
	
	/* The CDROM is read-only, has no nodes (devices) on it, and since
	   all of the files appear to be owned by root, we really do not want
	   to allow suid.  (suid or devices will not show up unless we have
	   Rock Ridge extensions) */
	
	s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
	
	if(s->u.isofs_sb.s_log_zone_size != (1 << ISOFS_BLOCK_BITS)) {
		printk("1 <<Block bits != Block size\n");
		goto out;
	};
	
	brelse(bh);
	
	printk("Max size:%ld   Log zone size:%ld\n",
	       s->u.isofs_sb.s_max_size, 
	       s->u.isofs_sb.s_log_zone_size);
	printk("First datazone:%ld   Root inode number %d\n",
	       s->u.isofs_sb.s_firstdatazone,
	       isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
	if(high_sierra) printk("Disc in High Sierra format.\n");
	unlock_super(s);
	/* set up enough so that it can read an inode */
	
	s->s_dev = dev;
	s->s_op = &isofs_sops;
	s->u.isofs_sb.s_mapping = opt.map;
	s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 1 : 0);
	s->u.isofs_sb.s_conversion = opt.conversion;
	s->u.isofs_sb.s_cruft = opt.cruft;
	s->u.isofs_sb.s_uid = opt.uid;
	s->u.isofs_sb.s_gid = opt.gid;
	s->s_blocksize = opt.blocksize;
	s->s_blocksize_bits = blocksize_bits;
	s->s_mounted = iget(s, isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
	unlock_super(s);

	if (!(s->s_mounted)) {
		s->s_dev=0;
		printk("get root inode failed\n");
		return NULL;
	}

	if(!check_disk_change(s->s_dev)) return s;
 out: /* Kick out for various error conditions */
	brelse(bh);
	s->s_dev = 0;
	unlock_super(s);
	return NULL;
}
Пример #15
0
void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
{
    struct super_block * sb;
    struct ufs_sb_private_info * uspi;
    struct ufs_super_block_first * usb1;
    struct ufs_cg_private_info * ucpi;
    struct ufs_cylinder_group * ucg;
    unsigned overflow, cgno, bit, end_bit, i;
    u64 blkno;

    sb = inode->i_sb;
    uspi = UFS_SB(sb)->s_uspi;
    usb1 = ubh_get_usb_first(uspi);

    UFSD("ENTER, fragment %llu, count %u\n",
         (unsigned long long)fragment, count);

    if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {
        ufs_error (sb, "ufs_free_blocks", "internal error, "
                   "fragment %llu, count %u\n",
                   (unsigned long long)fragment, count);
        goto failed;
    }

    lock_super(sb);

do_more:
    overflow = 0;
    cgno = ufs_dtog(uspi, fragment);
    bit = ufs_dtogd(uspi, fragment);
    if (cgno >= uspi->s_ncg) {
        ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device");
        goto failed_unlock;
    }
    end_bit = bit + count;
    if (end_bit > uspi->s_fpg) {
        overflow = bit + count - uspi->s_fpg;
        count -= overflow;
        end_bit -= overflow;
    }

    ucpi = ufs_load_cylinder (sb, cgno);
    if (!ucpi)
        goto failed_unlock;
    ucg = ubh_get_ucg (UCPI_UBH(ucpi));
    if (!ufs_cg_chkmagic(sb, ucg)) {
        ufs_panic (sb, "ufs_free_blocks", "internal error, bad magic number on cg %u", cgno);
        goto failed_unlock;
    }

    for (i = bit; i < end_bit; i += uspi->s_fpb) {
        blkno = ufs_fragstoblks(i);
        if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
            ufs_error(sb, "ufs_free_blocks", "freeing free fragment");
        }
        ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
        if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
            ufs_clusteracct (sb, ucpi, blkno, 1);

        fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
        uspi->cs_total.cs_nbfree++;
        fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);

        if (uspi->fs_magic != UFS2_MAGIC) {
            unsigned cylno = ufs_cbtocylno(i);

            fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
                                      ufs_cbtorpos(i)), 1);
            fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
        }
    }

    ubh_mark_buffer_dirty (USPI_UBH(uspi));
    ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
    if (sb->s_flags & MS_SYNCHRONOUS) {
        ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
        ubh_wait_on_buffer (UCPI_UBH(ucpi));
    }

    if (overflow) {
        fragment += count;
        count = overflow;
        goto do_more;
    }

    sb->s_dirt = 1;
    unlock_super (sb);
    UFSD("EXIT\n");
    return;

failed_unlock:
    unlock_super (sb);
failed:
    UFSD("EXIT (FAILED)\n");
    return;
}
Пример #16
0
/*
 * There are two policies for allocating an inode.  If the new inode is
 * a directory, then a forward search is made for a block group with both
 * free space and a low directory-to-inode ratio; if that fails, then of
 * the groups with above-average free space, that group with the fewest
 * directories already is chosen.
 *
 * For other inodes, search forward from the parent directory\'s block
 * group to find a free inode.
 */
struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err)
{
	struct super_block * sb;
	struct buffer_head * bh;
	struct buffer_head * bh2;
	int i, j, avefreei;
	struct inode * inode;
	int bitmap_nr;
	struct ext2_group_desc * gdp;
	struct ext2_group_desc * tmp;
	struct ext2_super_block * es;

	/* Cannot create files in a deleted directory */
	if (!dir || !dir->i_nlink) {
		*err = -EPERM;
		return NULL;
	}

	inode = get_empty_inode ();
	if (!inode) {
		*err = -ENOMEM;
		return NULL;
	}

	sb = dir->i_sb;
	inode->i_sb = sb;
	inode->i_flags = 0;
	lock_super (sb);
	es = sb->u.ext2_sb.s_es;
repeat:
	gdp = NULL; i=0;
	
	*err = -ENOSPC;
	if (S_ISDIR(mode)) {
		avefreei = le32_to_cpu(es->s_free_inodes_count) /
			sb->u.ext2_sb.s_groups_count;
/* I am not yet convinced that this next bit is necessary.
		i = dir->u.ext2_i.i_block_group;
		for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
			tmp = ext2_get_group_desc (sb, i, &bh2);
			if (tmp &&
			    (le16_to_cpu(tmp->bg_used_dirs_count) << 8) < 
			     le16_to_cpu(tmp->bg_free_inodes_count)) {
				gdp = tmp;
				break;
			}
			else
			i = ++i % sb->u.ext2_sb.s_groups_count;
		}
*/
		if (!gdp) {
			for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
				tmp = ext2_get_group_desc (sb, j, &bh2);
				if (tmp &&
				    le16_to_cpu(tmp->bg_free_inodes_count) &&
				    le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) {
					if (!gdp || 
					    (le16_to_cpu(tmp->bg_free_blocks_count) >
					     le16_to_cpu(gdp->bg_free_blocks_count))) {
						i = j;
						gdp = tmp;
					}
				}
			}
		}
	}
	else 
	{
		/*
		 * Try to place the inode in its parent directory
		 */
		i = dir->u.ext2_i.i_block_group;
		tmp = ext2_get_group_desc (sb, i, &bh2);
		if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
			gdp = tmp;
		else
		{
			/*
			 * Use a quadratic hash to find a group with a
			 * free inode
			 */
			for (j = 1; j < sb->u.ext2_sb.s_groups_count; j <<= 1) {
				i += j;
				if (i >= sb->u.ext2_sb.s_groups_count)
					i -= sb->u.ext2_sb.s_groups_count;
				tmp = ext2_get_group_desc (sb, i, &bh2);
				if (tmp &&
				    le16_to_cpu(tmp->bg_free_inodes_count)) {
					gdp = tmp;
					break;
				}
			}
		}
		if (!gdp) {
			/*
			 * That failed: try linear search for a free inode
			 */
			i = dir->u.ext2_i.i_block_group + 1;
			for (j = 2; j < sb->u.ext2_sb.s_groups_count; j++) {
				if (++i >= sb->u.ext2_sb.s_groups_count)
					i = 0;
				tmp = ext2_get_group_desc (sb, i, &bh2);
				if (tmp &&
				    le16_to_cpu(tmp->bg_free_inodes_count)) {
					gdp = tmp;
					break;
				}
			}
		}
	}

	if (!gdp) {
		unlock_super (sb);
		iput(inode);
		return NULL;
	}
	bitmap_nr = load_inode_bitmap (sb, i);
	if (bitmap_nr < 0) {
		unlock_super (sb);
		iput(inode);
		*err = -EIO;
		return NULL;
	}

	bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
	if ((j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
				      EXT2_INODES_PER_GROUP(sb))) <
	    EXT2_INODES_PER_GROUP(sb)) {
		if (ext2_set_bit (j, bh->b_data)) {
			ext2_warning (sb, "ext2_new_inode",
				      "bit already set for inode %d", j);
			goto repeat;
		}
		mark_buffer_dirty(bh, 1);
		if (sb->s_flags & MS_SYNCHRONOUS) {
			ll_rw_block (WRITE, 1, &bh);
			wait_on_buffer (bh);
		}
	} else {
		if (le16_to_cpu(gdp->bg_free_inodes_count) != 0) {
			ext2_error (sb, "ext2_new_inode",
				    "Free inodes count corrupted in group %d",
				    i);
			unlock_super (sb);
			iput (inode);
			return NULL;
		}
		goto repeat;
	}
	j += i * EXT2_INODES_PER_GROUP(sb) + 1;
	if (j < EXT2_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) {
		ext2_error (sb, "ext2_new_inode",
			    "reserved inode or inode > inodes count - "
			    "block_group = %d,inode=%d", i, j);
		unlock_super (sb);
		iput (inode);
		return NULL;
	}
	gdp->bg_free_inodes_count =
		cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
	if (S_ISDIR(mode))
		gdp->bg_used_dirs_count =
			cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
	mark_buffer_dirty(bh2, 1);
	es->s_free_inodes_count =
		cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1);
	mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
	sb->s_dirt = 1;
	inode->i_mode = mode;
	inode->i_sb = sb;
	inode->i_nlink = 1;
	inode->i_dev = sb->s_dev;
	inode->i_uid = current->fsuid;
	if (test_opt (sb, GRPID))
		inode->i_gid = dir->i_gid;
	else if (dir->i_mode & S_ISGID) {
		inode->i_gid = dir->i_gid;
		if (S_ISDIR(mode))
			mode |= S_ISGID;
	} else
		inode->i_gid = current->fsgid;

	inode->i_ino = j;
	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size (for stat), not the fs block size */
	inode->i_blocks = 0;
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
	inode->u.ext2_i.i_new_inode = 1;
	inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags;
	if (S_ISLNK(mode))
		inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL | EXT2_APPEND_FL);
	inode->u.ext2_i.i_faddr = 0;
	inode->u.ext2_i.i_frag_no = 0;
	inode->u.ext2_i.i_frag_size = 0;
	inode->u.ext2_i.i_file_acl = 0;
	inode->u.ext2_i.i_dir_acl = 0;
	inode->u.ext2_i.i_dtime = 0;
	inode->u.ext2_i.i_block_group = i;
	inode->i_op = NULL;
	if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
		inode->i_flags |= MS_SYNCHRONOUS;
	insert_inode_hash(inode);
	mark_inode_dirty(inode);
	inc_inode_version (inode, gdp, mode);

	unlock_super (sb);
	if(DQUOT_ALLOC_INODE(sb, inode)) {
		sb->dq_op->drop(inode);
		inode->i_nlink = 0;
		iput(inode);
		*err = -EDQUOT;
		return NULL;
	}
	ext2_debug ("allocating inode %lu\n", inode->i_ino);

	*err = 0;
	return inode;
}
Пример #17
0
void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
{
    struct super_block * sb;
    struct ufs_sb_private_info * uspi;
    struct ufs_super_block_first * usb1;
    struct ufs_cg_private_info * ucpi;
    struct ufs_cylinder_group * ucg;
    unsigned cgno, bit, end_bit, bbase, blkmap, i;
    u64 blkno;

    sb = inode->i_sb;
    uspi = UFS_SB(sb)->s_uspi;
    usb1 = ubh_get_usb_first(uspi);

    UFSD("ENTER, fragment %llu, count %u\n",
         (unsigned long long)fragment, count);

    if (ufs_fragnum(fragment) + count > uspi->s_fpg)
        ufs_error (sb, "ufs_free_fragments", "internal error");

    lock_super(sb);

    cgno = ufs_dtog(uspi, fragment);
    bit = ufs_dtogd(uspi, fragment);
    if (cgno >= uspi->s_ncg) {
        ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device");
        goto failed;
    }

    ucpi = ufs_load_cylinder (sb, cgno);
    if (!ucpi)
        goto failed;
    ucg = ubh_get_ucg (UCPI_UBH(ucpi));
    if (!ufs_cg_chkmagic(sb, ucg)) {
        ufs_panic (sb, "ufs_free_fragments", "internal error, bad magic number on cg %u", cgno);
        goto failed;
    }

    end_bit = bit + count;
    bbase = ufs_blknum (bit);
    blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
    ufs_fragacct (sb, blkmap, ucg->cg_frsum, -1);
    for (i = bit; i < end_bit; i++) {
        if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, i))
            ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, i);
        else
            ufs_error (sb, "ufs_free_fragments",
                       "bit already cleared for fragment %u", i);
    }

    fs32_add(sb, &ucg->cg_cs.cs_nffree, count);
    uspi->cs_total.cs_nffree += count;
    fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
    blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
    ufs_fragacct(sb, blkmap, ucg->cg_frsum, 1);

    /*
     * Trying to reassemble free fragments into block
     */
    blkno = ufs_fragstoblks (bbase);
    if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
        fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb);
        uspi->cs_total.cs_nffree -= uspi->s_fpb;
        fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb);
        if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
            ufs_clusteracct (sb, ucpi, blkno, 1);
        fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
        uspi->cs_total.cs_nbfree++;
        fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
        if (uspi->fs_magic != UFS2_MAGIC) {
            unsigned cylno = ufs_cbtocylno (bbase);

            fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
                                      ufs_cbtorpos(bbase)), 1);
            fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
        }
    }

    ubh_mark_buffer_dirty (USPI_UBH(uspi));
    ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
    if (sb->s_flags & MS_SYNCHRONOUS) {
        ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
        ubh_wait_on_buffer (UCPI_UBH(ucpi));
    }
    sb->s_dirt = 1;

    unlock_super (sb);
    UFSD("EXIT\n");
    return;

failed:
    unlock_super (sb);
    UFSD("EXIT (FAILED)\n");
    return;
}
Пример #18
0
/*
 * NOTE! When we get the inode, we're the only people
 * that have access to it, and as such there are no
 * race conditions we have to worry about. The inode
 * is not on the hash-lists, and it cannot be reached
 * through the filesystem because the directory entry
 * has been deleted earlier.
 *
 * HOWEVER: we must make sure that we get no aliases,
 * which means that we have to call "clear_inode()"
 * _before_ we mark the inode not in use in the inode
 * bitmaps. Otherwise a newly created file might use
 * the same inode number (not actually the same pointer
 * though), and then we'd have two inodes sharing the
 * same inode number and space on the harddisk.
 */
void ext2_free_inode (struct inode * inode)
{
	struct super_block * sb = inode->i_sb;
	int is_directory;
	unsigned long ino;
	struct buffer_head * bh;
	struct buffer_head * bh2;
	unsigned long block_group;
	unsigned long bit;
	struct ext2_group_desc * desc;
	struct ext2_super_block * es;

	ino = inode->i_ino;
	ext2_debug ("freeing inode %lu\n", ino);

	/*
	 * Note: we must free any quota before locking the superblock,
	 * as writing the quota to disk may need the lock as well.
	 */
	if (!is_bad_inode(inode)) {
		/* Quota is already initialized in iput() */
	    	DQUOT_FREE_INODE(inode);
		DQUOT_DROP(inode);
	}

	lock_super (sb);
	es = sb->u.ext2_sb.s_es;
	is_directory = S_ISDIR(inode->i_mode);

	/* Do this BEFORE marking the inode not in use or returning an error */
	clear_inode (inode);

	if (ino < EXT2_FIRST_INO(sb) ||
	    ino > le32_to_cpu(es->s_inodes_count)) {
		ext2_error (sb, "ext2_free_inode",
			    "reserved or nonexistent inode %lu", ino);
		goto error_return;
	}
	block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb);
	bit = (ino - 1) % EXT2_INODES_PER_GROUP(sb);
	bh = load_inode_bitmap (sb, block_group);
	if (IS_ERR(bh))
		goto error_return;

	/* Ok, now we can actually update the inode bitmaps.. */
	if (!ext2_clear_bit (bit, bh->b_data))
		ext2_error (sb, "ext2_free_inode",
			      "bit already cleared for inode %lu", ino);
	else {
		desc = ext2_get_group_desc (sb, block_group, &bh2);
		if (desc) {
			desc->bg_free_inodes_count =
				cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) + 1);
			if (is_directory)
				desc->bg_used_dirs_count =
					cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) - 1);
		}
		mark_buffer_dirty(bh2);
		es->s_free_inodes_count =
			cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
		mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
	}
	mark_buffer_dirty(bh);
	if (sb->s_flags & MS_SYNCHRONOUS) {
		ll_rw_block (WRITE, 1, &bh);
		wait_on_buffer (bh);
	}
	sb->s_dirt = 1;
error_return:
	unlock_super (sb);
}
Пример #19
0
struct super_block *
ncp_read_super(struct super_block *sb, void *raw_data, int silent)
{
	struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
        struct ncp_server *server;
	struct file *ncp_filp;
	struct file *wdog_filp;
	struct file *msg_filp;
	kdev_t dev = sb->s_dev;
	int error;

	if (data == NULL)
	{
		printk("ncp_read_super: missing data argument\n");
		sb->s_dev = 0;
		return NULL;
	}

	if (data->version != NCP_MOUNT_VERSION)
	{
		printk("ncp warning: mount version %s than kernel\n",
		       (data->version < NCP_MOUNT_VERSION) ?
                       "older" : "newer");
		sb->s_dev = 0;
		return NULL;
	}

	if (   (data->ncp_fd >= NR_OPEN)
	    || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
	    || (!S_ISSOCK(ncp_filp->f_inode->i_mode)))
	{
		printk("ncp_read_super: invalid ncp socket\n");
		sb->s_dev = 0;
		return NULL;
	}

	if (   (data->wdog_fd >= NR_OPEN)
	    || ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
	    || (!S_ISSOCK(wdog_filp->f_inode->i_mode)))
	{
		printk("ncp_read_super: invalid wdog socket\n");
		sb->s_dev = 0;
		return NULL;
	}

	if (   (data->message_fd >= NR_OPEN)
	    || ((msg_filp = current->files->fd[data->message_fd]) == NULL)
	    || (!S_ISSOCK(msg_filp->f_inode->i_mode)))
	{
		printk("ncp_read_super: invalid wdog socket\n");
		sb->s_dev = 0;
		return NULL;
	}

        /* We must malloc our own super-block info */
        server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
                                                   GFP_KERNEL);

        if (server == NULL)
	{
                printk("ncp_read_super: could not alloc ncp_server\n");
                return NULL;
        }

	ncp_filp->f_count += 1;
	wdog_filp->f_count += 1;
	msg_filp->f_count += 1;

	lock_super(sb);

        NCP_SBP(sb) = server;
        
	sb->s_blocksize = 1024; /* Eh...  Is this correct? */
	sb->s_blocksize_bits = 10;
	sb->s_magic = NCP_SUPER_MAGIC;
	sb->s_dev = dev;
	sb->s_op = &ncp_sops;

	server->ncp_filp    = ncp_filp;
	server->wdog_filp   = wdog_filp;
	server->msg_filp    = msg_filp;
	server->lock        = 0;
	server->wait        = NULL;
        server->packet      = NULL;
	server->buffer_size = 0;
	server->conn_status = 0;

        server->m = *data;
	server->m.file_mode = (server->m.file_mode &
			       (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
	server->m.dir_mode  = (server->m.dir_mode &
			       (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;

	/* protect against invalid mount points */
	server->m.mount_point[sizeof(server->m.mount_point)-1] = '\0';

	server->packet_size = NCP_PACKET_SIZE;
	server->packet      = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);

	if (server->packet == NULL)
	{
		printk("ncpfs: could not alloc packet\n");
		error = -ENOMEM;
		unlock_super(sb);
		goto fail;
	}
   
        /*
         * Make the connection to the server
         */

	if (ncp_catch_watchdog(server) != 0)
	{
		printk("ncp_read_super: Could not catch watchdog\n");
		error = -EINVAL;
		unlock_super(sb);
		goto fail;
	}

	if (ncp_catch_message(server) != 0)
	{
		printk("ncp_read_super: Could not catch messages\n");
		ncp_dont_catch_watchdog(server);
		error = -EINVAL;
		unlock_super(sb);
		goto fail;
	}

	ncp_lock_server(server);
	error = ncp_connect(server);
	ncp_unlock_server(server);
	unlock_super(sb);

	if (error < 0)
	{
		sb->s_dev = 0;
		printk("ncp_read_super: Failed connection, bailing out "
                       "(error = %d).\n", -error);
                ncp_kfree_s(server->packet, server->packet_size);
		ncp_dont_catch_watchdog(server);
                goto fail;
	}

        DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));

	ncp_init_root(server);

	if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, &(server->root)))))
	{
		sb->s_dev = 0;
		printk("ncp_read_super: get root inode failed\n");
                goto disconnect;
	}

	if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
				     &(server->buffer_size)) != 0)
	{
		sb->s_dev = 0;
		printk("ncp_read_super: could not get bufsize\n");
		goto disconnect;
	}

	DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);

        MOD_INC_USE_COUNT;
	return sb;

 disconnect:
	ncp_lock_server(server);
	ncp_disconnect(server);
	ncp_unlock_server(server);
	ncp_kfree_s(server->packet, server->packet_size);
	ncp_dont_catch_watchdog(server);
 fail:
	ncp_filp->f_count -= 1;
	wdog_filp->f_count -= 1;
	msg_filp->f_count -= 1;
        ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
        return NULL;
}
Пример #20
0
struct inode * ext2_new_inode (const struct inode * dir, int mode)
{
	struct super_block * sb;
	struct buffer_head * bh;
	struct buffer_head * bh2;
	int group, i;
	ino_t ino;
	struct inode * inode;
	struct ext2_group_desc * desc;
	struct ext2_super_block * es;
	int err;

	sb = dir->i_sb;
	inode = new_inode(sb);
	if (!inode)
		return ERR_PTR(-ENOMEM);

	lock_super (sb);
	es = sb->u.ext2_sb.s_es;
repeat:
	if (S_ISDIR(mode))
		group = find_group_dir(sb, dir->u.ext2_i.i_block_group);
	else 
		group = find_group_other(sb, dir->u.ext2_i.i_block_group);

	err = -ENOSPC;
	if (group == -1)
		goto fail;

	err = -EIO;
	bh = load_inode_bitmap (sb, group);
	if (IS_ERR(bh))
		goto fail2;

	i = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
				      EXT2_INODES_PER_GROUP(sb));
	if (i >= EXT2_INODES_PER_GROUP(sb))
		goto bad_count;
	ext2_set_bit (i, bh->b_data);

	mark_buffer_dirty(bh);
	if (sb->s_flags & MS_SYNCHRONOUS) {
		ll_rw_block (WRITE, 1, &bh);
		wait_on_buffer (bh);
	}

	ino = group * EXT2_INODES_PER_GROUP(sb) + i + 1;
	if (ino < EXT2_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
		ext2_error (sb, "ext2_new_inode",
			    "reserved inode or inode > inodes count - "
			    "block_group = %d,inode=%ld", group,
			    (unsigned long) ino);
		err = -EIO;
		goto fail2;
	}

	es->s_free_inodes_count =
		cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1);
	mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
	sb->s_dirt = 1;
	inode->i_uid = current->fsuid;
	if (test_opt (sb, GRPID))
		inode->i_gid = dir->i_gid;
	else if (dir->i_mode & S_ISGID) {
		inode->i_gid = dir->i_gid;
		if (S_ISDIR(mode))
			mode |= S_ISGID;
	} else
		inode->i_gid = current->fsgid;
	inode->i_mode = mode;

	inode->i_ino = ino;
	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size (for stat), not the fs block size */
	inode->i_blocks = 0;
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
	inode->u.ext2_i.i_new_inode = 1;
	inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags;
	if (S_ISLNK(mode))
		inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL|EXT2_APPEND_FL);
	inode->u.ext2_i.i_block_group = group;
	if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
		inode->i_flags |= S_SYNC;
	insert_inode_hash(inode);
	inode->i_generation = event++;
	mark_inode_dirty(inode);

	unlock_super (sb);
	if(DQUOT_ALLOC_INODE(inode)) {
		DQUOT_DROP(inode);
		inode->i_flags |= S_NOQUOTA;
		inode->i_nlink = 0;
		iput(inode);
		return ERR_PTR(-EDQUOT);
	}
	ext2_debug ("allocating inode %lu\n", inode->i_ino);
	return inode;

fail2:
	desc = ext2_get_group_desc (sb, group, &bh2);
	desc->bg_free_inodes_count =
		cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) + 1);
	if (S_ISDIR(mode))
		desc->bg_used_dirs_count =
			cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) - 1);
	mark_buffer_dirty(bh2);
fail:
	unlock_super(sb);
	make_bad_inode(inode);
	iput(inode);
	return ERR_PTR(err);

bad_count:
	ext2_error (sb, "ext2_new_inode",
		    "Free inodes count corrupted in group %d",
		    group);
	/* Is it really ENOSPC? */
	err = -ENOSPC;
	if (sb->s_flags & MS_RDONLY)
		goto fail;

	desc = ext2_get_group_desc (sb, group, &bh2);
	desc->bg_free_inodes_count = 0;
	mark_buffer_dirty(bh2);
	goto repeat;
}
Пример #21
0
/*
 * The way this works is that the mount process passes a structure
 * in the data argument which contains the server's IP address
 * and the root file handle obtained from the server's mount
 * daemon. We stash these away in the private superblock fields.
 */
struct super_block *
nfs_read_super(struct super_block *sb, void *raw_data, int silent)
{
    struct nfs_mount_data	*data = (struct nfs_mount_data *) raw_data;
    struct nfs_server	*server;
    struct rpc_xprt		*xprt;
    struct rpc_clnt		*clnt;
    struct nfs_fh		*root_fh;
    struct inode		*root_inode;
    unsigned int		authflavor;
    int			tcp;
    struct sockaddr_in	srvaddr;
    struct rpc_timeout	timeparms;
    struct nfs_fattr	fattr;

    MOD_INC_USE_COUNT;
    if (!data)
        goto out_miss_args;

    /* No NFS V3. */
    if (data->flags & NFS_MOUNT_VER3)
        goto out_fail;

    /* Don't complain if "mount" is newer. */
    if (data->version < NFS_MOUNT_VERSION) {
        printk("nfs warning: mount version %s than kernel\n",
               data->version < NFS_MOUNT_VERSION ? "older" : "newer");
        if (data->version < 2)
            data->namlen = 0;
        if (data->version < 3)
            data->bsize  = 0;
    }

    /* We now require that the mount process passes the remote address */
    memcpy(&srvaddr, &data->addr, sizeof(srvaddr));
    if (srvaddr.sin_addr.s_addr == INADDR_ANY)
        goto out_no_remote;

    lock_super(sb);

    sb->s_flags |= MS_ODD_RENAME; /* This should go away */

    sb->s_magic      = NFS_SUPER_MAGIC;
    sb->s_op         = &nfs_sops;
    sb->s_blocksize  = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
    sb->u.nfs_sb.s_root = data->root;
    server           = &sb->u.nfs_sb.s_server;
    server->rsize    = nfs_block_size(data->rsize, NULL);
    server->wsize    = nfs_block_size(data->wsize, NULL);
    server->flags    = data->flags;

    if (data->flags & NFS_MOUNT_NOAC) {
        data->acregmin = data->acregmax = 0;
        data->acdirmin = data->acdirmax = 0;
    }
    server->acregmin = data->acregmin*HZ;
    server->acregmax = data->acregmax*HZ;
    server->acdirmin = data->acdirmin*HZ;
    server->acdirmax = data->acdirmax*HZ;

    server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL);
    if (!server->hostname)
        goto out_unlock;
    strcpy(server->hostname, data->hostname);

    /* Which protocol do we use? */
    tcp   = (data->flags & NFS_MOUNT_TCP);

    /* Initialize timeout values */
    timeparms.to_initval = data->timeo * HZ / 10;
    timeparms.to_retries = data->retrans;
    timeparms.to_maxval  = tcp? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT;
    timeparms.to_exponential = 1;

    /* Now create transport and client */
    xprt = xprt_create_proto(tcp? IPPROTO_TCP : IPPROTO_UDP,
                             &srvaddr, &timeparms);
    if (xprt == NULL)
        goto out_no_xprt;

    /* Choose authentication flavor */
    authflavor = RPC_AUTH_UNIX;
    if (data->flags & NFS_MOUNT_SECURE)
        authflavor = RPC_AUTH_DES;
    else if (data->flags & NFS_MOUNT_KERBEROS)
        authflavor = RPC_AUTH_KRB;

    clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
                             NFS_VERSION, authflavor);
    if (clnt == NULL)
        goto out_no_client;

    clnt->cl_intr     = (data->flags & NFS_MOUNT_INTR)? 1 : 0;
    clnt->cl_softrtry = (data->flags & NFS_MOUNT_SOFT)? 1 : 0;
    clnt->cl_chatty   = 1;
    server->client    = clnt;

    /* Fire up rpciod if not yet running */
    if (rpciod_up() != 0)
        goto out_no_iod;

    /*
     * Keep the super block locked while we try to get
     * the root fh attributes.
     */
    root_fh = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL);
    if (!root_fh)
        goto out_no_fh;
    *root_fh = data->root;

    if (nfs_proc_getattr(server, root_fh, &fattr) != 0)
        goto out_no_fattr;

    clnt->cl_to_err = 1;

    root_inode = __nfs_fhget(sb, &fattr);
    if (!root_inode)
        goto out_no_root;
    sb->s_root = d_alloc_root(root_inode, NULL);
    if (!sb->s_root)
        goto out_no_root;
    sb->s_root->d_op = &nfs_dentry_operations;
    sb->s_root->d_fsdata = root_fh;

    /* We're airborne */
    unlock_super(sb);

    /* Check whether to start the lockd process */
    if (!(server->flags & NFS_MOUNT_NONLM))
        lockd_up();
    return sb;

    /* Yargs. It didn't work out. */
out_no_root:
    printk("nfs_read_super: get root inode failed\n");
    iput(root_inode);
    goto out_free_fh;

out_no_fattr:
    printk("nfs_read_super: get root fattr failed\n");
out_free_fh:
    kfree(root_fh);
out_no_fh:
    rpciod_down();
    goto out_shutdown;

out_no_iod:
    printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
out_shutdown:
    rpc_shutdown_client(server->client);
    goto out_free_host;

out_no_client:
    printk(KERN_WARNING "NFS: cannot create RPC client.\n");
    xprt_destroy(xprt);
    goto out_free_host;

out_no_xprt:
    printk(KERN_WARNING "NFS: cannot create RPC transport.\n");

out_free_host:
    kfree(server->hostname);
out_unlock:
    unlock_super(sb);
    goto out_fail;

out_no_remote:
    printk("NFS: mount program didn't pass remote address!\n");
    goto out_fail;

out_miss_args:
    printk("nfs_read_super: missing data argument\n");

out_fail:
    sb->s_dev = 0;
    MOD_DEC_USE_COUNT;
    return NULL;
}
Пример #22
0
struct super_block * ext2_read_super (struct super_block * sb, void * data,
				      int silent)
{
	struct buffer_head * bh;
	struct ext2_super_block * es;
	unsigned long sb_block = 1;
	unsigned long logic_sb_block = 1;
	int dev = sb->s_dev;
	int bh_count;
	int i, j;
#ifdef EXT2FS_PRE_02B_COMPAT
	int fs_converted = 0;
#endif

	set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
	if (!parse_options ((char *) data, &sb_block,
	    &sb->u.ext2_sb.s_mount_opt)) {
		sb->s_dev = 0;
		return NULL;
	}

	lock_super (sb);
	set_blocksize (dev, BLOCK_SIZE);
	if (!(bh = bread (dev, sb_block, BLOCK_SIZE))) {
		sb->s_dev = 0;
		unlock_super (sb);
		printk ("EXT2-fs: unable to read superblock\n");
		return NULL;
	}
	/*
	 * Note: s_es must be initialized s_es as soon as possible because
	 * some ext2 macro-instructions depend on its value
	 */
	es = (struct ext2_super_block *) bh->b_data;
	sb->u.ext2_sb.s_es = es;
	sb->s_magic = es->s_magic;
	if (sb->s_magic != EXT2_SUPER_MAGIC
#ifdef EXT2FS_PRE_02B_COMPAT
	   && sb->s_magic != EXT2_PRE_02B_MAGIC
#endif
	   ) {
		sb->s_dev = 0;
		unlock_super (sb);
		brelse (bh);
		if (!silent)
			printk ("VFS: Can't find an ext2 filesystem on dev %d/%d.\n",
				MAJOR(dev), MINOR(dev));
		return NULL;
	}
	sb->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size;
	sb->s_blocksize_bits = EXT2_BLOCK_SIZE_BITS(sb);
	if (sb->s_blocksize != BLOCK_SIZE && 
	    (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||  
	     sb->s_blocksize == 4096)) {
		unsigned long offset;

		brelse (bh);
		set_blocksize (dev, sb->s_blocksize);
		logic_sb_block = sb_block / sb->s_blocksize;
		offset = sb_block % sb->s_blocksize;
		bh = bread (dev, logic_sb_block, sb->s_blocksize);
		if(!bh)
			return NULL;
		es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
		sb->u.ext2_sb.s_es = es;
		if (es->s_magic != EXT2_SUPER_MAGIC) {
			sb->s_dev = 0;
			unlock_super (sb);
			brelse (bh);
			printk ("EXT2-fs: Magic mismatch, very weird !\n");
			return NULL;
		}
	}
	sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
				   es->s_log_frag_size;
	if (sb->u.ext2_sb.s_frag_size)
		sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize /
						  sb->u.ext2_sb.s_frag_size;
	else
		sb->s_magic = 0;
	sb->u.ext2_sb.s_blocks_per_group = es->s_blocks_per_group;
	sb->u.ext2_sb.s_frags_per_group = es->s_frags_per_group;
	sb->u.ext2_sb.s_inodes_per_group = es->s_inodes_per_group;
	sb->u.ext2_sb.s_inodes_per_block = sb->s_blocksize /
					   sizeof (struct ext2_inode);
	sb->u.ext2_sb.s_itb_per_group = sb->u.ext2_sb.s_inodes_per_group /
				        sb->u.ext2_sb.s_inodes_per_block;
	sb->u.ext2_sb.s_desc_per_block = sb->s_blocksize /
					 sizeof (struct ext2_group_desc);
	sb->u.ext2_sb.s_sbh = bh;
	sb->u.ext2_sb.s_es = es;
	sb->u.ext2_sb.s_mount_state = es->s_state;
	sb->u.ext2_sb.s_rename_lock = 0;
	sb->u.ext2_sb.s_rename_wait = NULL;
#ifdef EXT2FS_PRE_02B_COMPAT
	if (sb->s_magic == EXT2_PRE_02B_MAGIC) {
		if (es->s_blocks_count > 262144) {
			/*
			 * fs > 256 MB can't be converted
			 */ 
			sb->s_dev = 0;
			unlock_super (sb);
			brelse (bh);
			printk ("EXT2-fs: trying to mount a pre-0.2b file"
				"system which cannot be converted\n");
			return NULL;
		}
		printk ("EXT2-fs: mounting a pre 0.2b file system, "
			"will try to convert the structure\n");
		if (!(sb->s_flags & MS_RDONLY)) {
			sb->s_dev = 0;
			unlock_super (sb);
			brelse (bh);
			printk ("EXT2-fs: cannot convert a read-only fs\n");
			return NULL;
		}
		if (!convert_pre_02b_fs (sb, bh)) {
			sb->s_dev = 0;
			unlock_super (sb);
			brelse (bh);
			printk ("EXT2-fs: conversion failed !!!\n");
			return NULL;
		}
		printk ("EXT2-fs: conversion succeeded !!!\n");
		fs_converted = 1;
	}
#endif
	if (sb->s_magic != EXT2_SUPER_MAGIC) {
		sb->s_dev = 0;
		unlock_super (sb);
		brelse (bh);
		if (!silent)
			printk ("VFS: Can't find an ext2 filesystem on dev %d/%d.\n",
				MAJOR(dev), MINOR(dev));
		return NULL;
	}
	if (sb->s_blocksize != bh->b_size) {
		sb->s_dev = 0;
		unlock_super (sb);
		brelse (bh);
		if (!silent)
			printk ("VFS: Unsupported blocksize on dev 0x%04x.\n",
				dev);
		return NULL;
	}

	if (sb->s_blocksize != sb->u.ext2_sb.s_frag_size) {
		sb->s_dev = 0;
		unlock_super (sb);
		brelse (bh);
		printk ("EXT2-fs: fragsize %lu != blocksize %lu (not supported yet)\n",
			sb->u.ext2_sb.s_frag_size, sb->s_blocksize);
		return NULL;
	}

	sb->u.ext2_sb.s_groups_count = (es->s_blocks_count -
				        es->s_first_data_block +
				       EXT2_BLOCKS_PER_GROUP(sb) - 1) /
				       EXT2_BLOCKS_PER_GROUP(sb);
	for (i = 0; i < EXT2_MAX_GROUP_DESC; i++)
		sb->u.ext2_sb.s_group_desc[i] = NULL;
	bh_count = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
		   EXT2_DESC_PER_BLOCK(sb);
	if (bh_count > EXT2_MAX_GROUP_DESC) {
		sb->s_dev = 0;
		unlock_super (sb);
		brelse (bh);
		printk ("EXT2-fs: file system is too big\n");
		return NULL;
	}
	for (i = 0; i < bh_count; i++) {
		sb->u.ext2_sb.s_group_desc[i] = bread (dev, logic_sb_block + i + 1,
						       sb->s_blocksize);
		if (!sb->u.ext2_sb.s_group_desc[i]) {
			sb->s_dev = 0;
			unlock_super (sb);
			for (j = 0; j < i; j++)
				brelse (sb->u.ext2_sb.s_group_desc[j]);
			brelse (bh);
			printk ("EXT2-fs: unable to read group descriptors\n");
			return NULL;
		}
	}
	if (!ext2_check_descriptors (sb)) {
		sb->s_dev = 0;
		unlock_super (sb);
		for (j = 0; j < i; j++)
			brelse (sb->u.ext2_sb.s_group_desc[j]);
		brelse (bh);
		printk ("EXT2-fs: group descriptors corrupted !\n");
		return NULL;
	}
	for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
		sb->u.ext2_sb.s_inode_bitmap_number[i] = 0;
		sb->u.ext2_sb.s_inode_bitmap[i] = NULL;
		sb->u.ext2_sb.s_block_bitmap_number[i] = 0;
		sb->u.ext2_sb.s_block_bitmap[i] = NULL;
	}
	sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
	sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
	unlock_super (sb);
	/*
	 * set up enough so that it can read an inode
	 */
	sb->s_dev = dev;
	sb->s_op = &ext2_sops;
	if (!(sb->s_mounted = iget (sb, EXT2_ROOT_INO))) {
		sb->s_dev = 0;
		for (i = 0; i < EXT2_MAX_GROUP_DESC; i++)
			if (sb->u.ext2_sb.s_group_desc[i])
				brelse (sb->u.ext2_sb.s_group_desc[i]);
		brelse (bh);
		printk ("EXT2-fs: get root inode failed\n");
		return NULL;
	}
#ifdef EXT2FS_PRE_02B_COMPAT
	if (fs_converted) {
		for (i = 0; i < bh_count; i++)
			sb->u.ext2_sb.s_group_desc[i]->b_dirt = 1;
		sb->s_dirt = 1;
	}
#endif
	ext2_setup_super (sb, es);
	return sb;
}
Пример #23
0
/*
 * this functino has been reduced to the actual 'find the inode number' part
 */
ino_t
ext2_new_inode(const struct inode *dir, int mode)
{
	struct ext2_sb_info * sb;
	struct buffer_head * bh;
	struct buffer_head * bh2;
	int i, j, avefreei;
	int bitmap_nr;
	struct ext2_group_desc * gdp;
	struct ext2_group_desc * tmp;
	struct ext2_super_block * es;

	if (!dir)
		return 0;
	sb = dir->i_e2fs;

        lock_super (DEVVP(dir));
        es = sb->s_es;
repeat:
        gdp = NULL; i=0;

        if (S_ISDIR(mode)) {
		avefreei = es->s_free_inodes_count /
			sb->s_groups_count;
/* I am not yet convinced that this next bit is necessary.
		i = dir->u.ext2_i.i_block_group;
		for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
			tmp = get_group_desc (sb, i, &bh2);
			if ((tmp->bg_used_dirs_count << 8) <
			    tmp->bg_free_inodes_count) {
				gdp = tmp;
				break;
			}
			else
			i = ++i % sb->u.ext2_sb.s_groups_count;
		}
*/
		if (!gdp) {
			for (j = 0; j < sb->s_groups_count; j++) {
				tmp = get_group_desc(ITOV(dir)->v_mount,j,&bh2);
				if (tmp->bg_free_inodes_count &&
					tmp->bg_free_inodes_count >= avefreei) {
					if (!gdp ||
					    (tmp->bg_free_blocks_count >
					     gdp->bg_free_blocks_count)) {
						i = j;
						gdp = tmp;
					}
				}
			}
		}
	}
	else
	{
		/*
		 * Try to place the inode in its parent directory
		 */
		i = dir->i_block_group;
		tmp = get_group_desc (ITOV(dir)->v_mount, i, &bh2);
		if (tmp->bg_free_inodes_count)
			gdp = tmp;
		else
		{
			/*
			 * Use a quadratic hash to find a group with a
			 * free inode
			 */
			for (j = 1; j < sb->s_groups_count; j <<= 1) {
				i += j;
				if (i >= sb->s_groups_count)
					i -= sb->s_groups_count;
				tmp = get_group_desc(ITOV(dir)->v_mount,i,&bh2);
				if (tmp->bg_free_inodes_count) {
					gdp = tmp;
					break;
				}
			}
		}
		if (!gdp) {
			/*
			 * That failed: try linear search for a free inode
			 */
			i = dir->i_block_group + 1;
			for (j = 2; j < sb->s_groups_count; j++) {
				if (++i >= sb->s_groups_count)
					i = 0;
				tmp = get_group_desc(ITOV(dir)->v_mount,i,&bh2);
				if (tmp->bg_free_inodes_count) {
					gdp = tmp;
					break;
				}
			}
		}
	}

	if (!gdp) {
		unlock_super (DEVVP(dir));
		return 0;
	}
	bitmap_nr = load_inode_bitmap (ITOV(dir)->v_mount, i);
	bh = sb->s_inode_bitmap[bitmap_nr];
	if ((j = find_first_zero_bit ((unsigned long *) bh->b_data,
				      EXT2_INODES_PER_GROUP(sb))) <
	    EXT2_INODES_PER_GROUP(sb)) {
		if (set_bit (j, bh->b_data)) {
			kprintf ( "ext2_new_inode:"
				      "bit already set for inode %d", j);
			goto repeat;
		}
/* Linux now does the following:
		mark_buffer_dirty(bh);
		if (sb->s_flags & MS_SYNCHRONOUS) {
			ll_rw_block (WRITE, 1, &bh);
			wait_on_buffer (bh);
		}
*/
		mark_buffer_dirty(bh);
	} else {
		if (gdp->bg_free_inodes_count != 0) {
			kprintf ( "ext2_new_inode:"
				    "Free inodes count corrupted in group %d",
				    i);
			unlock_super (DEVVP(dir));
			return 0;
		}
		goto repeat;
	}
	j += i * EXT2_INODES_PER_GROUP(sb) + 1;
	if (j < EXT2_FIRST_INO(sb) || j > es->s_inodes_count) {
		kprintf ( "ext2_new_inode:"
			    "reserved inode or inode > inodes count - "
			    "block_group = %d,inode=%d", i, j);
		unlock_super (DEVVP(dir));
		return 0;
	}
	gdp->bg_free_inodes_count--;
	if (S_ISDIR(mode))
		gdp->bg_used_dirs_count++;
	mark_buffer_dirty(bh2);
	es->s_free_inodes_count--;
	/* mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); */
	sb->s_dirt = 1;
	unlock_super (DEVVP(dir));
	return j;
}
Пример #24
0
struct super_block *efs_read_super(struct super_block *s, void *d, int silent) {
	kdev_t dev = s->s_dev;
	struct efs_sb_info *sb;
	struct buffer_head *bh;

	MOD_INC_USE_COUNT;
	lock_super(s);
  
 	sb = SUPER_INFO(s);

	set_blocksize(dev, EFS_BLOCKSIZE);
  
	/* read the vh (volume header) block */
	bh = bread(dev, 0, EFS_BLOCKSIZE);

	if (!bh) {
		printk(KERN_ERR "EFS: cannot read volume header\n");
		goto out_no_fs_ul;
	}

	/*
	 * if this returns zero then we didn't find any partition table.
	 * this isn't (yet) an error - just assume for the moment that
	 * the device is valid and go on to search for a superblock.
	 */
	sb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data);
	brelse(bh);

	if (sb->fs_start == -1) {
		goto out_no_fs_ul;
	}

	bh = bread(dev, sb->fs_start + EFS_SUPER, EFS_BLOCKSIZE);
	if (!bh) {
		printk(KERN_ERR "EFS: cannot read superblock\n");
		goto out_no_fs_ul;
	}
		
	if (efs_validate_super(sb, (struct efs_super *) bh->b_data)) {
#ifdef DEBUG
		printk(KERN_WARNING "EFS: invalid superblock at block %u\n", sb->fs_start + EFS_SUPER);
#endif
		brelse(bh);
		goto out_no_fs_ul;
	}
	brelse(bh);
 
	s->s_magic		= EFS_SUPER_MAGIC;
	s->s_blocksize		= EFS_BLOCKSIZE;
	s->s_blocksize_bits	= EFS_BLOCKSIZE_BITS;
	if (!(s->s_flags & MS_RDONLY)) {
#ifdef DEBUG
		printk(KERN_INFO "EFS: forcing read-only mode\n");
#endif
		s->s_flags |= MS_RDONLY;
	}
	s->s_op   = &efs_superblock_operations;
	s->s_dev  = dev;
	s->s_root = d_alloc_root(iget(s, EFS_ROOTINODE), NULL);
	unlock_super(s);
 
	if (!(s->s_root)) {
		printk(KERN_ERR "EFS: get root inode failed\n");
		goto out_no_fs;
	}

	if (check_disk_change(s->s_dev)) {
		printk(KERN_ERR "EFS: device changed\n");
		goto out_no_fs;
	}

	return(s);

out_no_fs_ul:
	unlock_super(s);
out_no_fs:
	s->s_dev = 0;
	MOD_DEC_USE_COUNT;
	return(NULL);
}
Пример #25
0
/*
 * NOTE! When we get the inode, we're the only people
 * that have access to it, and as such there are no
 * race conditions we have to worry about. The inode
 * is not on the hash-lists, and it cannot be reached
 * through the filesystem because the directory entry
 * has been deleted earlier.
 *
 * HOWEVER: we must make sure that we get no aliases,
 * which means that we have to call "clear_inode()"
 * _before_ we mark the inode not in use in the inode
 * bitmaps. Otherwise a newly created file might use
 * the same inode number (not actually the same pointer
 * though), and then we'd have two inodes sharing the
 * same inode number and space on the harddisk.
 */
void ufs_free_inode (struct inode * inode)
{
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	struct ufs_cg_private_info * ucpi;
	struct ufs_cylinder_group * ucg;
	int is_directory;
	unsigned ino, cg, bit;
	
	UFSD("ENTER, ino %lu\n", inode->i_ino);

	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
	usb1 = ubh_get_usb_first(uspi);
	
	ino = inode->i_ino;

	lock_super (sb);

	if (!((ino > 1) && (ino < (uspi->s_ncg * uspi->s_ipg )))) {
		ufs_warning(sb, "ufs_free_inode", "reserved inode or nonexistent inode %u\n", ino);
		unlock_super (sb);
		return;
	}
	
	cg = ufs_inotocg (ino);
	bit = ufs_inotocgoff (ino);
	ucpi = ufs_load_cylinder (sb, cg);
	if (!ucpi) {
		unlock_super (sb);
		return;
	}
	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
	if (!ufs_cg_chkmagic(sb, ucg))
		ufs_panic (sb, "ufs_free_fragments", "internal error, bad cg magic number");

	ucg->cg_time = cpu_to_fs32(sb, get_seconds());

	is_directory = S_ISDIR(inode->i_mode);

	DQUOT_FREE_INODE(inode);
	DQUOT_DROP(inode);

	clear_inode (inode);

	if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit))
		ufs_error(sb, "ufs_free_inode", "bit already cleared for inode %u", ino);
	else {
		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit);
		if (ino < ucpi->c_irotor)
			ucpi->c_irotor = ino;
		fs32_add(sb, &ucg->cg_cs.cs_nifree, 1);
		uspi->cs_total.cs_nifree++;
		fs32_add(sb, &UFS_SB(sb)->fs_cs(cg).cs_nifree, 1);

		if (is_directory) {
			fs32_sub(sb, &ucg->cg_cs.cs_ndir, 1);
			uspi->cs_total.cs_ndir--;
			fs32_sub(sb, &UFS_SB(sb)->fs_cs(cg).cs_ndir, 1);
		}
	}

	ubh_mark_buffer_dirty (USPI_UBH(uspi));
	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
	if (sb->s_flags & MS_SYNCHRONOUS) {
		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
		ubh_wait_on_buffer (UCPI_UBH(ucpi));
	}
	
	sb->s_dirt = 1;
	unlock_super (sb);
	UFSD("EXIT\n");
}
Пример #26
0
struct super_block *isofs_read_super(struct super_block *s,void *data,
				     int silent)
{
	struct buffer_head *bh=NULL;
	int iso_blknum;
	unsigned int blocksize_bits;
	int high_sierra;
	kdev_t dev = s->s_dev;
	unsigned int vol_desc_start;
	int orig_zonesize;
	char *p;
	int joliet_level = 0;

	struct iso_volume_descriptor *vdp;
	struct hs_volume_descriptor *hdp;

	struct iso_primary_descriptor *pri = NULL;
	struct iso_supplementary_descriptor *sec = NULL;
	struct hs_primary_descriptor *h_pri = NULL;

	struct iso_directory_record *rootp;

	struct iso9660_options opt;

	MOD_INC_USE_COUNT;

	if (!parse_options((char *) data,&opt)) {
		s->s_dev = 0;
		MOD_DEC_USE_COUNT;
		return NULL;
	}

#if 0
	printk("map = %c\n", opt.map);
	printk("rock = %c\n", opt.rock);
	printk("joliet = %c\n", opt.joliet);
	printk("check = %c\n", opt.check);
	printk("cruft = %c\n", opt.cruft);
	printk("unhide = %c\n", opt.unhide);
	printk("conversion = %c\n", opt.conversion);
	printk("blocksize = %d\n", opt.blocksize);
	printk("gid = %d\n", opt.gid);
	printk("uid = %d\n", opt.uid);
#endif
	
	blocksize_bits = 0;
	{
	  int i = opt.blocksize;
	  while (i != 1){
	    blocksize_bits++;
	    i >>=1;
	  }
	}
	set_blocksize(dev, opt.blocksize);

	lock_super(s);

	s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */

	vol_desc_start = isofs_get_last_session(dev);
	
	for (iso_blknum = vol_desc_start+16;
             iso_blknum < vol_desc_start+100; iso_blknum++)
	{
	    int b = iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits);

	    if (!(bh = bread(dev,b,opt.blocksize))) {
		s->s_dev = 0;
		printk("isofs_read_super: bread failed, dev "
		       "%s iso_blknum %d block %d\n",
		       kdevname(dev), iso_blknum, b);
		unlock_super(s);
		MOD_DEC_USE_COUNT;
		return NULL;
	    }

	    vdp = (struct iso_volume_descriptor *)bh->b_data;
	    hdp = (struct hs_volume_descriptor *)bh->b_data;
	    
	    if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
		if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
		    goto out;
		if (isonum_711 (hdp->type) == ISO_VD_END)
		    goto out;
		
		s->u.isofs_sb.s_high_sierra = 1;
		high_sierra = 1;
		opt.rock = 'n';
		h_pri = (struct hs_primary_descriptor *)vdp;
		break;
	    }

	    if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
		if (isonum_711 (vdp->type) == ISO_VD_END)
		    break;
		if (isonum_711 (vdp->type) == ISO_VD_PRIMARY) {
		    if (pri == NULL) {
			pri = (struct iso_primary_descriptor *)vdp;
		    }
		} else if (isonum_711 (vdp->type) == ISO_VD_SUPPLEMENTARY) {
		    sec = (struct iso_supplementary_descriptor *)vdp;
		    if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
			if (opt.joliet == 'y') {
			    if (sec->escape[2] == 0x40) {
				joliet_level = 1;
			    } else if (sec->escape[2] == 0x43) {
				joliet_level = 2;
			    } else if (sec->escape[2] == 0x45) {
				joliet_level = 3;
			    }
			    printk("ISO9660 Extensions: Microsoft Joliet Level %d\n",
				   joliet_level);
			}
			break;
		    } else {
			/* Unknown supplementary volume descriptor */
			sec = NULL;
		    }
		}
		/* Just skip any volume descriptors we don't recognize */
	    }

	    brelse(bh);
	}
	if ((pri == NULL) && (sec == NULL) && (h_pri == NULL)) {
	    if (!silent)
		printk("Unable to identify CD-ROM format.\n");
	    s->s_dev = 0;
	    unlock_super(s);
	    MOD_DEC_USE_COUNT;
	    return NULL;
	}
	s->u.isofs_sb.s_joliet_level = joliet_level;
	if (joliet_level && opt.rock == 'n') {
	    /* This is the case of Joliet with the norock mount flag.
	     * A disc with both Joliet and Rock Ridge is handled later
	     */
	    pri = (struct iso_primary_descriptor *) sec;
	}

	if(high_sierra){
	  rootp = (struct iso_directory_record *) h_pri->root_directory_record;
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
	  if (isonum_723 (h_pri->volume_set_size) != 1) {
	    printk("Multi-volume disks not supported.\n");
	    goto out;
	  }
#endif IGNORE_WRONG_MULTI_VOLUME_SPECS
	  s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
	  s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
	  s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
	} else {
	  rootp = (struct iso_directory_record *) pri->root_directory_record;
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
	  if (isonum_723 (pri->volume_set_size) != 1) {
	    printk("Multi-volume disks not supported.\n");
	    goto out;
	  }
#endif IGNORE_WRONG_MULTI_VOLUME_SPECS
	  s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
	  s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
	  s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
	}
	
	s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */
	
	/* RDE: convert log zone size to bit shift */

	orig_zonesize = s -> u.isofs_sb.s_log_zone_size;
	switch (s -> u.isofs_sb.s_log_zone_size)
	  { case  512: s -> u.isofs_sb.s_log_zone_size =  9; break;
	    case 1024: s -> u.isofs_sb.s_log_zone_size = 10; break;
	    case 2048: s -> u.isofs_sb.s_log_zone_size = 11; break;

	    default:
	      printk("Bad logical zone size %ld\n", s -> u.isofs_sb.s_log_zone_size);
	      goto out;
	  }

	s->s_magic = ISOFS_SUPER_MAGIC;
	
	/* The CDROM is read-only, has no nodes (devices) on it, and since
	   all of the files appear to be owned by root, we really do not want
	   to allow suid.  (suid or devices will not show up unless we have
	   Rock Ridge extensions) */
	
	s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
	
	brelse(bh);
	
	/* RDE: data zone now byte offset! */

	s->u.isofs_sb.s_firstdatazone = ((isonum_733 (rootp->extent) + 
					   isonum_711 (rootp->ext_attr_length))
					 << s -> u.isofs_sb.s_log_zone_size);
	printk(KERN_DEBUG "Max size:%ld   Log zone size:%ld\n",
	       s->u.isofs_sb.s_max_size, 
	       1UL << s->u.isofs_sb.s_log_zone_size);
	printk(KERN_DEBUG "First datazone:%ld   Root inode number %ld\n",
	       s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size,
	       s->u.isofs_sb.s_firstdatazone);
	if(high_sierra) printk(KERN_DEBUG "Disc in High Sierra format.\n");
	unlock_super(s);
	/* set up enough so that it can read an inode */
	
	/*
	 * Force the blocksize to 512 for 512 byte sectors.  The file
	 * read primitives really get it wrong in a bad way if we don't
	 * do this.
	 */
	if( orig_zonesize < opt.blocksize )
	  {
	    opt.blocksize = orig_zonesize;
	    blocksize_bits = 0;
	    {
	      int i = opt.blocksize;
	      while (i != 1){
		blocksize_bits++;
		i >>=1;
	      }
	    }
	    set_blocksize(dev, opt.blocksize);
	    printk(KERN_DEBUG "Forcing new log zone size:%d\n", opt.blocksize);
	  }
Пример #27
0
struct super_block *capifs_read_super(struct super_block *s, void *data,
				      int silent)
{
	struct inode * root_inode;
	struct dentry * root;
	struct capifs_sb_info *sbi;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
	MOD_INC_USE_COUNT;
	lock_super(s);
#endif
	/* Super block already completed? */
	if (s->s_root)
		goto out;

	sbi = (struct capifs_sb_info *) kmalloc(sizeof(struct capifs_sb_info), GFP_KERNEL);
	if ( !sbi )
		goto fail;

	memset(sbi, 0, sizeof(struct capifs_sb_info));
	sbi->magic  = CAPIFS_SBI_MAGIC;

	if ( capifs_parse_options(data,sbi) ) {
		kfree(sbi);
		printk("capifs: called with bogus options\n");
		goto fail;
	}

	sbi->nccis = kmalloc(sizeof(struct capifs_ncci) * sbi->max_ncci, GFP_KERNEL);
	if ( !sbi->nccis ) {
		kfree(sbi);
		goto fail;
	}
	memset(sbi->nccis, 0, sizeof(struct capifs_ncci) * sbi->max_ncci);

	s->u.generic_sbp = (void *) sbi;
	s->s_blocksize = 1024;
	s->s_blocksize_bits = 10;
	s->s_magic = CAPIFS_SUPER_MAGIC;
	s->s_op = &capifs_sops;
	s->s_root = NULL;

	/*
	 * Get the root inode and dentry, but defer checking for errors.
	 */
	root_inode = iget(s, 1); /* inode 1 == root directory */
	root = d_alloc_root(root_inode);

	/*
	 * Check whether somebody else completed the super block.
	 */
	if (s->s_root) {
		if (root) dput(root);
		else iput(root_inode);
		goto out;
	}

	if (!root) {
		printk("capifs: get root dentry failed\n");
		/*
	 	* iput() can block, so we clear the super block first.
	 	*/
		iput(root_inode);
		kfree(sbi->nccis);
		kfree(sbi);
		goto fail;
	}

	/*
	 * Check whether somebody else completed the super block.
	 */
	if (s->s_root)
		goto out;
	
	/*
	 * Success! Install the root dentry now to indicate completion.
	 */
	s->s_root = root;

	sbi->next = mounts;
	if ( sbi->next )
		SBI(sbi->next)->back = &(sbi->next);
	sbi->back = &mounts;
	mounts = s;

out:	/* Success ... somebody else completed the super block for us. */ 
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
	unlock_super(s);
#endif
	return s;
fail:
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
	unlock_super(s);
	MOD_DEC_USE_COUNT;
#endif
	return NULL;
}
Пример #28
0
/* Called to mount a filesystem by read_super() in fs/super.c
 * Return a super block, the main structure of a filesystem
 *
 * NOTE : Don't store a pointer to an option, as the page containing the
 * options is freed after ntfs_read_super() returns.
 *
 * NOTE : A context switch can happen in kernel code only if the code blocks
 * (= calls schedule() in kernel/sched.c).
 */
struct super_block * ntfs_read_super(struct super_block *sb, 
				     void *options, int silent)
{
	ntfs_volume *vol;
	struct buffer_head *bh;
	int i;

	/* When the driver is compiled as a module, kmod must know when it
	 * can safely remove it from memory. To do this, each module owns a
	 * reference counter.
	 */
	MOD_INC_USE_COUNT;
	/* Don't put ntfs_debug() before MOD_INC_USE_COUNT, printk() can block
	 * so this could lead to a race condition with kmod.
	 */
	ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n");

#ifdef NTFS_IN_LINUX_KERNEL
	vol = NTFS_SB2VOL(sb);
#else
	if(!(vol = ntfs_malloc(sizeof(ntfs_volume))))
		goto ntfs_read_super_dec;
	NTFS_SB2VOL(sb)=vol;
#endif
	
	if(!parse_options(vol,(char*)options))
		goto ntfs_read_super_vol;

	/* Ensure that the super block won't be used until it is completed */
	lock_super(sb);
	ntfs_debug(DEBUG_OTHER, "lock_super\n");
#if 0
	/* Set to read only, user option might reset it */
	sb->s_flags |= MS_RDONLY;
#endif

	/* Assume a 512 bytes block device for now */
	set_blocksize(sb->s_dev, 512);
	/* Read the super block (boot block) */
	if(!(bh=bread(sb->s_dev,0,512))) {
		ntfs_error("Reading super block failed\n");
		goto ntfs_read_super_unl;
	}
	ntfs_debug(DEBUG_OTHER, "Done reading boot block\n");

	/* Check for 'NTFS' magic number */
	if(!IS_NTFS_VOLUME(bh->b_data)){
		ntfs_debug(DEBUG_OTHER, "Not a NTFS volume\n");
		brelse(bh);
		goto ntfs_read_super_unl;
	}

	ntfs_debug(DEBUG_OTHER, "Going to init volume\n");
	ntfs_init_volume(vol,bh->b_data);
	ntfs_debug(DEBUG_OTHER, "MFT record at cluster 0x%X\n",vol->mft_cluster);
	brelse(bh);
	NTFS_SB(vol)=sb;
	ntfs_debug(DEBUG_OTHER, "Done to init volume\n");

	/* Inform the kernel that a device block is a NTFS cluster */
	sb->s_blocksize=vol->clustersize;
	for(i=sb->s_blocksize,sb->s_blocksize_bits=0;i != 1;i>>=1)
		sb->s_blocksize_bits++;
	set_blocksize(sb->s_dev,sb->s_blocksize);
	ntfs_debug(DEBUG_OTHER, "set_blocksize\n");

	/* Allocate a MFT record (MFT record can be smaller than a cluster) */
	if(!(vol->mft=ntfs_malloc(max(vol->mft_recordsize,vol->clustersize))))
		goto ntfs_read_super_unl;

	/* Read at least the MFT record for $MFT */
	for(i=0;i<max(vol->mft_clusters_per_record,1);i++){
		if(!(bh=bread(sb->s_dev,vol->mft_cluster+i,vol->clustersize))) {
			ntfs_error("Could not read MFT record 0\n");
			goto ntfs_read_super_mft;
		}
		ntfs_memcpy(vol->mft+i*vol->clustersize,bh->b_data,vol->clustersize);
		brelse(bh);
		ntfs_debug(DEBUG_OTHER, "Read cluster %x\n",vol->mft_cluster+i);
	}

	/* Check and fixup this MFT record */
	if(!ntfs_check_mft_record(vol,vol->mft)){
		ntfs_error("Invalid MFT record 0\n");
		goto ntfs_read_super_mft;
	}

	/* Inform the kernel about which super operations are available */
	sb->s_op = &ntfs_super_operations;
	sb->s_magic = NTFS_SUPER_MAGIC;
	
	ntfs_debug(DEBUG_OTHER, "Reading special files\n");
	if(ntfs_load_special_files(vol)){
		ntfs_error("Error loading special files\n");
		goto ntfs_read_super_mft;
	}

	ntfs_debug(DEBUG_OTHER, "Getting RootDir\n");
	/* Get the root directory */
	if(!(sb->s_root=d_alloc_root(iget(sb,FILE_ROOT),NULL))){
		ntfs_error("Could not get root dir inode\n");
		goto ntfs_read_super_mft;
	}
	unlock_super(sb);
	ntfs_debug(DEBUG_OTHER, "unlock_super\n");
	ntfs_debug(DEBUG_OTHER, "read_super: done\n");
	return sb;

ntfs_read_super_mft:
	ntfs_free(vol->mft);
ntfs_read_super_unl:
	sb->s_dev = 0;
	unlock_super(sb);
	ntfs_debug(DEBUG_OTHER, "unlock_super\n");
ntfs_read_super_vol:
	#ifndef NTFS_IN_LINUX_KERNEL
	ntfs_free(vol);
ntfs_read_super_dec:
	#endif
	ntfs_debug(DEBUG_OTHER, "read_super: done\n");
	MOD_DEC_USE_COUNT;
	return NULL;
}
Пример #29
0
static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
{
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	struct ufs_super_block_third * usb3;
	unsigned new_mount_opt, ufstype;
	unsigned flags;

	lock_ufs(sb);
	lock_super(sb);
	uspi = UFS_SB(sb)->s_uspi;
	flags = UFS_SB(sb)->s_flags;
	usb1 = ubh_get_usb_first(uspi);
	usb3 = ubh_get_usb_third(uspi);
	
	/*
	 * Allow the "check" option to be passed as a remount option.
	 * It is not possible to change ufstype option during remount
	 */
	ufstype = UFS_SB(sb)->s_mount_opt & UFS_MOUNT_UFSTYPE;
	new_mount_opt = 0;
	ufs_set_opt (new_mount_opt, ONERROR_LOCK);
	if (!ufs_parse_options (data, &new_mount_opt)) {
		unlock_super(sb);
		unlock_ufs(sb);
		return -EINVAL;
	}
	if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) {
		new_mount_opt |= ufstype;
	} else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) {
		printk("ufstype can't be changed during remount\n");
		unlock_super(sb);
		unlock_ufs(sb);
		return -EINVAL;
	}

	if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
		UFS_SB(sb)->s_mount_opt = new_mount_opt;
		unlock_super(sb);
		unlock_ufs(sb);
		return 0;
	}
	
	/*
	 * fs was mouted as rw, remounting ro
	 */
	if (*mount_flags & MS_RDONLY) {
		ufs_put_super_internal(sb);
		usb1->fs_time = cpu_to_fs32(sb, get_seconds());
		if ((flags & UFS_ST_MASK) == UFS_ST_SUN
		  || (flags & UFS_ST_MASK) == UFS_ST_SUNOS
		  || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) 
			ufs_set_fs_state(sb, usb1, usb3,
				UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
		ubh_mark_buffer_dirty (USPI_UBH(uspi));
		sb->s_dirt = 0;
		sb->s_flags |= MS_RDONLY;
	} else {
	/*
	 * fs was mounted as ro, remounting rw
	 */
#ifndef CONFIG_UFS_FS_WRITE
		printk("ufs was compiled with read-only support, "
		"can't be mounted as read-write\n");
		unlock_super(sb);
		unlock_ufs(sb);
		return -EINVAL;
#else
		if (ufstype != UFS_MOUNT_UFSTYPE_SUN && 
		    ufstype != UFS_MOUNT_UFSTYPE_SUNOS &&
		    ufstype != UFS_MOUNT_UFSTYPE_44BSD &&
		    ufstype != UFS_MOUNT_UFSTYPE_SUNx86 &&
		    ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
			printk("this ufstype is read-only supported\n");
			unlock_super(sb);
			unlock_ufs(sb);
			return -EINVAL;
		}
		if (!ufs_read_cylinder_structures(sb)) {
			printk("failed during remounting\n");
			unlock_super(sb);
			unlock_ufs(sb);
			return -EPERM;
		}
		sb->s_flags &= ~MS_RDONLY;
#endif
	}
	UFS_SB(sb)->s_mount_opt = new_mount_opt;
	unlock_super(sb);
	unlock_ufs(sb);
	return 0;
}
Пример #30
0
static struct super_block *
affs_read_super(struct super_block *s, void *data, int silent)
{
	struct buffer_head	*bh = NULL;
	struct buffer_head	*bb;
	struct inode		*root_inode;
	kdev_t			 dev = s->s_dev;
	s32			 root_block;
	int			 blocks, size, blocksize;
	u32			 chksum;
	u32			*bm;
	s32			 ptype, stype;
	int			 mapidx;
	int			 num_bm;
	int			 i, j;
	s32			 key;
	uid_t			 uid;
	gid_t			 gid;
	int			 reserved;
	int			 az_no;
	int			 bmalt = 0;
	unsigned long		 mount_flags;
	unsigned long		 offset;

	pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options");

	MOD_INC_USE_COUNT;
	lock_super(s);
	s->s_magic             = AFFS_SUPER_MAGIC;
	s->s_op                = &affs_sops;
	s->u.affs_sb.s_bitmap  = NULL;
	s->u.affs_sb.s_root_bh = NULL;
	s->u.affs_sb.s_prefix  = NULL;
	s->u.affs_sb.s_hashsize= 0;

	if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
				&blocksize,&s->u.affs_sb.s_prefix,
				s->u.affs_sb.s_volume, &mount_flags))
		goto out_bad_opts;
	/* N.B. after this point s_prefix must be released */

	s->u.affs_sb.s_flags   = mount_flags;
	s->u.affs_sb.s_mode    = i;
	s->u.affs_sb.s_uid     = uid;
	s->u.affs_sb.s_gid     = gid;
	s->u.affs_sb.s_reserved= reserved;

	/* Get the size of the device in 512-byte blocks.
	 * If we later see that the partition uses bigger
	 * blocks, we will have to change it.
	 */

	blocks = blk_size[MAJOR(dev)][MINOR(dev)];
	if (blocks == 0)
		goto out_bad_size;
	s->u.affs_sb.s_blksize = blksize_size[MAJOR(dev)][MINOR(dev)];
	if (!s->u.affs_sb.s_blksize)
		s->u.affs_sb.s_blksize = BLOCK_SIZE;
	size = (s->u.affs_sb.s_blksize / 512) * blocks;
	pr_debug("AFFS: initial blksize=%d, blocks=%d\n",
		s->u.affs_sb.s_blksize, blocks);

	/* Try to find root block. Its location depends on the block size. */

	i = 512;
	j = 4096;
	if (blocksize > 0) {
		i = j = blocksize;
		size = size / (blocksize / 512);
	}
	for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) {
		s->u.affs_sb.s_root_block = root_block;
		if (root_block < 0)
			s->u.affs_sb.s_root_block = (reserved + size - 1) / 2;
		pr_debug("AFFS: setting blocksize to %d\n", blocksize);
		set_blocksize(dev, blocksize);

		/* The root block location that was calculated above is not
		 * correct if the partition size is an odd number of 512-
		 * byte blocks, which will be rounded down to a number of
		 * 1024-byte blocks, and if there were an even number of
		 * reserved blocks. Ideally, all partition checkers should
		 * report the real number of blocks of the real blocksize,
		 * but since this just cannot be done, we have to try to
		 * find the root block anyways. In the above case, it is one
		 * block behind the calculated one. So we check this one, too.
		 */
		for (num_bm = 0; num_bm < 2; num_bm++) {
			pr_debug("AFFS: Dev %s, trying root=%u, bs=%d, "
				"size=%d, reserved=%d\n",
				kdevname(dev),
				s->u.affs_sb.s_root_block + num_bm,
				blocksize, size, reserved);
			bh = affs_bread(dev, s->u.affs_sb.s_root_block + num_bm,
					blocksize);
			if (!bh)
				continue;
			if (!affs_checksum_block(blocksize,bh->b_data,&ptype,&stype) &&
			    ptype == T_SHORT && stype == ST_ROOT) {
				s->s_blocksize             = blocksize;
				s->u.affs_sb.s_hashsize    = blocksize / 4 - 56;
				s->u.affs_sb.s_root_block += num_bm;
				key                        = 1;
				goto got_root;
			}
			affs_brelse(bh);
			bh = NULL;
		}
	}
	goto out_no_valid_block;

	/* N.B. after this point bh must be released */
got_root:
	root_block = s->u.affs_sb.s_root_block;

	s->u.affs_sb.s_partition_size   = size;
	s->s_blocksize_bits             = blocksize == 512 ? 9 :
					  blocksize == 1024 ? 10 :
					  blocksize == 2048 ? 11 : 12;

	/* Find out which kind of FS we have */
	bb = affs_bread(dev,0,s->s_blocksize);
	if (!bb)
		goto out_no_root_block;
	chksum = be32_to_cpu(*(u32 *)bb->b_data);
	affs_brelse(bb);

	/* Dircache filesystems are compatible with non-dircache ones
	 * when reading. As long as they aren't supported, writing is
	 * not recommended.
	 */
	if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS
	     || chksum == MUFS_DCOFS) && !(s->s_flags & MS_RDONLY)) {
		printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n",
			kdevname(dev));
		s->s_flags |= MS_RDONLY;
		s->u.affs_sb.s_flags |= SF_READONLY;
	}
	switch (chksum) {
		case MUFS_FS:
		case MUFS_INTLFFS:
			s->u.affs_sb.s_flags |= SF_MUFS;
			/* fall thru */
		case FS_INTLFFS:
			s->u.affs_sb.s_flags |= SF_INTL;
			break;
		case MUFS_DCFFS:
		case MUFS_FFS:
			s->u.affs_sb.s_flags |= SF_MUFS;
			break;
		case FS_DCFFS:
		case FS_FFS:
			break;
		case MUFS_OFS:
			s->u.affs_sb.s_flags |= SF_MUFS;
			/* fall thru */
		case FS_OFS:
			s->u.affs_sb.s_flags |= SF_OFS;
			s->s_flags |= MS_NOEXEC;
			break;
		case MUFS_DCOFS:
		case MUFS_INTLOFS:
			s->u.affs_sb.s_flags |= SF_MUFS;
		case FS_DCOFS:
		case FS_INTLOFS:
			s->u.affs_sb.s_flags |= SF_INTL | SF_OFS;
			s->s_flags |= MS_NOEXEC;
			break;
		default:
			goto out_unknown_fs;
	}

	if (mount_flags & SF_VERBOSE) {
		chksum = cpu_to_be32(chksum);
		printk(KERN_NOTICE "AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n",
			GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0],
			&GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1],
			(char *)&chksum,((char *)&chksum)[3] + '0',blocksize);
	}