int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) { struct sysfs_addrm_cxt acxt; struct sysfs_dirent **pos, *sd; if (!dir_sd) return -ENOENT; sysfs_addrm_start(&acxt, dir_sd); for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) { sd = *pos; if (!sysfs_type(sd)) continue; if (!strcmp(sd->s_name, name)) { *pos = sd->s_sibling; sd->s_sibling = NULL; sysfs_remove_one(&acxt, sd); break; } } if (sysfs_addrm_finish(&acxt)) return 0; return -ENOENT; }
static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) { struct sysfs_addrm_cxt acxt; struct sysfs_dirent **pos; if (!dir_sd) return; pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); sysfs_addrm_start(&acxt, dir_sd); pos = &dir_sd->s_children; while (*pos) { struct sysfs_dirent *sd = *pos; if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) { *pos = sd->s_sibling; sd->s_sibling = NULL; sysfs_remove_one(&acxt, sd); } else pos = &(*pos)->s_sibling; } sysfs_addrm_finish(&acxt); remove_dir(dir_sd); }
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; }
/** * sysfs_hash_and_remove - find a sysfs_dirent by name and remove it * @dir_sd: parent of the target * @name: name of the sysfs_dirent to remove * @ns: namespace tag of the sysfs_dirent to remove * * Look for the sysfs_dirent with @name and @ns under @dir_sd and remove * it. Returns 0 on success, -ENOENT if such entry doesn't exist. */ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name, const void *ns) { struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; if (!dir_sd) { WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n", name); return -ENOENT; } sysfs_addrm_start(&acxt); sd = sysfs_find_dirent(dir_sd, name, ns); if (sd) __sysfs_remove(&acxt, sd); sysfs_addrm_finish(&acxt); if (sd) return 0; else return -ENOENT; }
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; }
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; }
/** * sysfs_remove - remove a sysfs_dirent recursively * @sd: the sysfs_dirent to remove * * Remove @sd along with all its subdirectories and files. */ void sysfs_remove(struct sysfs_dirent *sd) { struct sysfs_addrm_cxt acxt; sysfs_addrm_start(&acxt); __sysfs_remove(&acxt, sd); sysfs_addrm_finish(&acxt); }
static void remove_dir(struct sysfs_dirent *sd) { struct sysfs_addrm_cxt acxt; sysfs_addrm_start(&acxt, sd->s_parent); sysfs_remove_one(&acxt, sd); sysfs_addrm_finish(&acxt); }
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; }
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) { struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; if (!dir_sd) return -ENOENT; sysfs_addrm_start(&acxt, dir_sd); sd = sysfs_find_dirent(dir_sd, name); if (sd) sysfs_remove_one(&acxt, sd); sysfs_addrm_finish(&acxt); if (sd) return 0; else return -ENOENT; }
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; }