static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, const char *name, struct sysfs_dirent **p_sd) { umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; /* allocate */ sd = sysfs_new_dirent(name, mode, SYSFS_DIR); if (!sd) return -ENOMEM; sd->s_elem.dir.kobj = kobj; /* link in */ sysfs_addrm_start(&acxt, parent_sd); if (!sysfs_find_dirent(parent_sd, name)) { sysfs_add_one(&acxt, sd); sysfs_link_sibling(sd); } if (!sysfs_addrm_finish(&acxt)) { sysfs_put(sd); return -EEXIST; } *p_sd = sd; return 0; }
int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, int type) { umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; sd = sysfs_new_dirent(attr->name, mode, type); if (!sd) return -ENOMEM; sd->s_elem.attr.attr = (void *)attr; sysfs_addrm_start(&acxt, dir_sd); if (!sysfs_find_dirent(dir_sd, attr->name)) { sysfs_add_one(&acxt, sd); sysfs_link_sibling(sd); } if (!sysfs_addrm_finish(&acxt)) { sysfs_put(sd); return -EEXIST; } return 0; }
static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, enum kobj_ns_type type, const char *name, const void *ns, struct sysfs_dirent **p_sd) { umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; int rc; /* allocate */ sd = sysfs_new_dirent(name, mode, SYSFS_DIR); if (!sd) return -ENOMEM; sd->s_flags |= (type << SYSFS_NS_TYPE_SHIFT); sd->s_ns = ns; sd->s_dir.kobj = kobj; /* link in */ sysfs_addrm_start(&acxt); rc = sysfs_add_one(&acxt, sd, parent_sd); sysfs_addrm_finish(&acxt); if (rc == 0) *p_sd = sd; else sysfs_put(sd); return rc; }
static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, const char *name, int warn) { struct sysfs_dirent *parent_sd = NULL; struct sysfs_dirent *target_sd = NULL; struct sysfs_dirent *sd = NULL; struct sysfs_addrm_cxt acxt; int error; BUG_ON(!name); if (!kobj) parent_sd = &sysfs_root; else parent_sd = kobj->sd; error = -EFAULT; if (!parent_sd) goto out_put; /* target->sd can go away beneath us but is protected with * sysfs_assoc_lock. Fetch target_sd from it. */ spin_lock(&sysfs_assoc_lock); if (target->sd) target_sd = sysfs_get(target->sd); spin_unlock(&sysfs_assoc_lock); error = -ENOENT; if (!target_sd) goto out_put; error = -ENOMEM; sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); if (!sd) goto out_put; sd->s_symlink.target_sd = target_sd; target_sd = NULL; /* reference is now owned by the symlink */ sysfs_addrm_start(&acxt, parent_sd); if (warn) error = sysfs_add_one(&acxt, sd); else error = __sysfs_add_one(&acxt, sd); sysfs_addrm_finish(&acxt); if (error) goto out_put; return 0; out_put: sysfs_put(target_sd); sysfs_put(sd); return error; }
struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj) { struct sysfs_dirent *parent_sd = kobj->sd->s_parent; struct dentry *dir, *parent, *shadow; struct inode *inode; struct sysfs_dirent *sd; struct sysfs_addrm_cxt acxt; dir = sysfs_get_dentry(kobj->sd); if (IS_ERR(dir)) { sd = (void *)dir; goto out; } parent = dir->d_parent; inode = dir->d_inode; sd = ERR_PTR(-EINVAL); if (!sysfs_is_shadowed_inode(inode)) goto out_dput; shadow = d_alloc(parent, &dir->d_name); if (!shadow) goto nomem; sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR); if (!sd) goto nomem; sd->s_elem.dir.kobj = kobj; sysfs_addrm_start(&acxt, parent_sd); /* add but don't link into children list */ sysfs_add_one(&acxt, sd); /* attach and instantiate dentry */ sysfs_attach_dentry(sd, shadow); d_instantiate(shadow, igrab(inode)); inc_nlink(inode); /* tj: synchronization? */ sysfs_addrm_finish(&acxt); dget(shadow); /* Extra count - pin the dentry in core */ goto out_dput; nomem: dput(shadow); sd = ERR_PTR(-ENOMEM); out_dput: dput(dir); out: return sd; }
static int sysfs_dir_open(struct inode *inode, struct file *file) { struct dentry * dentry = file->f_path.dentry; struct sysfs_dirent * parent_sd = dentry->d_fsdata; struct sysfs_dirent * sd; sd = sysfs_new_dirent("_DIR_", 0, 0); if (sd) { mutex_lock(&sysfs_mutex); sd->s_parent = sysfs_get(parent_sd); sysfs_link_sibling(sd); mutex_unlock(&sysfs_mutex); } file->private_data = sd; return sd ? 0 : -ENOMEM; }
int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, int type) { umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; int rc; sd = sysfs_new_dirent(attr->name, mode, type); if (!sd) return -ENOMEM; sd->s_attr.attr = (void *)attr; sysfs_addrm_start(&acxt, dir_sd); rc = sysfs_add_one(&acxt, sd); sysfs_addrm_finish(&acxt); if (rc) sysfs_put(sd); return rc; }