@@ -40,15 +40,105 @@ static DEFINE_MUTEX(eventfs_mutex);
4040 */
4141DEFINE_STATIC_SRCU (eventfs_srcu );
4242
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+
4352static struct dentry * eventfs_root_lookup (struct inode * dir ,
4453 struct dentry * dentry ,
4554 unsigned int flags );
4655static int dcache_dir_open_wrapper (struct inode * inode , struct file * file );
4756static int dcache_readdir_wrapper (struct file * file , struct dir_context * ctx );
4857static int eventfs_release (struct inode * inode , struct file * file );
4958
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+
50135static const struct inode_operations eventfs_root_dir_inode_operations = {
51136 .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 ,
52142};
53143
54144static const struct file_operations eventfs_file_operations = {
@@ -59,10 +149,30 @@ static const struct file_operations eventfs_file_operations = {
59149 .release = eventfs_release ,
60150};
61151
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+
62171/**
63172 * create_file - create a file in the tracefs filesystem
64173 * @name: the name of the file to create.
65174 * @mode: the permission that the file should have.
175+ * @attr: saved attributes changed by user
66176 * @parent: parent dentry for this file.
67177 * @data: something that the caller will want to get to later on.
68178 * @fop: struct file_operations that should be used for this file.
@@ -72,6 +182,7 @@ static const struct file_operations eventfs_file_operations = {
72182 * call.
73183 */
74184static struct dentry * create_file (const char * name , umode_t mode ,
185+ struct eventfs_attr * attr ,
75186 struct dentry * parent , void * data ,
76187 const struct file_operations * fop )
77188{
@@ -95,7 +206,10 @@ static struct dentry *create_file(const char *name, umode_t mode,
95206 if (unlikely (!inode ))
96207 return eventfs_failed_creating (dentry );
97208
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 ;
99213 inode -> i_fop = fop ;
100214 inode -> i_private = data ;
101215
@@ -108,27 +222,29 @@ static struct dentry *create_file(const char *name, umode_t mode,
108222
109223/**
110224 * 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
112226 * @parent: parent dentry for this file.
113227 *
114228 * This function will create a dentry for a directory represented by
115229 * a eventfs_inode.
116230 */
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 )
118232{
119233 struct tracefs_inode * ti ;
120234 struct dentry * dentry ;
121235 struct inode * inode ;
122236
123- dentry = eventfs_start_creating (name , parent );
237+ dentry = eventfs_start_creating (ei -> name , parent );
124238 if (IS_ERR (dentry ))
125239 return dentry ;
126240
127241 inode = tracefs_get_inode (dentry -> d_sb );
128242 if (unlikely (!inode ))
129243 return eventfs_failed_creating (dentry );
130244
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+
132248 inode -> i_op = & eventfs_root_dir_inode_operations ;
133249 inode -> i_fop = & eventfs_file_operations ;
134250
@@ -146,6 +262,7 @@ static void free_ei(struct eventfs_inode *ei)
146262{
147263 kfree_const (ei -> name );
148264 kfree (ei -> d_children );
265+ kfree (ei -> entry_attrs );
149266 kfree (ei );
150267}
151268
@@ -231,7 +348,7 @@ void eventfs_set_ei_status_free(struct tracefs_inode *ti, struct dentry *dentry)
231348/**
232349 * create_file_dentry - create a dentry for a file of an eventfs_inode
233350 * @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
235352 * @parent: The parent dentry of the created file.
236353 * @name: The name of the file to create
237354 * @mode: The mode of the file.
@@ -244,10 +361,12 @@ void eventfs_set_ei_status_free(struct tracefs_inode *ti, struct dentry *dentry)
244361 * just do a dget() on it and return. Otherwise create the dentry and attach it.
245362 */
246363static struct dentry *
247- create_file_dentry (struct eventfs_inode * ei , struct dentry * * e_dentry ,
364+ create_file_dentry (struct eventfs_inode * ei , int idx ,
248365 struct dentry * parent , const char * name , umode_t mode , void * data ,
249366 const struct file_operations * fops , bool lookup )
250367{
368+ struct eventfs_attr * attr = NULL ;
369+ struct dentry * * e_dentry = & ei -> d_children [idx ];
251370 struct dentry * dentry ;
252371 bool invalidate = false;
253372
@@ -264,13 +383,18 @@ create_file_dentry(struct eventfs_inode *ei, struct dentry **e_dentry,
264383 mutex_unlock (& eventfs_mutex );
265384 return * e_dentry ;
266385 }
386+
387+ /* ei->entry_attrs are protected by SRCU */
388+ if (ei -> entry_attrs )
389+ attr = & ei -> entry_attrs [idx ];
390+
267391 mutex_unlock (& eventfs_mutex );
268392
269393 /* The lookup already has the parent->d_inode locked */
270394 if (!lookup )
271395 inode_lock (parent -> d_inode );
272396
273- dentry = create_file (name , mode , parent , data , fops );
397+ dentry = create_file (name , mode , attr , parent , data , fops );
274398
275399 if (!lookup )
276400 inode_unlock (parent -> d_inode );
@@ -378,7 +502,7 @@ create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei,
378502 if (!lookup )
379503 inode_lock (parent -> d_inode );
380504
381- dentry = create_dir (ei -> name , parent );
505+ dentry = create_dir (ei , parent );
382506
383507 if (!lookup )
384508 inode_unlock (parent -> d_inode );
@@ -495,8 +619,7 @@ static struct dentry *eventfs_root_lookup(struct inode *dir,
495619 if (r <= 0 )
496620 continue ;
497621 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 ,
500623 fops , true);
501624 break ;
502625 }
@@ -629,8 +752,7 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file)
629752 r = entry -> callback (name , & mode , & cdata , & fops );
630753 if (r <= 0 )
631754 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);
634756 if (d ) {
635757 ret = add_dentries (& dentries , d , cnt );
636758 if (ret < 0 )
0 commit comments