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
));
79 netfs_inode_init(&vnode
->netfs
, NULL
, false);
81 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
83 inode
->i_op
= &afs_dynroot_inode_operations
;
84 inode
->i_fop
= &simple_dir_operations
;
86 inode
->i_op
= &afs_autocell_inode_operations
;
89 inode
->i_uid
= GLOBAL_ROOT_UID
;
90 inode
->i_gid
= GLOBAL_ROOT_GID
;
91 simple_inode_init_ts(inode
);
93 inode
->i_generation
= 0;
95 set_bit(AFS_VNODE_PSEUDODIR
, &vnode
->flags
);
97 set_bit(AFS_VNODE_MOUNTPOINT
, &vnode
->flags
);
98 inode
->i_flags
|= S_AUTOMOUNT
;
101 inode
->i_flags
|= S_NOATIME
;
102 unlock_new_inode(inode
);
103 _leave(" = %p", inode
);
108 * Probe to see if a cell may exist. This prevents positive dentries from
109 * being created unnecessarily.
111 static int afs_probe_cell_name(struct dentry
*dentry
)
113 struct afs_cell
*cell
;
114 struct afs_net
*net
= afs_d2net(dentry
);
115 const char *name
= dentry
->d_name
.name
;
116 size_t len
= dentry
->d_name
.len
;
120 /* Names prefixed with a dot are R/W mounts. */
121 if (name
[0] == '.') {
128 cell
= afs_find_cell(net
, name
, len
, afs_cell_trace_use_probe
);
130 afs_unuse_cell(net
, cell
, afs_cell_trace_unuse_probe
);
134 ret
= dns_query(net
->net
, "afsdb", name
, len
, "srv=1",
135 &result
, NULL
, false);
136 if (ret
== -ENODATA
|| ret
== -ENOKEY
|| ret
== 0)
138 if (ret
> 0 && ret
>= sizeof(struct dns_server_list_v1_header
)) {
139 struct dns_server_list_v1_header
*v1
= (void *)result
;
141 if (v1
->hdr
.zero
== 0 &&
142 v1
->hdr
.content
== DNS_PAYLOAD_IS_SERVER_LIST
&&
143 v1
->hdr
.version
== 1 &&
144 (v1
->status
!= DNS_LOOKUP_GOOD
&&
145 v1
->status
!= DNS_LOOKUP_GOOD_WITH_BAD
))
155 * Try to auto mount the mountpoint with pseudo directory, if the autocell
156 * operation is setted.
158 struct inode
*afs_try_auto_mntpt(struct dentry
*dentry
, struct inode
*dir
)
160 struct afs_vnode
*vnode
= AFS_FS_I(dir
);
164 _enter("%p{%pd}, {%llx:%llu}",
165 dentry
, dentry
, vnode
->fid
.vid
, vnode
->fid
.vnode
);
167 if (!test_bit(AFS_VNODE_AUTOCELL
, &vnode
->flags
))
170 ret
= afs_probe_cell_name(dentry
);
174 inode
= afs_iget_pseudo_dir(dir
->i_sb
, false);
176 ret
= PTR_ERR(inode
);
180 _leave("= %p", inode
);
185 return ret
== -ENOENT
? NULL
: ERR_PTR(ret
);
189 * Look up @cell in a dynroot directory. This is a substitution for the
190 * local cell name for the net namespace.
192 static struct dentry
*afs_lookup_atcell(struct dentry
*dentry
)
194 struct afs_cell
*cell
;
195 struct afs_net
*net
= afs_d2net(dentry
);
201 return ERR_PTR(-ENOENT
);
203 ret
= ERR_PTR(-ENOMEM
);
204 name
= kmalloc(AFS_MAXCELLNAME
+ 1, GFP_KERNEL
);
208 down_read(&net
->cells_lock
);
211 len
= cell
->name_len
;
212 memcpy(name
, cell
->name
, len
+ 1);
214 up_read(&net
->cells_lock
);
216 ret
= ERR_PTR(-ENOENT
);
220 ret
= lookup_one_len(name
, dentry
->d_parent
, len
);
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.
233 * Look up an entry in a dynroot directory.
235 static struct dentry
*afs_dynroot_lookup(struct inode
*dir
, struct dentry
*dentry
,
238 _enter("%pd", dentry
);
240 ASSERTCMP(d_inode(dentry
), ==, NULL
);
242 if (flags
& LOOKUP_CREATE
)
243 return ERR_PTR(-EOPNOTSUPP
);
245 if (dentry
->d_name
.len
>= AFSNAMEMAX
) {
246 _leave(" = -ENAMETOOLONG");
247 return ERR_PTR(-ENAMETOOLONG
);
250 if (dentry
->d_name
.len
== 5 &&
251 memcmp(dentry
->d_name
.name
, "@cell", 5) == 0)
252 return afs_lookup_atcell(dentry
);
254 return d_splice_alias(afs_try_auto_mntpt(dentry
, dir
), dentry
);
257 const struct inode_operations afs_dynroot_inode_operations
= {
258 .lookup
= afs_dynroot_lookup
,
261 const struct dentry_operations afs_dynroot_dentry_operations
= {
262 .d_delete
= always_delete_dentry
,
263 .d_release
= afs_d_release
,
264 .d_automount
= afs_d_automount
,
268 * Create a manually added cell mount directory.
269 * - The caller must hold net->proc_cells_lock
271 int afs_dynroot_mkdir(struct afs_net
*net
, struct afs_cell
*cell
)
273 struct super_block
*sb
= net
->dynroot_sb
;
274 struct dentry
*root
, *subdir
;
277 if (!sb
|| atomic_read(&sb
->s_active
) == 0)
280 /* Let the ->lookup op do the creation */
282 inode_lock(root
->d_inode
);
283 subdir
= lookup_one_len(cell
->name
, root
, cell
->name_len
);
284 if (IS_ERR(subdir
)) {
285 ret
= PTR_ERR(subdir
);
289 /* Note that we're retaining an extra ref on the dentry */
290 subdir
->d_fsdata
= (void *)1UL;
293 inode_unlock(root
->d_inode
);
298 * Remove a manually added cell mount directory.
299 * - The caller must hold net->proc_cells_lock
301 void afs_dynroot_rmdir(struct afs_net
*net
, struct afs_cell
*cell
)
303 struct super_block
*sb
= net
->dynroot_sb
;
304 struct dentry
*root
, *subdir
;
306 if (!sb
|| atomic_read(&sb
->s_active
) == 0)
310 inode_lock(root
->d_inode
);
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
));
319 _debug("rmdir %pd %u", subdir
, d_count(subdir
));
321 if (subdir
->d_fsdata
) {
322 _debug("unpin %u", d_count(subdir
));
323 subdir
->d_fsdata
= NULL
;
328 inode_unlock(root
->d_inode
);
333 * Populate a newly created dynamic root with cell names.
335 int afs_dynroot_populate(struct super_block
*sb
)
337 struct afs_cell
*cell
;
338 struct afs_net
*net
= afs_sb2net(sb
);
341 mutex_lock(&net
->proc_cells_lock
);
343 net
->dynroot_sb
= sb
;
344 hlist_for_each_entry(cell
, &net
->proc_cells
, proc_link
) {
345 ret
= afs_dynroot_mkdir(net
, cell
);
352 mutex_unlock(&net
->proc_cells_lock
);
356 net
->dynroot_sb
= NULL
;
361 * When a dynamic root that's in the process of being destroyed, depopulate it
362 * of pinned directories.
364 void afs_dynroot_depopulate(struct super_block
*sb
)
366 struct afs_net
*net
= afs_sb2net(sb
);
367 struct dentry
*root
= sb
->s_root
, *subdir
;
369 /* Prevent more subdirs from being created */
370 mutex_lock(&net
->proc_cells_lock
);
371 if (net
->dynroot_sb
== sb
)
372 net
->dynroot_sb
= NULL
;
373 mutex_unlock(&net
->proc_cells_lock
);
376 struct hlist_node
*n
;
377 inode_lock(root
->d_inode
);
379 /* Remove all the pins for dirs created for manually added cells */
380 hlist_for_each_entry_safe(subdir
, n
, &root
->d_children
, d_sib
) {
381 if (subdir
->d_fsdata
) {
382 subdir
->d_fsdata
= NULL
;
387 inode_unlock(root
->d_inode
);