static void configfs_d_iput(struct dentry * dentry, struct inode * inode) { struct configfs_dirent * sd = dentry->d_fsdata; if (sd) { BUG_ON(sd->s_dentry != dentry); sd->s_dentry = NULL; configfs_put(sd); } iput(inode); }
int configfs_unlink(struct inode *dir, struct dentry *dentry) { struct configfs_dirent *sd = dentry->d_fsdata; struct configfs_symlink *sl; struct config_item *parent_item; struct config_item_type *type; int ret; ret = -EPERM; /* What lack-of-symlink returns */ if (!(sd->s_type & CONFIGFS_ITEM_LINK)) goto out; BUG_ON(dentry->d_parent == configfs_sb->s_root); sl = sd->s_element; 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); spin_unlock(&configfs_dirent_lock); configfs_drop_dentry(sd, dentry->d_parent); dput(dentry); configfs_put(sd); /* * drop_link() must be called before * list_del_init(&sl->sl_list), so that the order of * drop_link(this, target) and drop_item(target) is preserved. */ if (type && type->ct_item_ops && type->ct_item_ops->drop_link) type->ct_item_ops->drop_link(parent_item, sl->sl_target); spin_lock(&configfs_dirent_lock); list_del_init(&sl->sl_list); spin_unlock(&configfs_dirent_lock); /* Put reference from create_link() */ config_item_put(sl->sl_target); kfree(sl); config_item_put(parent_item); ret = 0; out: return ret; }
int configfs_unlink(struct inode *dir, struct dentry *dentry) { struct configfs_dirent *sd = dentry->d_fsdata; struct configfs_symlink *sl; struct config_item *parent_item; struct config_item_type *type; int ret; ret = -EPERM; /* */ if (!(sd->s_type & CONFIGFS_ITEM_LINK)) goto out; sl = sd->s_element; 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); spin_unlock(&configfs_dirent_lock); configfs_drop_dentry(sd, dentry->d_parent); dput(dentry); configfs_put(sd); /* */ if (type && type->ct_item_ops && type->ct_item_ops->drop_link) type->ct_item_ops->drop_link(parent_item, sl->sl_target); spin_lock(&configfs_dirent_lock); list_del_init(&sl->sl_list); spin_unlock(&configfs_dirent_lock); /* */ config_item_put(sl->sl_target); kfree(sl); config_item_put(parent_item); ret = 0; out: return ret; }
static void configfs_d_iput(struct dentry * dentry, struct inode * inode) { struct configfs_dirent *sd = dentry->d_fsdata; if (sd) { BUG_ON(sd->s_dentry != dentry); /* Coordinate with configfs_readdir */ spin_lock(&configfs_dirent_lock); sd->s_dentry = NULL; spin_unlock(&configfs_dirent_lock); configfs_put(sd); } iput(inode); }
static void configfs_d_iput(struct dentry * dentry, struct inode * inode) { struct configfs_dirent *sd = dentry->d_fsdata; if (sd) { /* Coordinate with configfs_readdir */ spin_lock(&configfs_dirent_lock); /* Coordinate with configfs_attach_attr where will increase * sd->s_count and update sd->s_dentry to new allocated one. * Only set sd->dentry to null when this dentry is the only * sd owner. * If not do so, configfs_d_iput may run just after * configfs_attach_attr and set sd->s_dentry to null * even it's still in use. */ if (atomic_read(&sd->s_count) <= 2) sd->s_dentry = NULL; spin_unlock(&configfs_dirent_lock); configfs_put(sd); } iput(inode); }