git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
DSS2: Small VRFB context allocation bug fixed
[pandora-kernel.git]
/
fs
/
configfs
/
symlink.c
diff --git
a/fs/configfs/symlink.c
b/fs/configfs/symlink.c
index
2a731ef
..
bf74973
100644
(file)
--- a/
fs/configfs/symlink.c
+++ b/
fs/configfs/symlink.c
@@
-31,6
+31,9
@@
#include <linux/configfs.h>
#include "configfs_internal.h"
#include <linux/configfs.h>
#include "configfs_internal.h"
+/* Protects attachments of new symlinks */
+DEFINE_MUTEX(configfs_symlink_mutex);
+
static int item_depth(struct config_item * item)
{
struct config_item * p = item;
static int item_depth(struct config_item * item)
{
struct config_item * p = item;
@@
-73,21
+76,34
@@
static int create_link(struct config_item *parent_item,
struct configfs_symlink *sl;
int ret;
struct configfs_symlink *sl;
int ret;
+ ret = -ENOENT;
+ if (!configfs_dirent_is_ready(target_sd))
+ goto out;
ret = -ENOMEM;
sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL);
if (sl) {
sl->sl_target = config_item_get(item);
ret = -ENOMEM;
sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL);
if (sl) {
sl->sl_target = config_item_get(item);
- /* FIXME: needs a lock, I'd bet */
+ spin_lock(&configfs_dirent_lock);
+ if (target_sd->s_type & CONFIGFS_USET_DROPPING) {
+ spin_unlock(&configfs_dirent_lock);
+ config_item_put(item);
+ kfree(sl);
+ return -ENOENT;
+ }
list_add(&sl->sl_list, &target_sd->s_links);
list_add(&sl->sl_list, &target_sd->s_links);
+ spin_unlock(&configfs_dirent_lock);
ret = configfs_create_link(sl, parent_item->ci_dentry,
dentry);
if (ret) {
ret = configfs_create_link(sl, parent_item->ci_dentry,
dentry);
if (ret) {
+ spin_lock(&configfs_dirent_lock);
list_del_init(&sl->sl_list);
list_del_init(&sl->sl_list);
+ spin_unlock(&configfs_dirent_lock);
config_item_put(item);
kfree(sl);
}
}
config_item_put(item);
kfree(sl);
}
}
+out:
return ret;
}
return ret;
}
@@
-117,6
+133,7
@@
int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symna
{
int ret;
struct nameidata nd;
{
int ret;
struct nameidata nd;
+ struct configfs_dirent *sd;
struct config_item *parent_item;
struct config_item *target_item;
struct config_item_type *type;
struct config_item *parent_item;
struct config_item *target_item;
struct config_item_type *type;
@@
-125,9
+142,19
@@
int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symna
if (dentry->d_parent == configfs_sb->s_root)
goto out;
if (dentry->d_parent == configfs_sb->s_root)
goto out;
+ sd = dentry->d_parent->d_fsdata;
+ /*
+ * Fake invisibility if dir belongs to a group/default groups hierarchy
+ * being attached
+ */
+ ret = -ENOENT;
+ if (!configfs_dirent_is_ready(sd))
+ goto out;
+
parent_item = configfs_get_config_item(dentry->d_parent);
type = parent_item->ci_type;
parent_item = configfs_get_config_item(dentry->d_parent);
type = parent_item->ci_type;
+ ret = -EPERM;
if (!type || !type->ct_item_ops ||
!type->ct_item_ops->allow_link)
goto out_put;
if (!type || !type->ct_item_ops ||
!type->ct_item_ops->allow_link)
goto out_put;
@@
-137,8
+164,14
@@
int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symna
goto out_put;
ret = type->ct_item_ops->allow_link(parent_item, target_item);
goto out_put;
ret = type->ct_item_ops->allow_link(parent_item, target_item);
- if (!ret)
+ if (!ret) {
+ mutex_lock(&configfs_symlink_mutex);
ret = create_link(parent_item, target_item, dentry);
ret = create_link(parent_item, target_item, dentry);
+ mutex_unlock(&configfs_symlink_mutex);
+ if (ret && type->ct_item_ops->drop_link)
+ type->ct_item_ops->drop_link(parent_item,
+ target_item);
+ }
config_item_put(target_item);
path_put(&nd.path);
config_item_put(target_item);
path_put(&nd.path);
@@
-169,7
+202,9
@@
int configfs_unlink(struct inode *dir, struct dentry *dentry)
parent_item = configfs_get_config_item(dentry->d_parent);
type = parent_item->ci_type;
parent_item = configfs_get_config_item(dentry->d_parent);
type = parent_item->ci_type;
+ spin_lock(&configfs_dirent_lock);
list_del_init(&sd->s_sibling);
list_del_init(&sd->s_sibling);
+ spin_unlock(&configfs_dirent_lock);
configfs_drop_dentry(sd, dentry->d_parent);
dput(dentry);
configfs_put(sd);
configfs_drop_dentry(sd, dentry->d_parent);
dput(dentry);
configfs_put(sd);
@@
-184,8
+219,9
@@
int configfs_unlink(struct inode *dir, struct dentry *dentry)
type->ct_item_ops->drop_link(parent_item,
sl->sl_target);
type->ct_item_ops->drop_link(parent_item,
sl->sl_target);
- /* FIXME: Needs lock */
+ spin_lock(&configfs_dirent_lock);
list_del_init(&sl->sl_list);
list_del_init(&sl->sl_list);
+ spin_unlock(&configfs_dirent_lock);
/* Put reference from create_link() */
config_item_put(sl->sl_target);
/* Put reference from create_link() */
config_item_put(sl->sl_target);