- 论坛徽章:
- 0
|
if (nd.mnt && nd.mnt->mnt_sb == sb
&& nd.mnt->mnt_root == nd.dentry)什么意思?
请指教,谢谢
long do_mount(char * dev_name, char * dir_name, char *type_page,
unsigned long flags, void *data_page)
{
struct file_system_type * fstype;
struct nameidata nd;
struct vfsmount *mnt = NULL;
struct super_block *sb;
int retval = 0;
/* Discard magic */
if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
flags &= ~MS_MGC_MSK;
/* Basic sanity checks */
if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
return -EINVAL;
if (dev_name && !memchr(dev_name, 0, PAGE_SIZE))
return -EINVAL;
/* OK, looks good, now let's see what do they want */
/* just change the flags? - capabilities are checked in do_remount() */
if (flags & MS_REMOUNT)
return do_remount(dir_name, flags & ~MS_REMOUNT,
(char *) data_page);
/* "mount --bind"? Equivalent to older "mount -t bind" */
/* No capabilities? What if users do thousands of these? */
if (flags & MS_BIND)
return do_loopback(dev_name, dir_name);
/* For the rest we need the type */
if (!type_page || !memchr(type_page, 0, PAGE_SIZE))
return -EINVAL;
#if 0 /* Can be deleted again. Introduced in patch-2.3.99-pre6 */
/* loopback mount? This is special - requires fewer capabilities */
if (strcmp(type_page, "bind")==0)
return do_loopback(dev_name, dir_name);
#endif
/* for the rest we _really_ need capabilities... */
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
/* ... filesystem driver... */
fstype = get_fs_type(type_page);
if (!fstype)
return -ENODEV;
/* ... and mountpoint. Do the lookup first to force automounting. */
if (path_init(dir_name,
LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, &nd))
retval = path_walk(dir_name, &nd);
if (retval)
goto fs_out;
/* get superblock, locks mount_sem on success */
if (fstype->fs_flags & FS_NOMOUNT)
sb = ERR_PTR(-EINVAL);
else if (fstype->fs_flags & FS_REQUIRES_DEV)
sb = get_sb_bdev(fstype, dev_name, flags, data_page);
else if (fstype->fs_flags & FS_SINGLE)
sb = get_sb_single(fstype, flags, data_page);
else
sb = get_sb_nodev(fstype, flags, data_page);
retval = PTR_ERR(sb);
if (IS_ERR(sb))
goto dput_out;
/* Something was mounted here while we slept */
while(d_mountpoint(nd.dentry) && follow_down(&nd.mnt, &nd.dentry))
;
/* Refuse the same filesystem on the same mount point */
retval = -EBUSY;
if (nd.mnt && nd.mnt->mnt_sb == sb
&& nd.mnt->mnt_root == nd.dentry)
goto fail;
retval = -ENOENT;
if (!nd.dentry->d_inode)
goto fail;
down(&nd.dentry->d_inode->i_zombie);
if (!IS_DEADDIR(nd.dentry->d_inode)) {
retval = -ENOMEM;
mnt = add_vfsmnt(&nd, sb->s_root, dev_name);
}
up(&nd.dentry->d_inode->i_zombie);
if (!mnt)
goto fail;
retval = 0;
unlock_out:
up(&mount_sem);
dput_out:
path_release(&nd);
fs_out:
put_filesystem(fstype);
return retval;
fail:
if (list_empty(&sb->s_mounts))
kill_super(sb, 0);
goto unlock_out;
} |
|