Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/configfs/item.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* item.c - library routines for handling generic config items
4
*
5
* Based on kobject:
6
* kobject is Copyright (c) 2002-2003 Patrick Mochel
7
*
8
* configfs Copyright (C) 2005 Oracle. All rights reserved.
9
*
10
* Please see the file Documentation/filesystems/configfs.rst for
11
* critical information about using the config_item interface.
12
*/
13
14
#include <linux/string.h>
15
#include <linux/module.h>
16
#include <linux/stat.h>
17
#include <linux/slab.h>
18
19
#include <linux/configfs.h>
20
21
22
static inline struct config_item *to_item(struct list_head *entry)
23
{
24
return container_of(entry, struct config_item, ci_entry);
25
}
26
27
/* Evil kernel */
28
static void config_item_release(struct kref *kref);
29
30
/**
31
* config_item_init - initialize item.
32
* @item: item in question.
33
*/
34
static void config_item_init(struct config_item *item)
35
{
36
kref_init(&item->ci_kref);
37
INIT_LIST_HEAD(&item->ci_entry);
38
}
39
40
/**
41
* config_item_set_name - Set the name of an item
42
* @item: item.
43
* @fmt: The vsnprintf()'s format string.
44
*
45
* If strlen(name) >= CONFIGFS_ITEM_NAME_LEN, then use a
46
* dynamically allocated string that @item->ci_name points to.
47
* Otherwise, use the static @item->ci_namebuf array.
48
*/
49
int config_item_set_name(struct config_item *item, const char *fmt, ...)
50
{
51
int limit = CONFIGFS_ITEM_NAME_LEN;
52
int need;
53
va_list args;
54
char *name;
55
56
/*
57
* First, try the static array
58
*/
59
va_start(args, fmt);
60
need = vsnprintf(item->ci_namebuf, limit, fmt, args);
61
va_end(args);
62
if (need < limit)
63
name = item->ci_namebuf;
64
else {
65
va_start(args, fmt);
66
name = kvasprintf(GFP_KERNEL, fmt, args);
67
va_end(args);
68
if (!name)
69
return -ENOMEM;
70
}
71
72
/* Free the old name, if necessary. */
73
if (item->ci_name && item->ci_name != item->ci_namebuf)
74
kfree(item->ci_name);
75
76
/* Now, set the new name */
77
item->ci_name = name;
78
return 0;
79
}
80
EXPORT_SYMBOL(config_item_set_name);
81
82
void config_item_init_type_name(struct config_item *item,
83
const char *name,
84
const struct config_item_type *type)
85
{
86
config_item_set_name(item, "%s", name);
87
item->ci_type = type;
88
config_item_init(item);
89
}
90
EXPORT_SYMBOL(config_item_init_type_name);
91
92
void config_group_init_type_name(struct config_group *group, const char *name,
93
const struct config_item_type *type)
94
{
95
config_item_set_name(&group->cg_item, "%s", name);
96
group->cg_item.ci_type = type;
97
config_group_init(group);
98
}
99
EXPORT_SYMBOL(config_group_init_type_name);
100
101
struct config_item *config_item_get(struct config_item *item)
102
{
103
if (item)
104
kref_get(&item->ci_kref);
105
return item;
106
}
107
EXPORT_SYMBOL(config_item_get);
108
109
struct config_item *config_item_get_unless_zero(struct config_item *item)
110
{
111
if (item && kref_get_unless_zero(&item->ci_kref))
112
return item;
113
return NULL;
114
}
115
EXPORT_SYMBOL(config_item_get_unless_zero);
116
117
static void config_item_cleanup(struct config_item *item)
118
{
119
const struct config_item_type *t = item->ci_type;
120
struct config_group *s = item->ci_group;
121
struct config_item *parent = item->ci_parent;
122
123
pr_debug("config_item %s: cleaning up\n", config_item_name(item));
124
if (item->ci_name != item->ci_namebuf)
125
kfree(item->ci_name);
126
item->ci_name = NULL;
127
if (t && t->ct_item_ops && t->ct_item_ops->release)
128
t->ct_item_ops->release(item);
129
if (s)
130
config_group_put(s);
131
if (parent)
132
config_item_put(parent);
133
}
134
135
static void config_item_release(struct kref *kref)
136
{
137
config_item_cleanup(container_of(kref, struct config_item, ci_kref));
138
}
139
140
/**
141
* config_item_put - decrement refcount for item.
142
* @item: item.
143
*
144
* Decrement the refcount, and if 0, call config_item_cleanup().
145
*/
146
void config_item_put(struct config_item *item)
147
{
148
if (item)
149
kref_put(&item->ci_kref, config_item_release);
150
}
151
EXPORT_SYMBOL(config_item_put);
152
153
/**
154
* config_group_init - initialize a group for use
155
* @group: config_group
156
*/
157
void config_group_init(struct config_group *group)
158
{
159
config_item_init(&group->cg_item);
160
INIT_LIST_HEAD(&group->cg_children);
161
INIT_LIST_HEAD(&group->default_groups);
162
}
163
EXPORT_SYMBOL(config_group_init);
164
165
/**
166
* config_group_find_item - search for item in group.
167
* @group: group we're looking in.
168
* @name: item's name.
169
*
170
* Iterate over @group->cg_list, looking for a matching config_item.
171
* If matching item is found take a reference and return the item.
172
* Caller must have locked group via @group->cg_subsys->su_mtx.
173
*/
174
struct config_item *config_group_find_item(struct config_group *group,
175
const char *name)
176
{
177
struct list_head *entry;
178
struct config_item *ret = NULL;
179
180
list_for_each(entry, &group->cg_children) {
181
struct config_item *item = to_item(entry);
182
if (config_item_name(item) &&
183
!strcmp(config_item_name(item), name)) {
184
ret = config_item_get(item);
185
break;
186
}
187
}
188
return ret;
189
}
190
EXPORT_SYMBOL(config_group_find_item);
191
192