18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* -*- mode: c; c-basic-offset:8; -*- 38c2ecf20Sopenharmony_ci * vim: noexpandtab sw=8 ts=8 sts=0: 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * configfs_internal.h - Internal stuff for configfs 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Based on sysfs: 88c2ecf20Sopenharmony_ci * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * configfs Copyright (C) 2005 Oracle. All rights reserved. 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#ifdef pr_fmt 148c2ecf20Sopenharmony_ci#undef pr_fmt 158c2ecf20Sopenharmony_ci#endif 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <linux/slab.h> 208c2ecf20Sopenharmony_ci#include <linux/list.h> 218c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistruct configfs_fragment { 248c2ecf20Sopenharmony_ci atomic_t frag_count; 258c2ecf20Sopenharmony_ci struct rw_semaphore frag_sem; 268c2ecf20Sopenharmony_ci bool frag_dead; 278c2ecf20Sopenharmony_ci}; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_civoid put_fragment(struct configfs_fragment *); 308c2ecf20Sopenharmony_cistruct configfs_fragment *get_fragment(struct configfs_fragment *); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistruct configfs_dirent { 338c2ecf20Sopenharmony_ci atomic_t s_count; 348c2ecf20Sopenharmony_ci int s_dependent_count; 358c2ecf20Sopenharmony_ci struct list_head s_sibling; 368c2ecf20Sopenharmony_ci struct list_head s_children; 378c2ecf20Sopenharmony_ci int s_links; 388c2ecf20Sopenharmony_ci void * s_element; 398c2ecf20Sopenharmony_ci int s_type; 408c2ecf20Sopenharmony_ci umode_t s_mode; 418c2ecf20Sopenharmony_ci struct dentry * s_dentry; 428c2ecf20Sopenharmony_ci struct iattr * s_iattr; 438c2ecf20Sopenharmony_ci#ifdef CONFIG_LOCKDEP 448c2ecf20Sopenharmony_ci int s_depth; 458c2ecf20Sopenharmony_ci#endif 468c2ecf20Sopenharmony_ci struct configfs_fragment *s_frag; 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#define CONFIGFS_ROOT 0x0001 508c2ecf20Sopenharmony_ci#define CONFIGFS_DIR 0x0002 518c2ecf20Sopenharmony_ci#define CONFIGFS_ITEM_ATTR 0x0004 528c2ecf20Sopenharmony_ci#define CONFIGFS_ITEM_BIN_ATTR 0x0008 538c2ecf20Sopenharmony_ci#define CONFIGFS_ITEM_LINK 0x0020 548c2ecf20Sopenharmony_ci#define CONFIGFS_USET_DIR 0x0040 558c2ecf20Sopenharmony_ci#define CONFIGFS_USET_DEFAULT 0x0080 568c2ecf20Sopenharmony_ci#define CONFIGFS_USET_DROPPING 0x0100 578c2ecf20Sopenharmony_ci#define CONFIGFS_USET_IN_MKDIR 0x0200 588c2ecf20Sopenharmony_ci#define CONFIGFS_USET_CREATING 0x0400 598c2ecf20Sopenharmony_ci#define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR | CONFIGFS_ITEM_BIN_ATTR) 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ciextern struct mutex configfs_symlink_mutex; 628c2ecf20Sopenharmony_ciextern spinlock_t configfs_dirent_lock; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ciextern struct kmem_cache *configfs_dir_cachep; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ciextern int configfs_is_root(struct config_item *item); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ciextern struct inode * configfs_new_inode(umode_t mode, struct configfs_dirent *, struct super_block *); 698c2ecf20Sopenharmony_ciextern struct inode *configfs_create(struct dentry *, umode_t mode); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ciextern int configfs_create_file(struct config_item *, const struct configfs_attribute *); 728c2ecf20Sopenharmony_ciextern int configfs_create_bin_file(struct config_item *, 738c2ecf20Sopenharmony_ci const struct configfs_bin_attribute *); 748c2ecf20Sopenharmony_ciextern int configfs_make_dirent(struct configfs_dirent *, struct dentry *, 758c2ecf20Sopenharmony_ci void *, umode_t, int, struct configfs_fragment *); 768c2ecf20Sopenharmony_ciextern int configfs_dirent_is_ready(struct configfs_dirent *); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ciextern void configfs_hash_and_remove(struct dentry * dir, const char * name); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ciextern const unsigned char * configfs_get_name(struct configfs_dirent *sd); 818c2ecf20Sopenharmony_ciextern void configfs_drop_dentry(struct configfs_dirent *sd, struct dentry *parent); 828c2ecf20Sopenharmony_ciextern int configfs_setattr(struct dentry *dentry, struct iattr *iattr); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ciextern struct dentry *configfs_pin_fs(void); 858c2ecf20Sopenharmony_ciextern void configfs_release_fs(void); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ciextern const struct file_operations configfs_dir_operations; 888c2ecf20Sopenharmony_ciextern const struct file_operations configfs_file_operations; 898c2ecf20Sopenharmony_ciextern const struct file_operations configfs_bin_file_operations; 908c2ecf20Sopenharmony_ciextern const struct inode_operations configfs_dir_inode_operations; 918c2ecf20Sopenharmony_ciextern const struct inode_operations configfs_root_inode_operations; 928c2ecf20Sopenharmony_ciextern const struct inode_operations configfs_symlink_inode_operations; 938c2ecf20Sopenharmony_ciextern const struct dentry_operations configfs_dentry_ops; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ciextern int configfs_symlink(struct inode *dir, struct dentry *dentry, 968c2ecf20Sopenharmony_ci const char *symname); 978c2ecf20Sopenharmony_ciextern int configfs_unlink(struct inode *dir, struct dentry *dentry); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ciint configfs_create_link(struct configfs_dirent *target, struct dentry *parent, 1008c2ecf20Sopenharmony_ci struct dentry *dentry, char *body); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic inline struct config_item * to_item(struct dentry * dentry) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci struct configfs_dirent * sd = dentry->d_fsdata; 1058c2ecf20Sopenharmony_ci return ((struct config_item *) sd->s_element); 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic inline struct configfs_attribute * to_attr(struct dentry * dentry) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci struct configfs_dirent * sd = dentry->d_fsdata; 1118c2ecf20Sopenharmony_ci return ((struct configfs_attribute *) sd->s_element); 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic inline struct configfs_bin_attribute *to_bin_attr(struct dentry *dentry) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci struct configfs_attribute *attr = to_attr(dentry); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci return container_of(attr, struct configfs_bin_attribute, cb_attr); 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic inline struct config_item *configfs_get_config_item(struct dentry *dentry) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci struct config_item * item = NULL; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci spin_lock(&dentry->d_lock); 1268c2ecf20Sopenharmony_ci if (!d_unhashed(dentry)) { 1278c2ecf20Sopenharmony_ci struct configfs_dirent * sd = dentry->d_fsdata; 1288c2ecf20Sopenharmony_ci item = config_item_get(sd->s_element); 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci spin_unlock(&dentry->d_lock); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci return item; 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic inline void release_configfs_dirent(struct configfs_dirent * sd) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci if (!(sd->s_type & CONFIGFS_ROOT)) { 1388c2ecf20Sopenharmony_ci kfree(sd->s_iattr); 1398c2ecf20Sopenharmony_ci put_fragment(sd->s_frag); 1408c2ecf20Sopenharmony_ci kmem_cache_free(configfs_dir_cachep, sd); 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic inline struct configfs_dirent * configfs_get(struct configfs_dirent * sd) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci if (sd) { 1478c2ecf20Sopenharmony_ci WARN_ON(!atomic_read(&sd->s_count)); 1488c2ecf20Sopenharmony_ci atomic_inc(&sd->s_count); 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci return sd; 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cistatic inline void configfs_put(struct configfs_dirent * sd) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci WARN_ON(!atomic_read(&sd->s_count)); 1568c2ecf20Sopenharmony_ci if (atomic_dec_and_test(&sd->s_count)) 1578c2ecf20Sopenharmony_ci release_configfs_dirent(sd); 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 160