⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 super.c

📁 嵌入式系统设计与实例开发源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	s->s_flags = flags;	spin_lock(&sb_lock);	insert_super(s, type);	lock_super(s);	if (!type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))		goto out_fail;	s->s_flags |= MS_ACTIVE;	unlock_super(s);	/* tell bdcache that we are going to keep this one */	if (bdev)		atomic_inc(&bdev->bd_count);out:	return s;out_fail:	unlock_super(s);	deactivate_super(s);	remove_super(s);	return NULL;}/* * Unnamed block devices are dummy devices used by virtual * filesystems which don't use real block-devices.  -- jrs */static unsigned long unnamed_dev_in_use[256/(8*sizeof(unsigned long))];kdev_t get_unnamed_dev(void){	int i;	for (i = 1; i < 256; i++) {		if (!test_and_set_bit(i,unnamed_dev_in_use))			return MKDEV(UNNAMED_MAJOR, i);	}	return 0;}void put_unnamed_dev(kdev_t dev){	if (!dev || MAJOR(dev) != UNNAMED_MAJOR)		return;	if (test_and_clear_bit(MINOR(dev), unnamed_dev_in_use))		return;	printk("VFS: put_unnamed_dev: freeing unused device %s\n",			kdevname(dev));}static struct super_block *get_sb_bdev(struct file_system_type *fs_type,	char *dev_name, int flags, void * data){	struct inode *inode;	struct block_device *bdev;	struct block_device_operations *bdops;	devfs_handle_t de;	struct super_block * s;	struct nameidata nd;	struct list_head *p;	kdev_t dev;	int error = 0;	mode_t mode = FMODE_READ; /* we always need it ;-) */	/* What device it is? */	if (!dev_name || !*dev_name)		return ERR_PTR(-EINVAL);	if (path_init(dev_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd))		error = path_walk(dev_name, &nd);	if (error)		return ERR_PTR(error);	inode = nd.dentry->d_inode;	error = -ENOTBLK;	if (!S_ISBLK(inode->i_mode))		goto out;	error = -EACCES;	if (nd.mnt->mnt_flags & MNT_NODEV)		goto out;	bd_acquire(inode);	bdev = inode->i_bdev;	de = devfs_get_handle_from_inode (inode);	bdops = devfs_get_ops (de);         /*  Increments module use count  */	if (bdops) bdev->bd_op = bdops;	/* Done with lookups, semaphore down */	dev = to_kdev_t(bdev->bd_dev);	if (!(flags & MS_RDONLY))		mode |= FMODE_WRITE;	error = blkdev_get(bdev, mode, 0, BDEV_FS);	devfs_put_ops (de);   /*  Decrement module use count now we're safe  */	if (error)		goto out;	check_disk_change(dev);	error = -EACCES;	if (!(flags & MS_RDONLY) && is_read_only(dev)) {		blkdev_put(bdev, BDEV_FS);		goto out;	}	error = -ENOMEM;	s = alloc_super();	if (!s) {		blkdev_put(bdev, BDEV_FS);		goto out;	}	error = -EBUSY;restart:	spin_lock(&sb_lock);	list_for_each(p, &super_blocks) {		struct super_block *old = sb_entry(p);		if (old->s_dev != dev)			continue;		if (old->s_type != fs_type ||		    ((flags ^ old->s_flags) & MS_RDONLY)) {			spin_unlock(&sb_lock);			destroy_super(s);			blkdev_put(bdev, BDEV_FS);			goto out;		}		if (!grab_super(old))			goto restart;		destroy_super(s);		blkdev_put(bdev, BDEV_FS);		path_release(&nd);		return old;	}	s->s_dev = dev;	s->s_bdev = bdev;	s->s_flags = flags;	insert_super(s, fs_type);	error = -EINVAL;	lock_super(s);	if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))		goto out_fail;	s->s_flags |= MS_ACTIVE;	unlock_super(s);	path_release(&nd);	return s;out_fail:	unlock_super(s);	deactivate_super(s);	remove_super(s);out:	path_release(&nd);	return ERR_PTR(error);}static struct super_block *get_sb_nodev(struct file_system_type *fs_type,	int flags, void * data){	kdev_t dev;	int error = -EMFILE;	dev = get_unnamed_dev();	if (dev) {		struct super_block * sb;		error = -EINVAL;		sb = read_super(dev, NULL, fs_type, flags, data);		if (sb)			return sb;	}	return ERR_PTR(error);}static struct super_block *get_sb_single(struct file_system_type *fs_type,	int flags, void *data){	struct super_block * s = alloc_super();	if (!s)		return ERR_PTR(-ENOMEM);	/*	 * Get the superblock of kernel-wide instance, but	 * keep the reference to fs_type.	 */retry:	spin_lock(&sb_lock);	if (!list_empty(&fs_type->fs_supers)) {		struct super_block *old;		old = list_entry(fs_type->fs_supers.next, struct super_block,				s_instances);		if (!grab_super(old))			goto retry;		destroy_super(s);		do_remount_sb(old, flags, data);		return old;	} else {		kdev_t dev = get_unnamed_dev();		if (!dev) {			spin_unlock(&sb_lock);			destroy_super(s);			return ERR_PTR(-EMFILE);		}		s->s_dev = dev;		s->s_flags = flags;		insert_super(s, fs_type);		lock_super(s);		if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))			goto out_fail;		s->s_flags |= MS_ACTIVE;		unlock_super(s);		return s;	out_fail:		unlock_super(s);		deactivate_super(s);		remove_super(s);		return ERR_PTR(-EINVAL);	}}void kill_super(struct super_block *sb){	struct dentry *root = sb->s_root;	struct file_system_type *fs = sb->s_type;	struct super_operations *sop = sb->s_op;	if (!deactivate_super(sb))		return;	down_write(&sb->s_umount);	lock_kernel();	sb->s_root = NULL;	/* Need to clean after the sucker */	if (fs->fs_flags & FS_LITTER)		d_genocide(root);	shrink_dcache_parent(root);	dput(root);	fsync_super(sb);	lock_super(sb);	sb->s_flags &= ~MS_ACTIVE;	invalidate_inodes(sb);	/* bad name - it should be evict_inodes() */	if (sop) {		if (sop->write_super && sb->s_dirt)			sop->write_super(sb);		if (sop->put_super)			sop->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");	}	unlock_kernel();	unlock_super(sb);	remove_super(sb);}/* * Alters the mount flags of a mounted file system. Only the mount point * is used as a reference - file system type and the device are ignored. */int do_remount_sb(struct super_block *sb, int flags, void *data){	int retval;		if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev))		return -EACCES;		/*flags |= MS_RDONLY;*/	if (flags & MS_RDONLY)		acct_auto_close(sb->s_dev);	shrink_dcache_sb(sb);	fsync_super(sb);	/* 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) {		lock_super(sb);		retval = sb->s_op->remount_fs(sb, &flags, data);		unlock_super(sb);		if (retval)			return retval;	}	sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);	/*	 * We can't invalidate inodes as we can loose data when remounting	 * (someone might manage to alter data while we are waiting in lock_super()	 * or in foo_remount_fs()))	 */	return 0;}struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data){	struct file_system_type * fstype;	struct vfsmount *mnt = NULL;	struct super_block *sb;	if (!type || !memchr(type, 0, PAGE_SIZE))		return ERR_PTR(-EINVAL);	/* we need capabilities... */	if (!capable(CAP_SYS_ADMIN))		return ERR_PTR(-EPERM);	/* ... filesystem driver... */	fstype = get_fs_type(type);	if (!fstype)				return ERR_PTR(-ENODEV);	/* ... allocated vfsmount... */	mnt = alloc_vfsmnt();	if (!mnt) {		mnt = ERR_PTR(-ENOMEM);		goto fs_out;	}	set_devname(mnt, name);	/* get locked superblock */	if (fstype->fs_flags & FS_REQUIRES_DEV)		sb = get_sb_bdev(fstype, name, flags, data);	else if (fstype->fs_flags & FS_SINGLE)		sb = get_sb_single(fstype, flags, data);	else		sb = get_sb_nodev(fstype, flags, data);	if (IS_ERR(sb)) {		free_vfsmnt(mnt);		mnt = (struct vfsmount *)sb;		goto fs_out;	}	if (fstype->fs_flags & FS_NOMOUNT)		sb->s_flags |= MS_NOUSER;	mnt->mnt_sb = sb;	mnt->mnt_root = dget(sb->s_root);	mnt->mnt_mountpoint = mnt->mnt_root;	mnt->mnt_parent = mnt;	up_write(&sb->s_umount);fs_out:	put_filesystem(fstype);	return mnt;}struct vfsmount *kern_mount(struct file_system_type *type){	return do_kern_mount((char *)type->name, 0, (char *)type->name, NULL);}static char * __initdata root_mount_data;static int __init root_data_setup(char *str){	root_mount_data = str;	return 1;}static char * __initdata root_fs_names;static int __init fs_names_setup(char *str){	root_fs_names = str;	return 1;}__setup("rootflags=", root_data_setup);__setup("rootfstype=", fs_names_setup);static void __init get_fs_names(char *page){	char *s = page;	if (root_fs_names) {		strcpy(page, root_fs_names);		while (*s++) {			if (s[-1] == ',')				s[-1] = '\0';		}	} else {		int len = get_filesystem_list(page);		char *p, *next;		page[len] = '\0';		for (p = page-1; p; p = next) {			next = strchr(++p, '\n');			if (*p++ != '\t')				continue;			while ((*s++ = *p++) != '\n')				;			s[-1] = '\0';		}	}	*s = '\0';}void __init mount_root(void){	struct nameidata root_nd;	struct super_block * sb;	struct vfsmount *vfsmnt;	struct block_device *bdev = NULL;	mode_t mode;	int retval;	void *handle;	char path[64];	int path_start = -1;	char *name = "/dev/root";	char *fs_names, *p;#ifdef CONFIG_ROOT_NFS	void *data;#endif	root_mountflags |= MS_VERBOSE;#ifdef CONFIG_ROOT_NFS	if (MAJOR(ROOT_DEV) != UNNAMED_MAJOR)		goto skip_nfs;	data = nfs_root_data();	if (!data)		goto no_nfs;	vfsmnt = do_kern_mount("nfs", root_mountflags, "/dev/root", data);	if (!IS_ERR(vfsmnt)) {		printk ("VFS: Mounted root (%s filesystem).\n", "nfs");		ROOT_DEV = vfsmnt->mnt_sb->s_dev;		goto attach_it;	}no_nfs:	printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");	ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0);skip_nfs:#endif#ifdef CONFIG_BLK_DEV_FD	if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {#ifdef CONFIG_BLK_DEV_RAM		extern int rd_doload;		extern void rd_load_secondary(void);#endif		floppy_eject();#ifndef CONFIG_BLK_DEV_RAM		printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n");#else		/* rd_doload is 2 for a dual initrd/ramload setup */		if(rd_doload==2)			rd_load_secondary();		else#endif		{			printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");			wait_for_keypress();		}	}#endif	fs_names = __getname();	get_fs_names(fs_names);	devfs_make_root (root_device_name);	handle = devfs_find_handle (NULL, ROOT_DEVICE_NAME,	                            MAJOR (ROOT_DEV), MINOR (ROOT_DEV),				    DEVFS_SPECIAL_BLK, 1);	if (handle)  /*  Sigh: bd*() functions only paper over the cracks  */	{	    unsigned major, minor;	    devfs_get_maj_min (handle, &major, &minor);	    ROOT_DEV = MKDEV (major, minor);	}	/*	 * Probably pure paranoia, but I'm less than happy about delving into	 * devfs crap and checking it right now. Later.	 */	if (!ROOT_DEV)		panic("I have no root and I want to scream");retry:	bdev = bdget(kdev_t_to_nr(ROOT_DEV));	if (!bdev)		panic("%s: unable to allocate root device", __FUNCTION__);	bdev->bd_op = devfs_get_ops (handle); /* Increments module use count */	path_start = devfs_generate_path (handle, path + 5, sizeof (path) - 5);	mode = FMODE_READ;	if (!(root_mountflags & MS_RDONLY))		mode |= FMODE_WRITE;	retval = blkdev_get(bdev, mode, 0, BDEV_FS);	devfs_put_ops (handle); /* Decrement module use count now we're safe */	if (retval == -EROFS) {		root_mountflags |= MS_RDONLY;		goto retry;	}	if (retval) {	        /*		 * Allow the user to distinguish between failed open		 * and bad superblock on root device.		 */Eio:		printk ("VFS: Cannot open root device \"%s\" or %s\n",			root_device_name, kdevname (ROOT_DEV));		printk ("Please append a correct \"root=\" boot option\n");		panic("VFS: Unable to mount root fs on %s",			kdevname(ROOT_DEV));	}	check_disk_change(ROOT_DEV);	sb = get_super(ROOT_DEV);	if (sb) {		/* FIXME */		p = (char *)sb->s_type->name;		atomic_inc(&sb->s_active);		up_read(&sb->s_umount);		down_write(&sb->s_umount);		goto mount_it;	}	for (p = fs_names; *p; p += strlen(p)+1) {		struct file_system_type * fs_type = get_fs_type(p);		if (!fs_type)  			continue;		atomic_inc(&bdev->bd_count);		retval = blkdev_get(bdev, mode, 0, BDEV_FS);		if (retval)			goto Eio;  		sb = read_super(ROOT_DEV, bdev, fs_type,				root_mountflags, root_mount_data);		put_filesystem(fs_type);		if (sb) {			blkdev_put(bdev, BDEV_FS);			goto mount_it;		}	}	panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV));mount_it:	/* FIXME */	up_write(&sb->s_umount);	printk ("VFS: Mounted root (%s filesystem)%s.\n", p,		(sb->s_flags & MS_RDONLY) ? " readonly" : "");	putname(fs_names);	if (path_start >= 0) {		name = path + path_start;		devfs_unregister (devfs_find_handle(NULL, "root", 0, 0, 0, 0));		devfs_mk_symlink (NULL, "root", DEVFS_FL_DEFAULT,				  name + 5, NULL, NULL);		memcpy (name, "/dev/", 5);	}	vfsmnt = alloc_vfsmnt();	if (!vfsmnt)		panic("VFS: alloc_vfsmnt failed for root fs");	set_devname(vfsmnt, name);	vfsmnt->mnt_sb = sb;	vfsmnt->mnt_root = dget(sb->s_root);	bdput(bdev); /* sb holds a reference */#ifdef CONFIG_ROOT_NFSattach_it:#endif	root_nd.mnt = root_vfsmnt;	root_nd.dentry = root_vfsmnt->mnt_sb->s_root;	graft_tree(vfsmnt, &root_nd);	set_fs_root(current->fs, vfsmnt, vfsmnt->mnt_root);	set_fs_pwd(current->fs, vfsmnt, vfsmnt->mnt_root);	mntput(vfsmnt);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -