@@ -185,50 +185,6 @@ struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir)
185
185
return ret == - ENOENT ? NULL : ERR_PTR (ret );
186
186
}
187
187
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
-
232
188
/*
233
189
* Look up an entry in a dynroot directory.
234
190
*/
@@ -247,10 +203,6 @@ static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentr
247
203
return ERR_PTR (- ENAMETOOLONG );
248
204
}
249
205
250
- if (dentry -> d_name .len == 5 &&
251
- memcmp (dentry -> d_name .name , "@cell" , 5 ) == 0 )
252
- return afs_lookup_atcell (dentry );
253
-
254
206
return d_splice_alias (afs_try_auto_mntpt (dentry , dir ), dentry );
255
207
}
256
208
@@ -271,7 +223,8 @@ const struct dentry_operations afs_dynroot_dentry_operations = {
271
223
int afs_dynroot_mkdir (struct afs_net * net , struct afs_cell * cell )
272
224
{
273
225
struct super_block * sb = net -> dynroot_sb ;
274
- struct dentry * root , * subdir ;
226
+ struct dentry * root , * subdir , * dsubdir ;
227
+ char * dotname = cell -> name - 1 ;
275
228
int ret ;
276
229
277
230
if (!sb || atomic_read (& sb -> s_active ) == 0 )
@@ -286,47 +239,185 @@ int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell)
286
239
goto unlock ;
287
240
}
288
241
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. */
290
250
subdir -> d_fsdata = (void * )1UL ;
251
+ dsubdir -> d_fsdata = (void * )1UL ;
291
252
ret = 0 ;
292
253
unlock :
293
254
inode_unlock (root -> d_inode );
294
255
return ret ;
295
256
}
296
257
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
+
297
279
/*
298
280
* Remove a manually added cell mount directory.
299
281
* - The caller must hold net->proc_cells_lock
300
282
*/
301
283
void afs_dynroot_rmdir (struct afs_net * net , struct afs_cell * cell )
302
284
{
303
285
struct super_block * sb = net -> dynroot_sb ;
304
- struct dentry * root , * subdir ;
286
+ char * dotname = cell -> name - 1 ;
305
287
306
288
if (!sb || atomic_read (& sb -> s_active ) == 0 )
307
289
return ;
308
290
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
+ }
311
297
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 );
317
361
}
318
362
319
- _debug ( "rmdir %pd %u" , subdir , d_count ( subdir ) );
363
+ vnode = AFS_FS_I ( inode );
320
364
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 );
325
370
}
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 :
328
419
inode_unlock (root -> d_inode );
329
- _leave ( "" ) ;
420
+ return ret ;
330
421
}
331
422
332
423
/*
@@ -341,6 +432,10 @@ int afs_dynroot_populate(struct super_block *sb)
341
432
mutex_lock (& net -> proc_cells_lock );
342
433
343
434
net -> dynroot_sb = sb ;
435
+ ret = afs_dynroot_symlink (net );
436
+ if (ret < 0 )
437
+ goto error ;
438
+
344
439
hlist_for_each_entry (cell , & net -> proc_cells , proc_link ) {
345
440
ret = afs_dynroot_mkdir (net , cell );
346
441
if (ret < 0 )
0 commit comments