return sd;
}
+/*
+ *
+ * Return -EEXIST if there is already a configfs element with the same
+ * name for the same parent.
+ *
+ * called with parent inode's i_mutex held
+ */
+static int configfs_dirent_exists(struct configfs_dirent *parent_sd,
+ const unsigned char *new)
+{
+ struct configfs_dirent * sd;
+
+ list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
+ if (sd->s_element) {
+ const unsigned char *existing = configfs_get_name(sd);
+ if (strcmp(existing, new))
+ continue;
+ else
+ return -EEXIST;
+ }
+ }
+
+ return 0;
+}
+
+
int configfs_make_dirent(struct configfs_dirent * parent_sd,
struct dentry * dentry, void * element,
umode_t mode, int type)
inode->i_fop = &configfs_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
return 0;
}
int error;
umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
- error = configfs_make_dirent(p->d_fsdata, d, k, mode,
- CONFIGFS_DIR);
+ error = configfs_dirent_exists(p->d_fsdata, d->d_name.name);
+ if (!error)
+ error = configfs_make_dirent(p->d_fsdata, d, k, mode,
+ CONFIGFS_DIR);
if (!error) {
error = configfs_create(d, mode, init_dir);
if (!error) {
- p->d_inode->i_nlink++;
+ inc_nlink(p->d_inode);
(d)->d_op = &configfs_dentry_ops;
} else {
struct configfs_dirent *sd = d->d_fsdata;
return;
}
- mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);
- mutex_lock(&dentry->d_inode->i_mutex);
+ mutex_lock_nested(&configfs_sb->s_root->d_inode->i_mutex,
+ I_MUTEX_PARENT);
+ mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
if (configfs_detach_prep(dentry)) {
printk(KERN_ERR "configfs: Tried to unregister non-empty subsystem!\n");
}