Ejemplo n.º 1
0
/*
 * This routine checks whether a floppy has been changed, and
 * invalidates all buffer-cache-entries in that case. This
 * is a relatively slow routine, so we have to try to minimize using
 * it. Thus it is called only upon a 'mount' or 'open'. This
 * is the best way of combining speed and utility, I think.
 * People changing diskettes in the middle of an operation deserve
 * to loose :-)
 *
 * NOTE! Although currently this is only for floppies, the idea is
 * that any additional removable block-device will use this routine,
 * and that mount/open needn't know that floppies/whatever are
 * special.
 */
void check_disk_change(int dev)
{
	int i;
	struct buffer_head * bh;

	switch(MAJOR(dev)){
	case 2: /* floppy disc */
		if (!(bh = getblk(dev,0,1024)))
			return;
		i = floppy_change(bh);
		brelse(bh);
		break;

#if defined(CONFIG_BLK_DEV_SR) && defined(CONFIG_SCSI)
         case 11: /* CDROM */
		i = check_cdrom_media_change(dev, 0);
		if (i) printk("Flushing buffers and inodes for CDROM\n");
		break;
#endif

         default:
		return;
	};

	if (!i)	return;

	for (i=0 ; i<NR_SUPER ; i++)
		if (super_block[i].s_dev == dev)
			put_super(super_block[i].s_dev);
	invalidate_inodes(dev);
	invalidate_buffers(dev);
}
Ejemplo n.º 2
0
/*
 * This routine checks whether a removable media has been changed,
 * and invalidates all buffer-cache-entries in that case. This
 * is a relatively slow routine, so we have to try to minimize using
 * it. Thus it is called only upon a 'mount' or 'open'. This
 * is the best way of combining speed and utility, I think.
 * People changing diskettes in the middle of an operation deserve
 * to loose :-)
 */
int check_disk_change(kdev_t dev)
{
	int i;
	struct file_operations * fops;
	struct super_block * sb;

	i = MAJOR(dev);
	if (i >= MAX_BLKDEV || (fops = blkdevs[i].fops) == NULL)
		return 0;
	if (fops->check_media_change == NULL)
		return 0;
	if (!fops->check_media_change(dev))
		return 0;

	printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",
		bdevname(dev));

	sb = get_super(dev);
	if (sb && invalidate_inodes(sb))
		printk("VFS: busy inodes on changed media.\n");

	invalidate_buffers(dev);

	if (fops->revalidate)
		fops->revalidate(dev);
	return 1;
}
Ejemplo n.º 3
0
/*
 * This routine checks whether a removable media has been changed,
 * and invalidates all buffer-cache-entries in that case. This
 * is a relatively slow routine, so we have to try to minimize using
 * it. Thus it is called only upon a 'mount' or 'open'. This
 * is the best way of combining speed and utility, I think.
 * People changing diskettes in the middle of an operation deserve
 * to loose :-)
 */
int check_disk_change(kdev_t dev)
{
	int i;
	struct file_operations * fops;

	i = MAJOR(dev);
	if (i >= MAX_BLKDEV || (fops = blkdevs[i].fops) == NULL)
		return 0;
	if (fops->check_media_change == NULL)
		return 0;
	if (!fops->check_media_change(dev))
		return 0;

	printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",
		kdevname(dev));
	for (i=0 ; i<NR_SUPER ; i++)
		if (super_blocks[i].s_dev == dev)
			put_super(super_blocks[i].s_dev);
	invalidate_inodes(dev);
	invalidate_buffers(dev);

	if (fops->revalidate)
		fops->revalidate(dev);
	return 1;
}
Ejemplo n.º 4
0
//// 检查磁盘是否更换,如果已更换就使对应高速缓冲区无效。
void
check_disk_change( int dev )
{
	int i;

// 是软盘设备吗?如果不是则退出。
	if( MAJOR( dev ) != 2 )
	{
		return;
	}
// 测试对应软盘是否已更换,如果没有则退出。
	if( !floppy_change( dev & 0x03 ) )
	{
		return;
	}
// 软盘已经更换,所以释放对应设备的i 节点位图和逻辑块位图所占的高速缓冲区;并使该设备的
// i 节点和数据块信息所占的高速缓冲区无效。
	for( i = 0; i < NR_SUPER; i++ )
	{
		if( super_block[i].s_dev == dev )
		{
			put_super( super_block[i].s_dev );
		}
	}
	invalidate_inodes( dev );
	invalidate_buffers( dev );
}
Ejemplo n.º 5
0
/*
 * This is called if the connection has gone bad ...
 * try to kill off all the current inodes.
 */
void
smb_invalidate_inodes(struct smb_sb_info *server)
{
	VERBOSE("\n");
	shrink_dcache_sb(SB_of(server));
	invalidate_inodes(SB_of(server));
}
Ejemplo n.º 6
0
Archivo: main.c Proyecto: gapry/myfs
// 回收超级块
static void myfs_kill_sb(struct super_block *sb)
{
	kfree(sb->s_fs_info);
	if (invalidate_inodes(sb, 1)) // 强制毁灭所有inode及其dirty页
		printk("myfs: Eliminate all inodes finished partially!\n");
	kill_litter_super(sb);
}
Ejemplo n.º 7
0
static int do_remount_sb(struct super_block *sb, int flags, char *data)
{
	int retval;
	struct vfsmount *vfsmnt;
	
	/*
	 * Invalidate the inodes, as some mount options may be changed.
	 * N.B. If we are changing media, we should check the return
	 * from invalidate_inodes ... can't allow _any_ open files.
	 */
	invalidate_inodes(sb);

	if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev))
		return -EACCES;
		/*flags |= MS_RDONLY;*/
	/* If we are remounting RDONLY, make sure there are no rw files open */
	if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
		if (!fs_may_remount_ro(sb))
			return -EBUSY;
	if (sb->s_op && sb->s_op->remount_fs) {
		retval = sb->s_op->remount_fs(sb, &flags, data);
		if (retval)
			return retval;
	}
	sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
	vfsmnt = lookup_vfsmnt(sb->s_dev);
	if (vfsmnt)
		vfsmnt->mnt_flags = sb->s_flags;
	return 0;
}
Ejemplo n.º 8
0
/*
 * This routine checks whether a floppy has been changed, and
 * invalidates all buffer-cache-entries in that case. This
 * is a relatively slow routine, so we have to try to minimize using
 * it. Thus it is called only upon a 'mount' or 'open'. This
 * is the best way of combining speed and utility, I think.
 * People changing diskettes in the middle of an operation deserve
 * to loose :-)
 *
 * NOTE! Although currently this is only for floppies, the idea is
 * that any additional removable block-device will use this routine,
 * and that mount/open needn't know that floppies/whatever are
 * special.
 */
void check_disk_change(dev_t dev)
{
	int i;
	struct buffer_head * bh;

	switch(MAJOR(dev)){
	case FLOPPY_MAJOR:
		if (!(bh = getblk(dev,0,1024)))
			return;
		i = floppy_change(bh);
		brelse(bh);
		break;

#if defined(CONFIG_BLK_DEV_SD) && defined(CONFIG_SCSI)
         case SCSI_DISK_MAJOR:
		i = check_scsidisk_media_change(dev, 0);
		break;
#endif

#if defined(CONFIG_BLK_DEV_SR) && defined(CONFIG_SCSI)
	 case SCSI_CDROM_MAJOR:
		i = check_cdrom_media_change(dev, 0);
		break;
#endif

#if defined(CONFIG_CDU31A)
         case CDU31A_CDROM_MAJOR:
		i = check_cdu31a_media_change(dev, 0);
		break;
#endif

#if defined(CONFIG_MCD)
         case MITSUMI_CDROM_MAJOR:
		i = check_mcd_media_change(dev, 0);
		break;
#endif

         default:
		return;
	};

	if (!i)	return;

	printk("VFS: Disk change detected on device %d/%d\n",
					MAJOR(dev), MINOR(dev));
	for (i=0 ; i<NR_SUPER ; i++)
		if (super_blocks[i].s_dev == dev)
			put_super(super_blocks[i].s_dev);
	invalidate_inodes(dev);
	invalidate_buffers(dev);

#if defined(CONFIG_BLK_DEV_SD) && defined(CONFIG_SCSI)
/* This is trickier for a removable hardisk, because we have to invalidate
   all of the partitions that lie on the disk. */
	if (MAJOR(dev) == SCSI_DISK_MAJOR)
		revalidate_scsidisk(dev, 0);
#endif
}
Ejemplo n.º 9
0
/*
 * This routine checks whether a floppy has been changed, and
 * invalidates all buffer-cache-entries in that case. This
 * is a relatively slow routine, so we have to try to minimize using
 * it. Thus it is called only upon a 'mount' or 'open'. This
 * is the best way of combining speed and utility, I think.
 * People changing diskettes in the middle of an operation deserve
 * to loose :-)
 *
 * NOTE! Although currently this is only for floppies, the idea is
 * that any additional removable block-device will use this routine,
 * and that mount/open needn't know that floppies/whatever are
 * special.
 */
void check_disk_change(int dev)
{
    int i;

    if (MAJOR(dev) != 2)
        return;
    if (!floppy_change(dev & 0x03))
        return;
    for (i=0 ; i<NR_SUPER ; i++)
        if (super_block[i].s_dev == dev)
            put_super(super_block[i].s_dev);
    invalidate_inodes(dev);
    invalidate_buffers(dev);
}
Ejemplo n.º 10
0
/*
 * This routine checks whether a floppy has been changed, and
 * invalidates all buffer-cache-entries in that case. This
 * is a relatively slow routine, so we have to try to minimize using
 * it. Thus it is called only upon a 'mount' or 'open'. This
 * is the best way of combining speed and utility, I think.
 * People changing diskettes in the middle of an operation deserve
 * to loose :-)
 *
 * NOTE! Although currently this is only for floppies, the idea is
 * that any additional removable block-device will use this routine,
 * and that mount/open needn't know that floppies/whatever are
 * special.
 */
void check_disk_change(int dev)
{
	int i;
	struct buffer_head * bh;

	if (MAJOR(dev) != 2)
		return;
	if (!(bh = getblk(dev,0)))
		return;
	i = floppy_change(bh);
	brelse(bh);
	if (!i)
		return;
	for (i=0 ; i<NR_SUPER ; i++)
		if (super_block[i].s_dev == dev)
			put_super(super_block[i].s_dev);
	invalidate_inodes(dev);
	invalidate_buffers(dev);
}
Ejemplo n.º 11
0
static int ext2_remount (struct super_block * sb, int * flags, char * data)
{
	struct ext2_sb_info * sbi = EXT2_SB(sb);
	struct ext2_super_block * es;
	unsigned long old_mount_opt = sbi->s_mount_opt;
	struct ext2_mount_options old_opts;
	unsigned long old_sb_flags;
	int err;

	lock_kernel();

	/* Store the old options */
	old_sb_flags = sb->s_flags;
	old_opts.s_mount_opt = sbi->s_mount_opt;
	old_opts.s_resuid = sbi->s_resuid;
	old_opts.s_resgid = sbi->s_resgid;

	/*
	 * Allow the "check" option to be passed as a remount option.
	 */
	if (!parse_options (data, sbi)) {
		err = -EINVAL;
		goto restore_opts;
	}

	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
		((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);

	ext2_xip_verify_sb(sb); /* see if bdev supports xip, unset
				    EXT2_MOUNT_XIP if not */

	if ((ext2_use_xip(sb)) && (sb->s_blocksize != PAGE_SIZE)) {
		printk("XIP: Unsupported blocksize\n");
		err = -EINVAL;
		goto restore_opts;
	}

	es = sbi->s_es;
	if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) !=
	    (old_mount_opt & EXT2_MOUNT_XIP)) &&
	    invalidate_inodes(sb)) {
		ext2_warning(sb, __func__, "refusing change of xip flag "
			     "with busy inodes while remounting");
		sbi->s_mount_opt &= ~EXT2_MOUNT_XIP;
		sbi->s_mount_opt |= old_mount_opt & EXT2_MOUNT_XIP;
	}
	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
		unlock_kernel();
		return 0;
	}
	if (*flags & MS_RDONLY) {
		if (le16_to_cpu(es->s_state) & EXT2_VALID_FS ||
		    !(sbi->s_mount_state & EXT2_VALID_FS)) {
			unlock_kernel();
			return 0;
		}
		/*
		 * OK, we are remounting a valid rw partition rdonly, so set
		 * the rdonly flag and then mark the partition as valid again.
		 */
		es->s_state = cpu_to_le16(sbi->s_mount_state);
		es->s_mtime = cpu_to_le32(get_seconds());
	} else {
		__le32 ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
					       ~EXT2_FEATURE_RO_COMPAT_SUPP);
		if (ret) {
			printk("EXT2-fs: %s: couldn't remount RDWR because of "
			       "unsupported optional features (%x).\n",
			       sb->s_id, le32_to_cpu(ret));
			err = -EROFS;
			goto restore_opts;
		}
		/*
		 * Mounting a RDONLY partition read-write, so reread and
		 * store the current valid flag.  (It may have been changed
		 * by e2fsck since we originally mounted the partition.)
		 */
		sbi->s_mount_state = le16_to_cpu(es->s_state);
		if (!ext2_setup_super (sb, es, 0))
			sb->s_flags &= ~MS_RDONLY;
	}
	ext2_sync_super(sb, es);
	unlock_kernel();
	return 0;
restore_opts:
	sbi->s_mount_opt = old_opts.s_mount_opt;
	sbi->s_resuid = old_opts.s_resuid;
	sbi->s_resgid = old_opts.s_resgid;
	sb->s_flags = old_sb_flags;
	unlock_kernel();
	return err;
}
Ejemplo n.º 12
0
Archivo: rd.c Proyecto: KP1533TM2/elks
static int rd_ioctl(register struct inode *inode, struct file *file,
		    unsigned int cmd, unsigned int arg)
{
    unsigned long size;
    unsigned int i;
    int j, k, target = DEVICE_NR(inode->i_rdev);

    if (!suser())
	return -EPERM;
    debug2("RD: ioctl %d %s\n", target, (cmd ? "kill" : "make"));
    switch (cmd) {
    case RDCREATE:
	if (rd_info[target].flags && RD_BUSY) {
	    return -EBUSY;
	} else {
	    /* allocate memory */

#if 0
	    rd_info[target].size = 0;
#endif

	    k = -1;
	    for (i = 0; i <= (arg - 1) / ((SEG_SIZE / 1024) * P_SIZE); i++) {
		j = find_free_seg();	/* find free place in queue */
		debug1("RD: ioctl find_free_seg() = %d\n", j);
		if (j == -1) {
		    rd_dealloc(target);
		    return -ENOMEM;
		}
		if (i == 0)
		    rd_info[target].index = j;

		if (i == (arg / ((SEG_SIZE / 1024) * P_SIZE)))
		    /* size in 16 byte pagez = (arg % 64) * 64 */
		    size =
			(arg % ((SEG_SIZE / 1024) * P_SIZE)) *
			((SEG_SIZE / 1024) * P_SIZE);
		else
		    size = SEG_SIZE;

		rd_segment[j].segment = mm_alloc(size);
		if (rd_segment[j].segment == -1) {
		    rd_dealloc(target);
		    return -ENOMEM;
		}
		debug4("RD: ioctl pass: %d, allocated %d pages, rd_segment[%d].segment = 0x%x\n",
		       i, (int) size, j, rd_segment[j].segment);

		/* recalculate int size to reflect size in sectors, not pages */
		size = size / DIVISOR;

		rd_segment[j].seg_size = size;	/* size in sectors */
		debug2("RD: ioctl rd_segment[%d].seg_size = %d sectors\n",
		       j, rd_segment[j].seg_size);
		rd_info[target].size += rd_segment[j].seg_size;	/* size in 512 B blocks */
		size = (long) rd_segment[j].seg_size * SECTOR_SIZE;
		debug1("RD: ioctl size = %ld\n", size);

		/* this terrible hack makes sure fmemset clears whole segment even if size == 64 KB :) */
		if (size != ((long) SEG_SIZE * (long) P_SIZE)) {
		    debug2("RD: ioctl calling fmemset(0, 0x%x, 0, %d) ..\n",
			   rd_segment[j].segment, (int) size);
		    fmemset(0, rd_segment[j].segment, 0, (int) size);	/* clear seg_size * SECTOR_SIZE bytes */
		} else {
		    debug2("RD: ioctl calling fmemset(0, 0x%x, 0, %d) ..\n",
			   rd_segment[j].segment, (int) (size / 2));
		    fmemset(0, rd_segment[j].segment, 0, (int) (size / 2));	/* we could hardcode 32768 instead of size / 2 here */
		    debug3("rd_ioctl(): calling fmemset(%d, 0x%x, 0, %d) ..\n",
			   (int) (size / 2), rd_segment[j].segment,
			   (int) (size / 2));
		    fmemset((size / 2), rd_segment[j].segment, 0,
			    (int) (size / 2));
		}

		if (k != -1)
		    rd_segment[k].next = j;	/* set link to next index */
		k = j;
	    }
	    rd_info[target].flags = RD_BUSY;
	    debug3("RD: ioctl ramdisk %d created, size = %d blocks, index = %d\n",
		 target, rd_info[target].size, rd_info[target].index);
	}
	debug("RD: ioctl about to return 0\n");
	return 0;
    case RDDESTROY:
	if (rd_info[target].flags && RD_BUSY) {
	    invalidate_inodes(inode->i_rdev);
	    invalidate_buffers(inode->i_rdev);
	    rd_dealloc(target);
	    rd_info[target].flags = 0;
	    return 0;
	} else
	    return -EINVAL;
    }
    return -EINVAL;
}
Ejemplo n.º 13
0
static int
flash_ioctl(struct inode *inode, struct file *file,
	    unsigned int cmd, unsigned long arg)
{
	int minor;
	struct flashpartition *part;
	struct flashchipinfo *finfo;

	if (!inode || !inode->i_rdev)
		return -EINVAL;

	minor = MINOR(inode->i_rdev);

	if(minor < FLASH_MINOR)
		return -EINVAL; /* only ioctl's for flash devices */

	part = &partitions[minor - FLASH_MINOR];

	switch(cmd) {
	case FLASHIO_CHIPINFO:

		if(!suser())
			return -EACCES;

		if(arg == 0)
			return -EINVAL;

		finfo = (struct flashchipinfo *)arg;

		/* TODO: verify arg */

		finfo->isValid = chips[0].isValid;
		finfo->manufacturer_id = chips[0].manufacturer_id;
		finfo->device_id = chips[0].device_id;
		finfo->size = chips[0].size;
		finfo->sectorsize = chips[0].sectorsize;

		return 0;

	case FLASHIO_ERASEALL:
		FDEBUG(printk("flash_ioctl(): Got FLASHIO_ERASEALL request.\n"));

		if(!part->start)
			return -EINVAL;

		if(!suser())
			return -EACCES;

		/* Invalidate all pages and buffers */

		invalidate_inodes(inode->i_rdev);
		invalidate_buffers(inode->i_rdev);

		/*
		 * Start the erasure, then sleep and wake up now and
		 * then to see if it's done. We use the waitqueue to
		 * make sure we don't start erasing in the middle of
		 * a write, or that nobody start using the flash while
		 * we're erasing.
		 *
		 * TODO: break up partition erases that spans more than one
		 *       chip.
		 */

		flash_safe_acquire(part);

		flash_init_erase(part->start, part->size);
#if 1
		flash_finalize_erase(part->start, part->size);
#else
		while (flash_is_busy(part->start)
		       || !flash_pos_is_clean(part->start)) {
			current->state = TASK_INTERRUPTIBLE;
			current->timeout = jiffies + HZ / 2;
			schedule();
		}
#endif

		flash_safe_release(part);

		return 0;

	default:
		return -EPERM;
	}

	return -EPERM;
}
Ejemplo n.º 14
0
static int do_umount(kdev_t dev, int unmount_root, int flags)
{
	struct super_block * sb;
	int retval;
	
	retval = -ENOENT;
	sb = get_super(dev);
	if (!sb || !sb->s_root)
		goto out;

	/*
	 * Before checking whether the filesystem is still busy,
	 * make sure the kernel doesn't hold any quota files open
	 * on the device. If the umount fails, too bad -- there
	 * are no quotas running any more. Just turn them on again.
	 */
	DQUOT_OFF(dev);
	acct_auto_close(dev);

	/*
	 * If we may have to abort operations to get out of this
	 * mount, and they will themselves hold resources we must
	 * allow the fs to do things. In the Unix tradition of
	 * 'Gee thats tricky lets do it in userspace' the umount_begin
	 * might fail to complete on the first run through as other tasks
	 * must return, and the like. Thats for the mount program to worry
	 * about for the moment.
	 */
	 
	if( (flags&MNT_FORCE) && sb->s_op->umount_begin)
		sb->s_op->umount_begin(sb);

	/*
	 * Shrink dcache, then fsync. This guarantees that if the
	 * filesystem is quiescent at this point, then (a) only the
	 * root entry should be in use and (b) that root entry is
	 * clean.
	 */
	shrink_dcache_sb(sb);
	fsync_dev(dev);

	if (dev==ROOT_DEV && !unmount_root) {
		/*
		 * Special case for "unmounting" root ...
		 * we just try to remount it readonly.
		 */
		retval = 0;
		if (!(sb->s_flags & MS_RDONLY))
			retval = do_remount_sb(sb, MS_RDONLY, 0);
		return retval;
	}

	retval = d_umount(sb);
	if (retval)
		goto out;

	if (sb->s_op) {
		if (sb->s_op->write_super && sb->s_dirt)
			sb->s_op->write_super(sb);
	}

	lock_super(sb);
	if (sb->s_op) {
		if (sb->s_op->put_super)
			sb->s_op->put_super(sb);
	}

	/* Forget any remaining inodes */
	if (invalidate_inodes(sb)) {
		printk("VFS: Busy inodes after unmount. "
			"Self-destruct in 5 seconds.  Have a nice day...\n");
	}

	sb->s_dev = 0;		/* Free the superblock */
	unlock_super(sb);

	remove_vfsmnt(dev);
out:
	return retval;
}