Commit 0862416e authored by Patrick Mochel's avatar Patrick Mochel

sysfs: make symlinks easier.

It's now

int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name)

So, the caller doesn't have to determine the path of the target nor the depth of
the object we're creating the symlink for; it's all taken care of.
parent d2f8eca7
...@@ -457,34 +457,84 @@ int sysfs_create_file(struct kobject * kobj, struct attribute * attr) ...@@ -457,34 +457,84 @@ int sysfs_create_file(struct kobject * kobj, struct attribute * attr)
} }
static int object_depth(struct kobject * kobj)
{
struct kobject * p = kobj;
int depth = 0;
do { depth++; } while ((p = p->parent));
return depth;
}
static int object_path_length(struct kobject * kobj)
{
struct kobject * p = kobj;
int length = 1;
do {
length += strlen(p->name) + 1;
p = p->parent;
} while (p);
return length;
}
static void fill_object_path(struct kobject * kobj, char * buffer, int length)
{
struct kobject * p;
--length;
for (p = kobj; p; p = p->parent) {
int cur = strlen(p->name);
/* back up enough to print this bus id with '/' */
length -= cur;
strncpy(buffer + length,p->name,cur);
*(buffer + --length) = '/';
}
}
/** /**
* sysfs_create_symlink - make a symlink * sysfs_create_link - create symlink between two objects.
* @kobj: object who's directory we're creating in. * @kobj: object whose directory we're creating the link in.
* @name: name of the symlink. * @target: object we're pointing to.
* @target: path we're pointing to. * @name: name of the symlink.
*/ */
int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name)
int sysfs_create_link(struct kobject * kobj, char * name, char * target)
{ {
struct dentry * dentry; struct dentry * dentry = kobj->dir.dentry;
int error; struct dentry * d;
int error = 0;
int size;
int depth;
char * path;
char * s;
depth = object_depth(kobj);
size = object_path_length(target) + depth * 3 - 1;
if (size > PATH_MAX)
return -ENAMETOOLONG;
pr_debug("%s: depth = %d, size = %d\n",__FUNCTION__,depth,size);
path = kmalloc(size,GFP_KERNEL);
if (!path)
return -ENOMEM;
memset(path,0,size);
if (kobj) { for (s = path; depth--; s += 3)
struct dentry * parent = kobj->dir.dentry; strcpy(s,"../");
down(&parent->d_inode->i_sem); fill_object_path(target,path,size);
dentry = get_dentry(parent,name); pr_debug("%s: path = '%s'\n",__FUNCTION__,path);
if (!IS_ERR(dentry))
error = sysfs_symlink(parent->d_inode,dentry,target); down(&dentry->d_inode->i_sem);
else d = get_dentry(dentry,name);
error = PTR_ERR(dentry); if (!IS_ERR(d))
up(&parent->d_inode->i_sem); error = sysfs_symlink(dentry->d_inode,d,path);
} else else
error = -EINVAL; error = PTR_ERR(d);
up(&dentry->d_inode->i_sem);
kfree(path);
return error; return error;
} }
static void hash_and_remove(struct dentry * dir, const char * name) static void hash_and_remove(struct dentry * dir, const char * name)
{ {
struct dentry * victim; struct dentry * victim;
......
...@@ -41,7 +41,7 @@ extern void ...@@ -41,7 +41,7 @@ extern void
sysfs_remove_file(struct kobject *, struct attribute *); sysfs_remove_file(struct kobject *, struct attribute *);
extern int extern int
sysfs_create_link(struct kobject * kobj, char * name, char * target); sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name);
extern void extern void
sysfs_remove_link(struct kobject *, char * name); sysfs_remove_link(struct kobject *, char * name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment