@@ -40,15 +40,105 @@ static DEFINE_MUTEX(eventfs_mutex);
40
40
*/
41
41
DEFINE_STATIC_SRCU (eventfs_srcu );
42
42
43
+ /* Mode is unsigned short, use the upper bits for flags */
44
+ enum {
45
+ EVENTFS_SAVE_MODE = BIT (16 ),
46
+ EVENTFS_SAVE_UID = BIT (17 ),
47
+ EVENTFS_SAVE_GID = BIT (18 ),
48
+ };
49
+
50
+ #define EVENTFS_MODE_MASK (EVENTFS_SAVE_MODE - 1)
51
+
43
52
static struct dentry * eventfs_root_lookup (struct inode * dir ,
44
53
struct dentry * dentry ,
45
54
unsigned int flags );
46
55
static int dcache_dir_open_wrapper (struct inode * inode , struct file * file );
47
56
static int dcache_readdir_wrapper (struct file * file , struct dir_context * ctx );
48
57
static int eventfs_release (struct inode * inode , struct file * file );
49
58
59
+ static void update_attr (struct eventfs_attr * attr , struct iattr * iattr )
60
+ {
61
+ unsigned int ia_valid = iattr -> ia_valid ;
62
+
63
+ if (ia_valid & ATTR_MODE ) {
64
+ attr -> mode = (attr -> mode & ~EVENTFS_MODE_MASK ) |
65
+ (iattr -> ia_mode & EVENTFS_MODE_MASK ) |
66
+ EVENTFS_SAVE_MODE ;
67
+ }
68
+ if (ia_valid & ATTR_UID ) {
69
+ attr -> mode |= EVENTFS_SAVE_UID ;
70
+ attr -> uid = iattr -> ia_uid ;
71
+ }
72
+ if (ia_valid & ATTR_GID ) {
73
+ attr -> mode |= EVENTFS_SAVE_GID ;
74
+ attr -> gid = iattr -> ia_gid ;
75
+ }
76
+ }
77
+
78
+ static int eventfs_set_attr (struct mnt_idmap * idmap , struct dentry * dentry ,
79
+ struct iattr * iattr )
80
+ {
81
+ const struct eventfs_entry * entry ;
82
+ struct eventfs_inode * ei ;
83
+ const char * name ;
84
+ int ret ;
85
+
86
+ mutex_lock (& eventfs_mutex );
87
+ ei = dentry -> d_fsdata ;
88
+ /* The LSB is set when the eventfs_inode is being freed */
89
+ if (((unsigned long )ei & 1UL ) || ei -> is_freed ) {
90
+ /* Do not allow changes if the event is about to be removed. */
91
+ mutex_unlock (& eventfs_mutex );
92
+ return - ENODEV ;
93
+ }
94
+
95
+ /* Preallocate the children mode array if necessary */
96
+ if (!(dentry -> d_inode -> i_mode & S_IFDIR )) {
97
+ if (!ei -> entry_attrs ) {
98
+ ei -> entry_attrs = kzalloc (sizeof (* ei -> entry_attrs ) * ei -> nr_entries ,
99
+ GFP_KERNEL );
100
+ if (!ei -> entry_attrs ) {
101
+ ret = - ENOMEM ;
102
+ goto out ;
103
+ }
104
+ }
105
+ }
106
+
107
+ ret = simple_setattr (idmap , dentry , iattr );
108
+ if (ret < 0 )
109
+ goto out ;
110
+
111
+ /*
112
+ * If this is a dir, then update the ei cache, only the file
113
+ * mode is saved in the ei->m_children, and the ownership is
114
+ * determined by the parent directory.
115
+ */
116
+ if (dentry -> d_inode -> i_mode & S_IFDIR ) {
117
+ update_attr (& ei -> attr , iattr );
118
+
119
+ } else {
120
+ name = dentry -> d_name .name ;
121
+
122
+ for (int i = 0 ; i < ei -> nr_entries ; i ++ ) {
123
+ entry = & ei -> entries [i ];
124
+ if (strcmp (name , entry -> name ) == 0 ) {
125
+ update_attr (& ei -> entry_attrs [i ], iattr );
126
+ break ;
127
+ }
128
+ }
129
+ }
130
+ out :
131
+ mutex_unlock (& eventfs_mutex );
132
+ return ret ;
133
+ }
134
+
50
135
static const struct inode_operations eventfs_root_dir_inode_operations = {
51
136
.lookup = eventfs_root_lookup ,
137
+ .setattr = eventfs_set_attr ,
138
+ };
139
+
140
+ static const struct inode_operations eventfs_file_inode_operations = {
141
+ .setattr = eventfs_set_attr ,
52
142
};
53
143
54
144
static const struct file_operations eventfs_file_operations = {
@@ -59,10 +149,30 @@ static const struct file_operations eventfs_file_operations = {
59
149
.release = eventfs_release ,
60
150
};
61
151
152
+ static void update_inode_attr (struct inode * inode , struct eventfs_attr * attr , umode_t mode )
153
+ {
154
+ if (!attr ) {
155
+ inode -> i_mode = mode ;
156
+ return ;
157
+ }
158
+
159
+ if (attr -> mode & EVENTFS_SAVE_MODE )
160
+ inode -> i_mode = attr -> mode & EVENTFS_MODE_MASK ;
161
+ else
162
+ inode -> i_mode = mode ;
163
+
164
+ if (attr -> mode & EVENTFS_SAVE_UID )
165
+ inode -> i_uid = attr -> uid ;
166
+
167
+ if (attr -> mode & EVENTFS_SAVE_GID )
168
+ inode -> i_gid = attr -> gid ;
169
+ }
170
+
62
171
/**
63
172
* create_file - create a file in the tracefs filesystem
64
173
* @name: the name of the file to create.
65
174
* @mode: the permission that the file should have.
175
+ * @attr: saved attributes changed by user
66
176
* @parent: parent dentry for this file.
67
177
* @data: something that the caller will want to get to later on.
68
178
* @fop: struct file_operations that should be used for this file.
@@ -72,6 +182,7 @@ static const struct file_operations eventfs_file_operations = {
72
182
* call.
73
183
*/
74
184
static struct dentry * create_file (const char * name , umode_t mode ,
185
+ struct eventfs_attr * attr ,
75
186
struct dentry * parent , void * data ,
76
187
const struct file_operations * fop )
77
188
{
@@ -95,7 +206,10 @@ static struct dentry *create_file(const char *name, umode_t mode,
95
206
if (unlikely (!inode ))
96
207
return eventfs_failed_creating (dentry );
97
208
98
- inode -> i_mode = mode ;
209
+ /* If the user updated the directory's attributes, use them */
210
+ update_inode_attr (inode , attr , mode );
211
+
212
+ inode -> i_op = & eventfs_file_inode_operations ;
99
213
inode -> i_fop = fop ;
100
214
inode -> i_private = data ;
101
215
@@ -108,27 +222,29 @@ static struct dentry *create_file(const char *name, umode_t mode,
108
222
109
223
/**
110
224
* create_dir - create a dir in the tracefs filesystem
111
- * @name : the name of the file to create.
225
+ * @ei : the eventfs_inode that represents the directory to create
112
226
* @parent: parent dentry for this file.
113
227
*
114
228
* This function will create a dentry for a directory represented by
115
229
* a eventfs_inode.
116
230
*/
117
- static struct dentry * create_dir (const char * name , struct dentry * parent )
231
+ static struct dentry * create_dir (struct eventfs_inode * ei , struct dentry * parent )
118
232
{
119
233
struct tracefs_inode * ti ;
120
234
struct dentry * dentry ;
121
235
struct inode * inode ;
122
236
123
- dentry = eventfs_start_creating (name , parent );
237
+ dentry = eventfs_start_creating (ei -> name , parent );
124
238
if (IS_ERR (dentry ))
125
239
return dentry ;
126
240
127
241
inode = tracefs_get_inode (dentry -> d_sb );
128
242
if (unlikely (!inode ))
129
243
return eventfs_failed_creating (dentry );
130
244
131
- inode -> i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO ;
245
+ /* If the user updated the directory's attributes, use them */
246
+ update_inode_attr (inode , & ei -> attr , S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO );
247
+
132
248
inode -> i_op = & eventfs_root_dir_inode_operations ;
133
249
inode -> i_fop = & eventfs_file_operations ;
134
250
@@ -146,6 +262,7 @@ static void free_ei(struct eventfs_inode *ei)
146
262
{
147
263
kfree_const (ei -> name );
148
264
kfree (ei -> d_children );
265
+ kfree (ei -> entry_attrs );
149
266
kfree (ei );
150
267
}
151
268
@@ -231,7 +348,7 @@ void eventfs_set_ei_status_free(struct tracefs_inode *ti, struct dentry *dentry)
231
348
/**
232
349
* create_file_dentry - create a dentry for a file of an eventfs_inode
233
350
* @ei: the eventfs_inode that the file will be created under
234
- * @e_dentry: a pointer to the d_children[] of the @ei
351
+ * @idx: the index into the d_children[] of the @ei
235
352
* @parent: The parent dentry of the created file.
236
353
* @name: The name of the file to create
237
354
* @mode: The mode of the file.
@@ -244,10 +361,12 @@ void eventfs_set_ei_status_free(struct tracefs_inode *ti, struct dentry *dentry)
244
361
* just do a dget() on it and return. Otherwise create the dentry and attach it.
245
362
*/
246
363
static struct dentry *
247
- create_file_dentry (struct eventfs_inode * ei , struct dentry * * e_dentry ,
364
+ create_file_dentry (struct eventfs_inode * ei , int idx ,
248
365
struct dentry * parent , const char * name , umode_t mode , void * data ,
249
366
const struct file_operations * fops , bool lookup )
250
367
{
368
+ struct eventfs_attr * attr = NULL ;
369
+ struct dentry * * e_dentry = & ei -> d_children [idx ];
251
370
struct dentry * dentry ;
252
371
bool invalidate = false;
253
372
@@ -264,13 +383,18 @@ create_file_dentry(struct eventfs_inode *ei, struct dentry **e_dentry,
264
383
mutex_unlock (& eventfs_mutex );
265
384
return * e_dentry ;
266
385
}
386
+
387
+ /* ei->entry_attrs are protected by SRCU */
388
+ if (ei -> entry_attrs )
389
+ attr = & ei -> entry_attrs [idx ];
390
+
267
391
mutex_unlock (& eventfs_mutex );
268
392
269
393
/* The lookup already has the parent->d_inode locked */
270
394
if (!lookup )
271
395
inode_lock (parent -> d_inode );
272
396
273
- dentry = create_file (name , mode , parent , data , fops );
397
+ dentry = create_file (name , mode , attr , parent , data , fops );
274
398
275
399
if (!lookup )
276
400
inode_unlock (parent -> d_inode );
@@ -378,7 +502,7 @@ create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei,
378
502
if (!lookup )
379
503
inode_lock (parent -> d_inode );
380
504
381
- dentry = create_dir (ei -> name , parent );
505
+ dentry = create_dir (ei , parent );
382
506
383
507
if (!lookup )
384
508
inode_unlock (parent -> d_inode );
@@ -495,8 +619,7 @@ static struct dentry *eventfs_root_lookup(struct inode *dir,
495
619
if (r <= 0 )
496
620
continue ;
497
621
ret = simple_lookup (dir , dentry , flags );
498
- create_file_dentry (ei , & ei -> d_children [i ],
499
- ei_dentry , name , mode , cdata ,
622
+ create_file_dentry (ei , i , ei_dentry , name , mode , cdata ,
500
623
fops , true);
501
624
break ;
502
625
}
@@ -629,8 +752,7 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file)
629
752
r = entry -> callback (name , & mode , & cdata , & fops );
630
753
if (r <= 0 )
631
754
continue ;
632
- d = create_file_dentry (ei , & ei -> d_children [i ],
633
- parent , name , mode , cdata , fops , false);
755
+ d = create_file_dentry (ei , i , parent , name , mode , cdata , fops , false);
634
756
if (d ) {
635
757
ret = add_dentries (& dentries , d , cnt );
636
758
if (ret < 0 )
0 commit comments