summaryrefslogtreecommitdiffstats
path: root/fs/sysfs/sysfs.h
blob: 718e2e123faef8ec0a8a2d5bc67ba8ad9aabe434 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
struct sysfs_elem_dir {
	struct kobject		* kobj;
};

struct sysfs_elem_symlink {
	struct kobject		* target_kobj;
};

struct sysfs_elem_attr {
	struct attribute	* attr;
};

struct sysfs_elem_bin_attr {
	struct bin_attribute	* bin_attr;
};

struct sysfs_dirent {
	atomic_t		s_count;
	struct sysfs_dirent	* s_parent;
	struct list_head	s_sibling;
	struct list_head	s_children;
	const char		* s_name;

	union {
		struct sysfs_elem_dir		dir;
		struct sysfs_elem_symlink	symlink;
		struct sysfs_elem_attr		attr;
		struct sysfs_elem_bin_attr	bin_attr;
	}			s_elem;

	int			s_type;
	umode_t			s_mode;
	ino_t			s_ino;
	struct dentry		* s_dentry;
	struct iattr		* s_iattr;
	atomic_t		s_event;
};

extern struct vfsmount * sysfs_mount;
extern struct kmem_cache *sysfs_dir_cachep;

extern void sysfs_delete_inode(struct inode *inode);
extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));

extern void release_sysfs_dirent(struct sysfs_dirent * sd);
extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode,
					     int type);
extern void sysfs_attach_dirent(struct sysfs_dirent *sd,
				struct sysfs_dirent *parent_sd,
				struct dentry *dentry);

extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
extern int sysfs_hash_and_remove(struct dentry * dir, const char * name);
extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);

extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
extern void sysfs_remove_subdir(struct dentry *);

extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);

extern spinlock_t sysfs_lock;
extern spinlock_t kobj_sysfs_assoc_lock;
extern struct rw_semaphore sysfs_rename_sem;
extern struct super_block * sysfs_sb;
extern const struct file_operations sysfs_dir_operations;
extern const struct file_operations sysfs_file_operations;
extern const struct file_operations bin_fops;
extern const struct inode_operations sysfs_dir_inode_operations;
extern const struct inode_operations sysfs_symlink_inode_operations;

struct sysfs_buffer {
	struct list_head		associates;
	size_t				count;
	loff_t				pos;
	char				* page;
	struct sysfs_ops		* ops;
	struct semaphore		sem;
	int				orphaned;
	int				needs_read_fill;
	int				event;
};

struct sysfs_buffer_collection {
	struct list_head	associates;
};

static inline struct kobject * to_kobj(struct dentry * dentry)
{
	struct sysfs_dirent * sd = dentry->d_fsdata;
	return sd->s_elem.dir.kobj;
}

static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
{
	struct kobject * kobj = NULL;

	spin_lock(&dcache_lock);
	if (!d_unhashed(dentry)) {
		struct sysfs_dirent * sd = dentry->d_fsdata;
		if (sd->s_type & SYSFS_KOBJ_LINK)
			kobj = kobject_get(sd->s_elem.symlink.target_kobj);
		else
			kobj = kobject_get(sd->s_elem.dir.kobj);
	}
	spin_unlock(&dcache_lock);

	return kobj;
}

static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
{
	if (sd) {
		WARN_ON(!atomic_read(&sd->s_count));
		atomic_inc(&sd->s_count);
	}
	return sd;
}

static inline void sysfs_put(struct sysfs_dirent * sd)
{
	if (sd && atomic_dec_and_test(&sd->s_count))
		release_sysfs_dirent(sd);
}

static inline int sysfs_is_shadowed_inode(struct inode *inode)
{
	return S_ISDIR(inode->i_mode) && inode->i_op->follow_link;
}