xref: /linux/fs/afs/dynroot.c (revision 088e88be5a380cc4e81963a9a02815da465d144f)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* AFS dynamic root handling
3  *
4  * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7 
8 #include <linux/fs.h>
9 #include <linux/namei.h>
10 #include <linux/dns_resolver.h>
11 #include "internal.h"
12 
13 const struct file_operations afs_dynroot_file_operations = {
14 	.open		= dcache_dir_open,
15 	.release	= dcache_dir_close,
16 	.iterate_shared	= dcache_readdir,
17 	.llseek		= dcache_dir_lseek,
18 };
19 
20 /*
21  * Probe to see if a cell may exist.  This prevents positive dentries from
22  * being created unnecessarily.
23  */
24 static int afs_probe_cell_name(struct dentry *dentry)
25 {
26 	struct afs_cell *cell;
27 	struct afs_net *net = afs_d2net(dentry);
28 	const char *name = dentry->d_name.name;
29 	size_t len = dentry->d_name.len;
30 	int ret;
31 
32 	/* Names prefixed with a dot are R/W mounts. */
33 	if (name[0] == '.') {
34 		if (len == 1)
35 			return -EINVAL;
36 		name++;
37 		len--;
38 	}
39 
40 	cell = afs_lookup_cell_rcu(net, name, len);
41 	if (!IS_ERR(cell)) {
42 		afs_put_cell(net, cell);
43 		return 0;
44 	}
45 
46 	ret = dns_query(net->net, "afsdb", name, len, "srv=1",
47 			NULL, NULL, false);
48 	if (ret == -ENODATA)
49 		ret = -EDESTADDRREQ;
50 	return ret;
51 }
52 
53 /*
54  * Try to auto mount the mountpoint with pseudo directory, if the autocell
55  * operation is setted.
56  */
57 struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir)
58 {
59 	struct afs_vnode *vnode = AFS_FS_I(dir);
60 	struct inode *inode;
61 	int ret = -ENOENT;
62 
63 	_enter("%p{%pd}, {%llx:%llu}",
64 	       dentry, dentry, vnode->fid.vid, vnode->fid.vnode);
65 
66 	if (!test_bit(AFS_VNODE_AUTOCELL, &vnode->flags))
67 		goto out;
68 
69 	ret = afs_probe_cell_name(dentry);
70 	if (ret < 0)
71 		goto out;
72 
73 	inode = afs_iget_pseudo_dir(dir->i_sb, false);
74 	if (IS_ERR(inode)) {
75 		ret = PTR_ERR(inode);
76 		goto out;
77 	}
78 
79 	_leave("= %p", inode);
80 	return inode;
81 
82 out:
83 	_leave("= %d", ret);
84 	return ret == -ENOENT ? NULL : ERR_PTR(ret);
85 }
86 
87 /*
88  * Look up @cell in a dynroot directory.  This is a substitution for the
89  * local cell name for the net namespace.
90  */
91 static struct dentry *afs_lookup_atcell(struct dentry *dentry)
92 {
93 	struct afs_cell *cell;
94 	struct afs_net *net = afs_d2net(dentry);
95 	struct dentry *ret;
96 	unsigned int seq = 0;
97 	char *name;
98 	int len;
99 
100 	if (!net->ws_cell)
101 		return ERR_PTR(-ENOENT);
102 
103 	ret = ERR_PTR(-ENOMEM);
104 	name = kmalloc(AFS_MAXCELLNAME + 1, GFP_KERNEL);
105 	if (!name)
106 		goto out_p;
107 
108 	rcu_read_lock();
109 	do {
110 		read_seqbegin_or_lock(&net->cells_lock, &seq);
111 		cell = rcu_dereference_raw(net->ws_cell);
112 		if (cell) {
113 			len = cell->name_len;
114 			memcpy(name, cell->name, len + 1);
115 		}
116 	} while (need_seqretry(&net->cells_lock, seq));
117 	done_seqretry(&net->cells_lock, seq);
118 	rcu_read_unlock();
119 
120 	ret = ERR_PTR(-ENOENT);
121 	if (!cell)
122 		goto out_n;
123 
124 	ret = lookup_one_len(name, dentry->d_parent, len);
125 
126 	/* We don't want to d_add() the @cell dentry here as we don't want to
127 	 * the cached dentry to hide changes to the local cell name.
128 	 */
129 
130 out_n:
131 	kfree(name);
132 out_p:
133 	return ret;
134 }
135 
136 /*
137  * Look up an entry in a dynroot directory.
138  */
139 static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentry,
140 					 unsigned int flags)
141 {
142 	_enter("%pd", dentry);
143 
144 	ASSERTCMP(d_inode(dentry), ==, NULL);
145 
146 	if (dentry->d_name.len >= AFSNAMEMAX) {
147 		_leave(" = -ENAMETOOLONG");
148 		return ERR_PTR(-ENAMETOOLONG);
149 	}
150 
151 	if (dentry->d_name.len == 5 &&
152 	    memcmp(dentry->d_name.name, "@cell", 5) == 0)
153 		return afs_lookup_atcell(dentry);
154 
155 	return d_splice_alias(afs_try_auto_mntpt(dentry, dir), dentry);
156 }
157 
158 const struct inode_operations afs_dynroot_inode_operations = {
159 	.lookup		= afs_dynroot_lookup,
160 };
161 
162 /*
163  * Dirs in the dynamic root don't need revalidation.
164  */
165 static int afs_dynroot_d_revalidate(struct dentry *dentry, unsigned int flags)
166 {
167 	return 1;
168 }
169 
170 /*
171  * Allow the VFS to enquire as to whether a dentry should be unhashed (mustn't
172  * sleep)
173  * - called from dput() when d_count is going to 0.
174  * - return 1 to request dentry be unhashed, 0 otherwise
175  */
176 static int afs_dynroot_d_delete(const struct dentry *dentry)
177 {
178 	return d_really_is_positive(dentry);
179 }
180 
181 const struct dentry_operations afs_dynroot_dentry_operations = {
182 	.d_revalidate	= afs_dynroot_d_revalidate,
183 	.d_delete	= afs_dynroot_d_delete,
184 	.d_release	= afs_d_release,
185 	.d_automount	= afs_d_automount,
186 };
187 
188 /*
189  * Create a manually added cell mount directory.
190  * - The caller must hold net->proc_cells_lock
191  */
192 int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell)
193 {
194 	struct super_block *sb = net->dynroot_sb;
195 	struct dentry *root, *subdir;
196 	int ret;
197 
198 	if (!sb || atomic_read(&sb->s_active) == 0)
199 		return 0;
200 
201 	/* Let the ->lookup op do the creation */
202 	root = sb->s_root;
203 	inode_lock(root->d_inode);
204 	subdir = lookup_one_len(cell->name, root, cell->name_len);
205 	if (IS_ERR(subdir)) {
206 		ret = PTR_ERR(subdir);
207 		goto unlock;
208 	}
209 
210 	/* Note that we're retaining an extra ref on the dentry */
211 	subdir->d_fsdata = (void *)1UL;
212 	ret = 0;
213 unlock:
214 	inode_unlock(root->d_inode);
215 	return ret;
216 }
217 
218 /*
219  * Remove a manually added cell mount directory.
220  * - The caller must hold net->proc_cells_lock
221  */
222 void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell)
223 {
224 	struct super_block *sb = net->dynroot_sb;
225 	struct dentry *root, *subdir;
226 
227 	if (!sb || atomic_read(&sb->s_active) == 0)
228 		return;
229 
230 	root = sb->s_root;
231 	inode_lock(root->d_inode);
232 
233 	/* Don't want to trigger a lookup call, which will re-add the cell */
234 	subdir = try_lookup_one_len(cell->name, root, cell->name_len);
235 	if (IS_ERR_OR_NULL(subdir)) {
236 		_debug("lookup %ld", PTR_ERR(subdir));
237 		goto no_dentry;
238 	}
239 
240 	_debug("rmdir %pd %u", subdir, d_count(subdir));
241 
242 	if (subdir->d_fsdata) {
243 		_debug("unpin %u", d_count(subdir));
244 		subdir->d_fsdata = NULL;
245 		dput(subdir);
246 	}
247 	dput(subdir);
248 no_dentry:
249 	inode_unlock(root->d_inode);
250 	_leave("");
251 }
252 
253 /*
254  * Populate a newly created dynamic root with cell names.
255  */
256 int afs_dynroot_populate(struct super_block *sb)
257 {
258 	struct afs_cell *cell;
259 	struct afs_net *net = afs_sb2net(sb);
260 	int ret;
261 
262 	mutex_lock(&net->proc_cells_lock);
263 
264 	net->dynroot_sb = sb;
265 	hlist_for_each_entry(cell, &net->proc_cells, proc_link) {
266 		ret = afs_dynroot_mkdir(net, cell);
267 		if (ret < 0)
268 			goto error;
269 	}
270 
271 	ret = 0;
272 out:
273 	mutex_unlock(&net->proc_cells_lock);
274 	return ret;
275 
276 error:
277 	net->dynroot_sb = NULL;
278 	goto out;
279 }
280 
281 /*
282  * When a dynamic root that's in the process of being destroyed, depopulate it
283  * of pinned directories.
284  */
285 void afs_dynroot_depopulate(struct super_block *sb)
286 {
287 	struct afs_net *net = afs_sb2net(sb);
288 	struct dentry *root = sb->s_root, *subdir, *tmp;
289 
290 	/* Prevent more subdirs from being created */
291 	mutex_lock(&net->proc_cells_lock);
292 	if (net->dynroot_sb == sb)
293 		net->dynroot_sb = NULL;
294 	mutex_unlock(&net->proc_cells_lock);
295 
296 	inode_lock(root->d_inode);
297 
298 	/* Remove all the pins for dirs created for manually added cells */
299 	list_for_each_entry_safe(subdir, tmp, &root->d_subdirs, d_child) {
300 		if (subdir->d_fsdata) {
301 			subdir->d_fsdata = NULL;
302 			dput(subdir);
303 		}
304 	}
305 
306 	inode_unlock(root->d_inode);
307 }
308