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