static int dev_mount;
#endif
+static DEFINE_MUTEX(dirlock);
+
static int __init mount_param(char *str)
{
dev_mount = simple_strtoul(str, NULL, 0);
dentry = lookup_create(&nd, 1);
if (!IS_ERR(dentry)) {
err = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
+ if (!err)
+ /* mark as kernel-created inode */
+ dentry->d_inode->i_private = &dev_mnt;
dput(dentry);
} else {
err = PTR_ERR(dentry);
}
- mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+ mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
path_put(&nd.path);
return err;
}
static int create_path(const char *nodepath)
{
- char *path;
- struct nameidata nd;
- int err = 0;
-
- path = kstrdup(nodepath, GFP_KERNEL);
- if (!path)
- return -ENOMEM;
-
- err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
- path, LOOKUP_PARENT, &nd);
- if (err == 0) {
- struct dentry *dentry;
-
- /* create directory right away */
- dentry = lookup_create(&nd, 1);
- if (!IS_ERR(dentry)) {
- err = vfs_mkdir(nd.path.dentry->d_inode,
- dentry, 0755);
- dput(dentry);
- }
- mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+ int err;
- path_put(&nd.path);
- } else if (err == -ENOENT) {
+ mutex_lock(&dirlock);
+ err = dev_mkdir(nodepath, 0755);
+ if (err == -ENOENT) {
+ char *path;
char *s;
/* parent directories do not exist, create them */
+ path = kstrdup(nodepath, GFP_KERNEL);
+ if (!path)
+ return -ENOMEM;
s = path;
- while (1) {
+ for (;;) {
s = strchr(s, '/');
if (!s)
break;
s[0] = '/';
s++;
}
+ kfree(path);
}
-
- kfree(path);
+ mutex_unlock(&dirlock);
return err;
}
mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
if (!IS_ERR(dentry)) {
- if (dentry->d_inode)
- err = vfs_rmdir(nd.path.dentry->d_inode, dentry);
- else
+ if (dentry->d_inode) {
+ if (dentry->d_inode->i_private == &dev_mnt)
+ err = vfs_rmdir(nd.path.dentry->d_inode,
+ dentry);
+ else
+ err = -EPERM;
+ } else {
err = -ENOENT;
+ }
dput(dentry);
} else {
err = PTR_ERR(dentry);
}
- mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+ mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
path_put(&nd.path);
return err;
}
if (!path)
return -ENOMEM;
- while (1) {
+ mutex_lock(&dirlock);
+ for (;;) {
char *base;
base = strrchr(path, '/');
if (err)
break;
}
+ mutex_unlock(&dirlock);
kfree(path);
return err;
* If configured, or requested by the commandline, devtmpfs will be
* auto-mounted after the kernel mounted the root filesystem.
*/
-int devtmpfs_mount(const char *mountpoint)
+int devtmpfs_mount(const char *mntdir)
{
- struct path path;
int err;
if (!dev_mount)
if (!dev_mnt)
return 0;
- err = kern_path(mountpoint, LOOKUP_FOLLOW, &path);
- if (err)
- return err;
- err = do_add_mount(dev_mnt, &path, 0, NULL);
+ err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL);
if (err)
printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
else
printk(KERN_INFO "devtmpfs: mounted\n");
- path_put(&path);
return err;
}
return err;
}
- mnt = kern_mount(&dev_fs_type);
+ mnt = kern_mount_data(&dev_fs_type, "mode=0755");
if (IS_ERR(mnt)) {
err = PTR_ERR(mnt);
printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);