1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* AFS dynamic root handling
4 * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
9 #include <linux/namei.h>
10 #include <linux/dns_resolver.h>
13 static atomic_t afs_autocell_ino
;
16 * iget5() comparator for inode created by autocell operations
18 * These pseudo inodes don't match anything.
20 static int afs_iget5_pseudo_test(struct inode
*inode
, void *opaque
)
26 * iget5() inode initialiser
28 static int afs_iget5_pseudo_set(struct inode
*inode
, void *opaque
)
30 struct afs_super_info
*as
= AFS_FS_S(inode
->i_sb
);
31 struct afs_vnode
*vnode
= AFS_FS_I(inode
);
32 struct afs_fid
*fid
= opaque
;
34 vnode
->volume
= as
->volume
;
36 inode
->i_ino
= fid
->vnode
;
37 inode
->i_generation
= fid
->unique
;
42 * Create an inode for a dynamic root directory or an autocell dynamic
45 struct inode
*afs_iget_pseudo_dir(struct super_block
*sb
, bool root
)
47 struct afs_super_info
*as
= AFS_FS_S(sb
);
48 struct afs_vnode
*vnode
;
50 struct afs_fid fid
= {};
55 fid
.vid
= as
->volume
->vid
;
60 fid
.vnode
= atomic_inc_return(&afs_autocell_ino
);
64 inode
= iget5_locked(sb
, fid
.vnode
,
65 afs_iget5_pseudo_test
, afs_iget5_pseudo_set
, &fid
);
68 return ERR_PTR(-ENOMEM
);
71 _debug("GOT INODE %p { ino=%lu, vl=%llx, vn=%llx, u=%x }",
72 inode
, inode
->i_ino
, fid
.vid
, fid
.vnode
, fid
.unique
);
74 vnode
= AFS_FS_I(inode
);
76 /* there shouldn't be an existing inode */
77 BUG_ON(!(inode
->i_state
& I_NEW
));
80 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
82 inode
->i_op
= &afs_dynroot_inode_operations
;
83 inode
->i_fop
= &simple_dir_operations
;
85 inode
->i_op
= &afs_autocell_inode_operations
;
88 inode
->i_uid
= GLOBAL_ROOT_UID
;
89 inode
->i_gid
= GLOBAL_ROOT_GID
;
90 inode
->i_ctime
= inode
->i_atime
= inode
->i_mtime
= current_time(inode
);
92 inode
->i_generation
= 0;
94 set_bit(AFS_VNODE_PSEUDODIR
, &vnode
->flags
);
96 set_bit(AFS_VNODE_MOUNTPOINT
, &vnode
->flags
);
97 inode
->i_flags
|= S_AUTOMOUNT
;
100 inode
->i_flags
|= S_NOATIME
;
101 unlock_new_inode(inode
);
102 _leave(" = %p", inode
);
107 * Probe to see if a cell may exist. This prevents positive dentries from
108 * being created unnecessarily.
110 static int afs_probe_cell_name(struct dentry
*dentry
)
112 struct afs_cell
*cell
;
113 struct afs_net
*net
= afs_d2net(dentry
);
114 const char *name
= dentry
->d_name
.name
;
115 size_t len
= dentry
->d_name
.len
;
118 /* Names prefixed with a dot are R/W mounts. */
119 if (name
[0] == '.') {
126 cell
= afs_lookup_cell_rcu(net
, name
, len
);
128 afs_put_cell(net
, cell
);
132 ret
= dns_query(net
->net
, "afsdb", name
, len
, "srv=1",
140 * Try to auto mount the mountpoint with pseudo directory, if the autocell
141 * operation is setted.
143 struct inode
*afs_try_auto_mntpt(struct dentry
*dentry
, struct inode
*dir
)
145 struct afs_vnode
*vnode
= AFS_FS_I(dir
);
149 _enter("%p{%pd}, {%llx:%llu}",
150 dentry
, dentry
, vnode
->fid
.vid
, vnode
->fid
.vnode
);
152 if (!test_bit(AFS_VNODE_AUTOCELL
, &vnode
->flags
))
155 ret
= afs_probe_cell_name(dentry
);
159 inode
= afs_iget_pseudo_dir(dir
->i_sb
, false);
161 ret
= PTR_ERR(inode
);
165 _leave("= %p", inode
);
170 return ret
== -ENOENT
? NULL
: ERR_PTR(ret
);
174 * Look up @cell in a dynroot directory. This is a substitution for the
175 * local cell name for the net namespace.
177 static struct dentry
*afs_lookup_atcell(struct dentry
*dentry
)
179 struct afs_cell
*cell
;
180 struct afs_net
*net
= afs_d2net(dentry
);
182 unsigned int seq
= 0;
187 return ERR_PTR(-ENOENT
);
189 ret
= ERR_PTR(-ENOMEM
);
190 name
= kmalloc(AFS_MAXCELLNAME
+ 1, GFP_KERNEL
);
196 read_seqbegin_or_lock(&net
->cells_lock
, &seq
);
197 cell
= rcu_dereference_raw(net
->ws_cell
);
199 len
= cell
->name_len
;
200 memcpy(name
, cell
->name
, len
+ 1);
202 } while (need_seqretry(&net
->cells_lock
, seq
));
203 done_seqretry(&net
->cells_lock
, seq
);
206 ret
= ERR_PTR(-ENOENT
);
210 ret
= lookup_one_len(name
, dentry
->d_parent
, len
);
212 /* We don't want to d_add() the @cell dentry here as we don't want to
213 * the cached dentry to hide changes to the local cell name.
223 * Look up an entry in a dynroot directory.
225 static struct dentry
*afs_dynroot_lookup(struct inode
*dir
, struct dentry
*dentry
,
228 _enter("%pd", dentry
);
230 ASSERTCMP(d_inode(dentry
), ==, NULL
);
232 if (flags
& LOOKUP_CREATE
)
233 return ERR_PTR(-EOPNOTSUPP
);
235 if (dentry
->d_name
.len
>= AFSNAMEMAX
) {
236 _leave(" = -ENAMETOOLONG");
237 return ERR_PTR(-ENAMETOOLONG
);
240 if (dentry
->d_name
.len
== 5 &&
241 memcmp(dentry
->d_name
.name
, "@cell", 5) == 0)
242 return afs_lookup_atcell(dentry
);
244 return d_splice_alias(afs_try_auto_mntpt(dentry
, dir
), dentry
);
247 const struct inode_operations afs_dynroot_inode_operations
= {
248 .lookup
= afs_dynroot_lookup
,
252 * Dirs in the dynamic root don't need revalidation.
254 static int afs_dynroot_d_revalidate(struct dentry
*dentry
, unsigned int flags
)
260 * Allow the VFS to enquire as to whether a dentry should be unhashed (mustn't
262 * - called from dput() when d_count is going to 0.
263 * - return 1 to request dentry be unhashed, 0 otherwise
265 static int afs_dynroot_d_delete(const struct dentry
*dentry
)
267 return d_really_is_positive(dentry
);
270 const struct dentry_operations afs_dynroot_dentry_operations
= {
271 .d_revalidate
= afs_dynroot_d_revalidate
,
272 .d_delete
= afs_dynroot_d_delete
,
273 .d_release
= afs_d_release
,
274 .d_automount
= afs_d_automount
,
278 * Create a manually added cell mount directory.
279 * - The caller must hold net->proc_cells_lock
281 int afs_dynroot_mkdir(struct afs_net
*net
, struct afs_cell
*cell
)
283 struct super_block
*sb
= net
->dynroot_sb
;
284 struct dentry
*root
, *subdir
;
287 if (!sb
|| atomic_read(&sb
->s_active
) == 0)
290 /* Let the ->lookup op do the creation */
292 inode_lock(root
->d_inode
);
293 subdir
= lookup_one_len(cell
->name
, root
, cell
->name_len
);
294 if (IS_ERR(subdir
)) {
295 ret
= PTR_ERR(subdir
);
299 /* Note that we're retaining an extra ref on the dentry */
300 subdir
->d_fsdata
= (void *)1UL;
303 inode_unlock(root
->d_inode
);
308 * Remove a manually added cell mount directory.
309 * - The caller must hold net->proc_cells_lock
311 void afs_dynroot_rmdir(struct afs_net
*net
, struct afs_cell
*cell
)
313 struct super_block
*sb
= net
->dynroot_sb
;
314 struct dentry
*root
, *subdir
;
316 if (!sb
|| atomic_read(&sb
->s_active
) == 0)
320 inode_lock(root
->d_inode
);
322 /* Don't want to trigger a lookup call, which will re-add the cell */
323 subdir
= try_lookup_one_len(cell
->name
, root
, cell
->name_len
);
324 if (IS_ERR_OR_NULL(subdir
)) {
325 _debug("lookup %ld", PTR_ERR(subdir
));
329 _debug("rmdir %pd %u", subdir
, d_count(subdir
));
331 if (subdir
->d_fsdata
) {
332 _debug("unpin %u", d_count(subdir
));
333 subdir
->d_fsdata
= NULL
;
338 inode_unlock(root
->d_inode
);
343 * Populate a newly created dynamic root with cell names.
345 int afs_dynroot_populate(struct super_block
*sb
)
347 struct afs_cell
*cell
;
348 struct afs_net
*net
= afs_sb2net(sb
);
351 mutex_lock(&net
->proc_cells_lock
);
353 net
->dynroot_sb
= sb
;
354 hlist_for_each_entry(cell
, &net
->proc_cells
, proc_link
) {
355 ret
= afs_dynroot_mkdir(net
, cell
);
362 mutex_unlock(&net
->proc_cells_lock
);
366 net
->dynroot_sb
= NULL
;
371 * When a dynamic root that's in the process of being destroyed, depopulate it
372 * of pinned directories.
374 void afs_dynroot_depopulate(struct super_block
*sb
)
376 struct afs_net
*net
= afs_sb2net(sb
);
377 struct dentry
*root
= sb
->s_root
, *subdir
, *tmp
;
379 /* Prevent more subdirs from being created */
380 mutex_lock(&net
->proc_cells_lock
);
381 if (net
->dynroot_sb
== sb
)
382 net
->dynroot_sb
= NULL
;
383 mutex_unlock(&net
->proc_cells_lock
);
385 inode_lock(root
->d_inode
);
387 /* Remove all the pins for dirs created for manually added cells */
388 list_for_each_entry_safe(subdir
, tmp
, &root
->d_subdirs
, d_child
) {
389 if (subdir
->d_fsdata
) {
390 subdir
->d_fsdata
= NULL
;
395 inode_unlock(root
->d_inode
);