162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * configfs_internal.h - Internal stuff for configfs 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Based on sysfs: 662306a36Sopenharmony_ci * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * configfs Copyright (C) 2005 Oracle. All rights reserved. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#ifdef pr_fmt 1262306a36Sopenharmony_ci#undef pr_fmt 1362306a36Sopenharmony_ci#endif 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/slab.h> 1862306a36Sopenharmony_ci#include <linux/list.h> 1962306a36Sopenharmony_ci#include <linux/spinlock.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistruct configfs_fragment { 2262306a36Sopenharmony_ci atomic_t frag_count; 2362306a36Sopenharmony_ci struct rw_semaphore frag_sem; 2462306a36Sopenharmony_ci bool frag_dead; 2562306a36Sopenharmony_ci}; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_civoid put_fragment(struct configfs_fragment *); 2862306a36Sopenharmony_cistruct configfs_fragment *get_fragment(struct configfs_fragment *); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistruct configfs_dirent { 3162306a36Sopenharmony_ci atomic_t s_count; 3262306a36Sopenharmony_ci int s_dependent_count; 3362306a36Sopenharmony_ci struct list_head s_sibling; 3462306a36Sopenharmony_ci struct list_head s_children; 3562306a36Sopenharmony_ci int s_links; 3662306a36Sopenharmony_ci void * s_element; 3762306a36Sopenharmony_ci int s_type; 3862306a36Sopenharmony_ci umode_t s_mode; 3962306a36Sopenharmony_ci struct dentry * s_dentry; 4062306a36Sopenharmony_ci struct iattr * s_iattr; 4162306a36Sopenharmony_ci#ifdef CONFIG_LOCKDEP 4262306a36Sopenharmony_ci int s_depth; 4362306a36Sopenharmony_ci#endif 4462306a36Sopenharmony_ci struct configfs_fragment *s_frag; 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define CONFIGFS_ROOT 0x0001 4862306a36Sopenharmony_ci#define CONFIGFS_DIR 0x0002 4962306a36Sopenharmony_ci#define CONFIGFS_ITEM_ATTR 0x0004 5062306a36Sopenharmony_ci#define CONFIGFS_ITEM_BIN_ATTR 0x0008 5162306a36Sopenharmony_ci#define CONFIGFS_ITEM_LINK 0x0020 5262306a36Sopenharmony_ci#define CONFIGFS_USET_DIR 0x0040 5362306a36Sopenharmony_ci#define CONFIGFS_USET_DEFAULT 0x0080 5462306a36Sopenharmony_ci#define CONFIGFS_USET_DROPPING 0x0100 5562306a36Sopenharmony_ci#define CONFIGFS_USET_IN_MKDIR 0x0200 5662306a36Sopenharmony_ci#define CONFIGFS_USET_CREATING 0x0400 5762306a36Sopenharmony_ci#define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR | CONFIGFS_ITEM_BIN_ATTR) 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciextern struct mutex configfs_symlink_mutex; 6062306a36Sopenharmony_ciextern spinlock_t configfs_dirent_lock; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciextern struct kmem_cache *configfs_dir_cachep; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciextern int configfs_is_root(struct config_item *item); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ciextern struct inode * configfs_new_inode(umode_t mode, struct configfs_dirent *, struct super_block *); 6762306a36Sopenharmony_ciextern struct inode *configfs_create(struct dentry *, umode_t mode); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciextern int configfs_create_file(struct config_item *, const struct configfs_attribute *); 7062306a36Sopenharmony_ciextern int configfs_create_bin_file(struct config_item *, 7162306a36Sopenharmony_ci const struct configfs_bin_attribute *); 7262306a36Sopenharmony_ciextern int configfs_make_dirent(struct configfs_dirent *, struct dentry *, 7362306a36Sopenharmony_ci void *, umode_t, int, struct configfs_fragment *); 7462306a36Sopenharmony_ciextern int configfs_dirent_is_ready(struct configfs_dirent *); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ciextern void configfs_hash_and_remove(struct dentry * dir, const char * name); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ciextern const unsigned char * configfs_get_name(struct configfs_dirent *sd); 7962306a36Sopenharmony_ciextern void configfs_drop_dentry(struct configfs_dirent *sd, struct dentry *parent); 8062306a36Sopenharmony_ciextern int configfs_setattr(struct mnt_idmap *idmap, 8162306a36Sopenharmony_ci struct dentry *dentry, struct iattr *iattr); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciextern struct dentry *configfs_pin_fs(void); 8462306a36Sopenharmony_ciextern void configfs_release_fs(void); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ciextern const struct file_operations configfs_dir_operations; 8762306a36Sopenharmony_ciextern const struct file_operations configfs_file_operations; 8862306a36Sopenharmony_ciextern const struct file_operations configfs_bin_file_operations; 8962306a36Sopenharmony_ciextern const struct inode_operations configfs_dir_inode_operations; 9062306a36Sopenharmony_ciextern const struct inode_operations configfs_root_inode_operations; 9162306a36Sopenharmony_ciextern const struct inode_operations configfs_symlink_inode_operations; 9262306a36Sopenharmony_ciextern const struct dentry_operations configfs_dentry_ops; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ciextern int configfs_symlink(struct mnt_idmap *idmap, 9562306a36Sopenharmony_ci struct inode *dir, struct dentry *dentry, 9662306a36Sopenharmony_ci const char *symname); 9762306a36Sopenharmony_ciextern int configfs_unlink(struct inode *dir, struct dentry *dentry); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ciint configfs_create_link(struct configfs_dirent *target, struct dentry *parent, 10062306a36Sopenharmony_ci struct dentry *dentry, char *body); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic inline struct config_item * to_item(struct dentry * dentry) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci struct configfs_dirent * sd = dentry->d_fsdata; 10562306a36Sopenharmony_ci return ((struct config_item *) sd->s_element); 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic inline struct configfs_attribute * to_attr(struct dentry * dentry) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci struct configfs_dirent * sd = dentry->d_fsdata; 11162306a36Sopenharmony_ci return ((struct configfs_attribute *) sd->s_element); 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic inline struct configfs_bin_attribute *to_bin_attr(struct dentry *dentry) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci struct configfs_attribute *attr = to_attr(dentry); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci return container_of(attr, struct configfs_bin_attribute, cb_attr); 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic inline struct config_item *configfs_get_config_item(struct dentry *dentry) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci struct config_item * item = NULL; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci spin_lock(&dentry->d_lock); 12662306a36Sopenharmony_ci if (!d_unhashed(dentry)) { 12762306a36Sopenharmony_ci struct configfs_dirent * sd = dentry->d_fsdata; 12862306a36Sopenharmony_ci item = config_item_get(sd->s_element); 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci spin_unlock(&dentry->d_lock); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci return item; 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic inline void release_configfs_dirent(struct configfs_dirent * sd) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci if (!(sd->s_type & CONFIGFS_ROOT)) { 13862306a36Sopenharmony_ci kfree(sd->s_iattr); 13962306a36Sopenharmony_ci put_fragment(sd->s_frag); 14062306a36Sopenharmony_ci kmem_cache_free(configfs_dir_cachep, sd); 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic inline struct configfs_dirent * configfs_get(struct configfs_dirent * sd) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci if (sd) { 14762306a36Sopenharmony_ci WARN_ON(!atomic_read(&sd->s_count)); 14862306a36Sopenharmony_ci atomic_inc(&sd->s_count); 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci return sd; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic inline void configfs_put(struct configfs_dirent * sd) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci WARN_ON(!atomic_read(&sd->s_count)); 15662306a36Sopenharmony_ci if (atomic_dec_and_test(&sd->s_count)) 15762306a36Sopenharmony_ci release_configfs_dirent(sd); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 160