Exemplo n.º 1
0
static int ace_open(struct block_device *bdev, fmode_t mode)
{
	struct ace_device *ace = bdev->bd_disk->private_data;
	unsigned long flags;

	dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1);

	mutex_lock(&xsysace_mutex);
	spin_lock_irqsave(&ace->lock, flags);
	ace->users++;
	spin_unlock_irqrestore(&ace->lock, flags);

	check_disk_change(bdev);
	mutex_unlock(&xsysace_mutex);

	return 0;
}
Exemplo n.º 2
0
static int mmc_blk_open(struct inode *inode, struct file *filp)
{
    struct mmc_blk_data *md;
    int ret = -ENXIO;

    md = mmc_blk_get(inode->i_bdev->bd_disk);
    if (md) {
        if (md->usage == 2)
            check_disk_change(inode->i_bdev);
        ret = 0;

        if ((filp->f_mode & FMODE_WRITE) && md->read_only)
            ret = -EROFS;
    }

    return ret;
}
Exemplo n.º 3
0
static int card_blk_open(struct block_device *bdev, fmode_t mode)
{
	struct card_blk_data *card_data;
	int ret = -ENXIO;

	card_data = card_blk_get(bdev->bd_disk);
	if (card_data) {
		if (card_data->usage == 2)
			check_disk_change(bdev);
		ret = 0;

		if ((mode & FMODE_WRITE) && card_data->read_only)
			ret = -EROFS;
	}

	return ret;
}
Exemplo n.º 4
0
static int
zvol_open(struct block_device *bdev, fmode_t flag)
{
	zvol_state_t *zv = bdev->bd_disk->private_data;
	int error = 0, drop_mutex = 0;

	/*
	 * If the caller is already holding the mutex do not take it
	 * again, this will happen as part of zvol_create_minor().
	 * Once add_disk() is called the device is live and the kernel
	 * will attempt to open it to read the partition information.
	 */
	if (!mutex_owned(&zvol_state_lock)) {
		mutex_enter(&zvol_state_lock);
		drop_mutex = 1;
	}

	ASSERT3P(zv, !=, NULL);

	if (zv->zv_open_count == 0) {
		error = zvol_first_open(zv);
		if (error)
			goto out_mutex;
	}

	if ((flag & FMODE_WRITE) &&
	    (get_disk_ro(zv->zv_disk) || (zv->zv_flags & ZVOL_RDONLY))) {
		error = -EROFS;
		goto out_open_count;
	}

	zv->zv_open_count++;

out_open_count:
	if (zv->zv_open_count == 0)
		zvol_last_close(zv);

out_mutex:
	if (drop_mutex)
		mutex_exit(&zvol_state_lock);

	check_disk_change(bdev);

	return (error);
}
Exemplo n.º 5
0
static int mbd_open(struct inode *inode, struct file *file)
{
	int dev;

	if (!inode)
		return -EINVAL;
	dev = inode->i_bdev->bd_disk->first_minor;
	if (dev >= MAX_MBD)
		return -ENODEV;

	check_disk_change(inode->i_bdev);

	if (!mbd_dev[dev].initialized)
		if (!mbd_init_disk(dev))
			return -ENODEV;

	mbd_dev[dev].refcnt++;
	return 0;
}
Exemplo n.º 6
0
/*
 * Ensure the zap is flushed then inform the VFS of the capacity change.
 */
static int
zvol_update_volsize(zvol_state_t *zv, uint64_t volsize)
{
	struct block_device *bdev;
	dmu_tx_t *tx;
	int error;

	ASSERT(MUTEX_HELD(&zvol_state_lock));

	tx = dmu_tx_create(zv->zv_objset);
	dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
	error = dmu_tx_assign(tx, TXG_WAIT);
	if (error) {
		dmu_tx_abort(tx);
		return (error);
	}

	error = zap_update(zv->zv_objset, ZVOL_ZAP_OBJ, "size", 8, 1,
	    &volsize, tx);
	dmu_tx_commit(tx);

	if (error)
		return (error);

	error = dmu_free_long_range(zv->zv_objset,
	    ZVOL_OBJ, volsize, DMU_OBJECT_END);
	if (error)
		return (error);

	zv->zv_volsize = volsize;
	zv->zv_changed = 1;

	bdev = bdget_disk(zv->zv_disk, 0);
	if (!bdev)
		return EIO;

	error = check_disk_change(bdev);
	ASSERT3U(error, !=, 0);
	bdput(bdev);

	return (0);
}
Exemplo n.º 7
0
static struct super_block * read_super(kdev_t dev,const char *name,int flags,
				       void *data, int silent)
{
	struct super_block * s;
	struct file_system_type *type;

	if (!dev)
		goto out_null;
	check_disk_change(dev);
	s = get_super(dev);
	if (s)
		goto out;

	type = get_fs_type(name);
	if (!type) {
		printk("VFS: on device %s: get_fs_type(%s) failed\n",
		       kdevname(dev), name);
		goto out;
	}
	s = get_empty_super();
	if (!s)
		goto out;
	s->s_dev = dev;
	s->s_flags = flags;
	s->s_dirt = 0;
	sema_init(&s->s_vfs_rename_sem,1);
	/* N.B. Should lock superblock now ... */
	if (!type->read_super(s, data, silent))
		goto out_fail;
	s->s_dev = dev; /* N.B. why do this again?? */
	s->s_rd_only = 0;
	s->s_type = type;
out:
	return s;

	/* N.B. s_dev should be cleared in type->read_super */
out_fail:
	s->s_dev = 0;
out_null:
	s = NULL;
	goto out;
}
Exemplo n.º 8
0
static int sd_open(struct inode * inode, struct file * filp)
{
        int target;
	target =  DEVICE_NR(MINOR(inode->i_rdev));

	if(target >= NR_SD || !rscsi_disks[target].device)
	  return -ENODEV;   /* No such device */
	
/* Make sure that only one process can do a check_change_disk at one time.
 This is also used to lock out further access when the partition table is being re-read. */

	while (rscsi_disks[target].device->busy);

	if(rscsi_disks[target].device->removable) {
	  check_disk_change(inode->i_rdev);

	  if(!rscsi_disks[target].device->access_count)
	    sd_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0);
	};
	rscsi_disks[target].device->access_count++;
	return 0;
}
Exemplo n.º 9
0
static struct super_block * read_super(kdev_t dev,const char *name,int flags,
				       void *data, int silent)
{
	struct super_block * s;
	struct file_system_type *type;

	if (!dev)
		return NULL;
	check_disk_change(dev);
	s = get_super(dev);
	if (s)
		return s;
	if (!(type = get_fs_type(name))) {
		printk("VFS: on device %s: get_fs_type(%s) failed\n",
		       kdevname(dev), name);
		return NULL;
	}
	for (s = 0+super_blocks ;; s++) {
		if (s >= NR_SUPER+super_blocks)
			return NULL;
		if (!(s->s_dev))
			break;
	}
	s->s_dev = dev;
	s->s_flags = flags;
	if (!type->read_super(s,data, silent)) {
		s->s_dev = 0;
		return NULL;
	}
	s->s_dev = dev;
	s->s_covered = NULL;
	s->s_rd_only = 0;
	s->s_dirt = 0;
	s->s_type = type;
	return s;
}
Exemplo n.º 10
0
static void
zvol_size_changed(zvol_state_t *zv, uint64_t volsize)
{
	struct block_device *bdev;

	bdev = bdget_disk(zv->zv_disk, 0);
	if (bdev == NULL)
		return;
/*
 * 2.6.28 API change
 * Added check_disk_size_change() helper function.
 */
#ifdef HAVE_CHECK_DISK_SIZE_CHANGE
	set_capacity(zv->zv_disk, volsize >> 9);
	zv->zv_volsize = volsize;
	check_disk_size_change(zv->zv_disk, bdev);
#else
	zv->zv_volsize = volsize;
	zv->zv_changed = 1;
	(void) check_disk_change(bdev);
#endif /* HAVE_CHECK_DISK_SIZE_CHANGE */

	bdput(bdev);
}
Exemplo n.º 11
0
static int floppy_open(struct block_device *bdev, fmode_t mode)
{
	struct floppy_state *fs = bdev->bd_disk->private_data;
	struct swim3 __iomem *sw = fs->swim3;
	int n, err = 0;

	if (fs->ref_count == 0) {
		if (fs->mdev->media_bay &&
		    check_media_bay(fs->mdev->media_bay) != MB_FD)
			return -ENXIO;
		out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2);
		out_8(&sw->control_bic, 0xff);
		out_8(&sw->mode, 0x95);
		udelay(10);
		out_8(&sw->intr_enable, 0);
		out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE);
		swim3_action(fs, MOTOR_ON);
		fs->write_prot = -1;
		fs->cur_cyl = -1;
		for (n = 0; n < 2 * HZ; ++n) {
			if (n >= HZ/30 && swim3_readbit(fs, SEEK_COMPLETE))
				break;
			if (signal_pending(current)) {
				err = -EINTR;
				break;
			}
			swim3_select(fs, RELAX);
			schedule_timeout_interruptible(1);
		}
		if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0
				 || swim3_readbit(fs, DISK_IN) == 0))
			err = -ENXIO;
		swim3_action(fs, SETMFM);
		swim3_select(fs, RELAX);

	} else if (fs->ref_count == -1 || mode & FMODE_EXCL)
		return -EBUSY;

	if (err == 0 && (mode & FMODE_NDELAY) == 0
	    && (mode & (FMODE_READ|FMODE_WRITE))) {
		check_disk_change(bdev);
		if (fs->ejected)
			err = -ENXIO;
	}

	if (err == 0 && (mode & FMODE_WRITE)) {
		if (fs->write_prot < 0)
			fs->write_prot = swim3_readbit(fs, WRITE_PROT);
		if (fs->write_prot)
			err = -EROFS;
	}

	if (err) {
		if (fs->ref_count == 0) {
			swim3_action(fs, MOTOR_OFF);
			out_8(&sw->control_bic, DRIVE_ENABLE | INTR_ENABLE);
			swim3_select(fs, RELAX);
		}
		return err;
	}

	if (mode & FMODE_EXCL)
		fs->ref_count = -1;
	else
		++fs->ref_count;

	return 0;
}
Exemplo n.º 12
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);
}
Exemplo n.º 13
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;
}