@@ -185,50 +185,6 @@ struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir)
185185 return ret == - ENOENT ? NULL : ERR_PTR (ret );
186186}
187187
188- /*
189- * Look up @cell in a dynroot directory. This is a substitution for the
190- * local cell name for the net namespace.
191- */
192- static struct dentry * afs_lookup_atcell (struct dentry * dentry )
193- {
194- struct afs_cell * cell ;
195- struct afs_net * net = afs_d2net (dentry );
196- struct dentry * ret ;
197- char * name ;
198- int len ;
199-
200- if (!net -> ws_cell )
201- return ERR_PTR (- ENOENT );
202-
203- ret = ERR_PTR (- ENOMEM );
204- name = kmalloc (AFS_MAXCELLNAME + 1 , GFP_KERNEL );
205- if (!name )
206- goto out_p ;
207-
208- down_read (& net -> cells_lock );
209- cell = net -> ws_cell ;
210- if (cell ) {
211- len = cell -> name_len ;
212- memcpy (name , cell -> name , len + 1 );
213- }
214- up_read (& net -> cells_lock );
215-
216- ret = ERR_PTR (- ENOENT );
217- if (!cell )
218- goto out_n ;
219-
220- ret = lookup_one_len (name , dentry -> d_parent , len );
221-
222- /* We don't want to d_add() the @cell dentry here as we don't want to
223- * the cached dentry to hide changes to the local cell name.
224- */
225-
226- out_n :
227- kfree (name );
228- out_p :
229- return ret ;
230- }
231-
232188/*
233189 * Look up an entry in a dynroot directory.
234190 */
@@ -247,10 +203,6 @@ static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentr
247203 return ERR_PTR (- ENAMETOOLONG );
248204 }
249205
250- if (dentry -> d_name .len == 5 &&
251- memcmp (dentry -> d_name .name , "@cell" , 5 ) == 0 )
252- return afs_lookup_atcell (dentry );
253-
254206 return d_splice_alias (afs_try_auto_mntpt (dentry , dir ), dentry );
255207}
256208
@@ -271,7 +223,8 @@ const struct dentry_operations afs_dynroot_dentry_operations = {
271223int afs_dynroot_mkdir (struct afs_net * net , struct afs_cell * cell )
272224{
273225 struct super_block * sb = net -> dynroot_sb ;
274- struct dentry * root , * subdir ;
226+ struct dentry * root , * subdir , * dsubdir ;
227+ char * dotname = cell -> name - 1 ;
275228 int ret ;
276229
277230 if (!sb || atomic_read (& sb -> s_active ) == 0 )
@@ -286,47 +239,185 @@ int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell)
286239 goto unlock ;
287240 }
288241
289- /* Note that we're retaining an extra ref on the dentry */
242+ dsubdir = lookup_one_len (dotname , root , cell -> name_len + 1 );
243+ if (IS_ERR (dsubdir )) {
244+ ret = PTR_ERR (dsubdir );
245+ dput (subdir );
246+ goto unlock ;
247+ }
248+
249+ /* Note that we're retaining extra refs on the dentries. */
290250 subdir -> d_fsdata = (void * )1UL ;
251+ dsubdir -> d_fsdata = (void * )1UL ;
291252 ret = 0 ;
292253unlock :
293254 inode_unlock (root -> d_inode );
294255 return ret ;
295256}
296257
258+ static void afs_dynroot_rm_one_dir (struct dentry * root , const char * name , size_t name_len )
259+ {
260+ struct dentry * subdir ;
261+
262+ /* Don't want to trigger a lookup call, which will re-add the cell */
263+ subdir = try_lookup_one_len (name , root , name_len );
264+ if (IS_ERR_OR_NULL (subdir )) {
265+ _debug ("lookup %ld" , PTR_ERR (subdir ));
266+ return ;
267+ }
268+
269+ _debug ("rmdir %pd %u" , subdir , d_count (subdir ));
270+
271+ if (subdir -> d_fsdata ) {
272+ _debug ("unpin %u" , d_count (subdir ));
273+ subdir -> d_fsdata = NULL ;
274+ dput (subdir );
275+ }
276+ dput (subdir );
277+ }
278+
297279/*
298280 * Remove a manually added cell mount directory.
299281 * - The caller must hold net->proc_cells_lock
300282 */
301283void afs_dynroot_rmdir (struct afs_net * net , struct afs_cell * cell )
302284{
303285 struct super_block * sb = net -> dynroot_sb ;
304- struct dentry * root , * subdir ;
286+ char * dotname = cell -> name - 1 ;
305287
306288 if (!sb || atomic_read (& sb -> s_active ) == 0 )
307289 return ;
308290
309- root = sb -> s_root ;
310- inode_lock (root -> d_inode );
291+ inode_lock (sb -> s_root -> d_inode );
292+ afs_dynroot_rm_one_dir (sb -> s_root , cell -> name , cell -> name_len );
293+ afs_dynroot_rm_one_dir (sb -> s_root , dotname , cell -> name_len + 1 );
294+ inode_unlock (sb -> s_root -> d_inode );
295+ _leave ("" );
296+ }
311297
312- /* Don't want to trigger a lookup call, which will re-add the cell */
313- subdir = try_lookup_one_len (cell -> name , root , cell -> name_len );
314- if (IS_ERR_OR_NULL (subdir )) {
315- _debug ("lookup %ld" , PTR_ERR (subdir ));
316- goto no_dentry ;
298+ static void afs_atcell_delayed_put_cell (void * arg )
299+ {
300+ struct afs_cell * cell = arg ;
301+
302+ afs_put_cell (cell , afs_cell_trace_put_atcell );
303+ }
304+
305+ /*
306+ * Read @cell or .@cell symlinks.
307+ */
308+ static const char * afs_atcell_get_link (struct dentry * dentry , struct inode * inode ,
309+ struct delayed_call * done )
310+ {
311+ struct afs_vnode * vnode = AFS_FS_I (inode );
312+ struct afs_cell * cell ;
313+ struct afs_net * net = afs_i2net (inode );
314+ const char * name ;
315+ bool dotted = vnode -> fid .vnode == 3 ;
316+
317+ if (!net -> ws_cell )
318+ return ERR_PTR (- ENOENT );
319+
320+ down_read (& net -> cells_lock );
321+
322+ cell = net -> ws_cell ;
323+ if (dotted )
324+ name = cell -> name - 1 ;
325+ else
326+ name = cell -> name ;
327+ afs_get_cell (cell , afs_cell_trace_get_atcell );
328+ set_delayed_call (done , afs_atcell_delayed_put_cell , cell );
329+
330+ up_read (& net -> cells_lock );
331+ return name ;
332+ }
333+
334+ static const struct inode_operations afs_atcell_inode_operations = {
335+ .get_link = afs_atcell_get_link ,
336+ };
337+
338+ /*
339+ * Look up @cell or .@cell in a dynroot directory. This is a substitution for
340+ * the local cell name for the net namespace.
341+ */
342+ static struct dentry * afs_dynroot_create_symlink (struct dentry * root , const char * name )
343+ {
344+ struct afs_vnode * vnode ;
345+ struct afs_fid fid = { .vnode = 2 , .unique = 1 , };
346+ struct dentry * dentry ;
347+ struct inode * inode ;
348+
349+ if (name [0 ] == '.' )
350+ fid .vnode = 3 ;
351+
352+ dentry = d_alloc_name (root , name );
353+ if (!dentry )
354+ return ERR_PTR (- ENOMEM );
355+
356+ inode = iget5_locked (dentry -> d_sb , fid .vnode ,
357+ afs_iget5_pseudo_test , afs_iget5_pseudo_set , & fid );
358+ if (!inode ) {
359+ dput (dentry );
360+ return ERR_PTR (- ENOMEM );
317361 }
318362
319- _debug ( "rmdir %pd %u" , subdir , d_count ( subdir ) );
363+ vnode = AFS_FS_I ( inode );
320364
321- if (subdir -> d_fsdata ) {
322- _debug ("unpin %u" , d_count (subdir ));
323- subdir -> d_fsdata = NULL ;
324- dput (subdir );
365+ /* there shouldn't be an existing inode */
366+ if (WARN_ON_ONCE (!(inode -> i_state & I_NEW ))) {
367+ iput (inode );
368+ dput (dentry );
369+ return ERR_PTR (- EIO );
325370 }
326- dput (subdir );
327- no_dentry :
371+
372+ netfs_inode_init (& vnode -> netfs , NULL , false);
373+ simple_inode_init_ts (inode );
374+ set_nlink (inode , 1 );
375+ inode -> i_size = 0 ;
376+ inode -> i_mode = S_IFLNK | 0555 ;
377+ inode -> i_op = & afs_atcell_inode_operations ;
378+ inode -> i_uid = GLOBAL_ROOT_UID ;
379+ inode -> i_gid = GLOBAL_ROOT_GID ;
380+ inode -> i_blocks = 0 ;
381+ inode -> i_generation = 0 ;
382+ inode -> i_flags |= S_NOATIME ;
383+
384+ unlock_new_inode (inode );
385+ d_splice_alias (inode , dentry );
386+ return dentry ;
387+ }
388+
389+ /*
390+ * Create @cell and .@cell symlinks.
391+ */
392+ static int afs_dynroot_symlink (struct afs_net * net )
393+ {
394+ struct super_block * sb = net -> dynroot_sb ;
395+ struct dentry * root , * symlink , * dsymlink ;
396+ int ret ;
397+
398+ /* Let the ->lookup op do the creation */
399+ root = sb -> s_root ;
400+ inode_lock (root -> d_inode );
401+ symlink = afs_dynroot_create_symlink (root , "@cell" );
402+ if (IS_ERR (symlink )) {
403+ ret = PTR_ERR (symlink );
404+ goto unlock ;
405+ }
406+
407+ dsymlink = afs_dynroot_create_symlink (root , ".@cell" );
408+ if (IS_ERR (dsymlink )) {
409+ ret = PTR_ERR (dsymlink );
410+ dput (symlink );
411+ goto unlock ;
412+ }
413+
414+ /* Note that we're retaining extra refs on the dentries. */
415+ symlink -> d_fsdata = (void * )1UL ;
416+ dsymlink -> d_fsdata = (void * )1UL ;
417+ ret = 0 ;
418+ unlock :
328419 inode_unlock (root -> d_inode );
329- _leave ( "" ) ;
420+ return ret ;
330421}
331422
332423/*
@@ -341,6 +432,10 @@ int afs_dynroot_populate(struct super_block *sb)
341432 mutex_lock (& net -> proc_cells_lock );
342433
343434 net -> dynroot_sb = sb ;
435+ ret = afs_dynroot_symlink (net );
436+ if (ret < 0 )
437+ goto error ;
438+
344439 hlist_for_each_entry (cell , & net -> proc_cells , proc_link ) {
345440 ret = afs_dynroot_mkdir (net , cell );
346441 if (ret < 0 )
0 commit comments