hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/fs/afs/dynroot.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* AFS dynamic root handling
23 *
34 * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
45 * Written by David Howells (dhowells@redhat.com)
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.
106 */
117
128 #include <linux/fs.h>
....@@ -14,12 +10,98 @@
1410 #include <linux/dns_resolver.h>
1511 #include "internal.h"
1612
17
-const 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
-};
13
+static atomic_t afs_autocell_ino;
14
+
15
+/*
16
+ * iget5() comparator for inode created by autocell operations
17
+ *
18
+ * These pseudo inodes don't match anything.
19
+ */
20
+static int afs_iget5_pseudo_test(struct inode *inode, void *opaque)
21
+{
22
+ return 0;
23
+}
24
+
25
+/*
26
+ * iget5() inode initialiser
27
+ */
28
+static int afs_iget5_pseudo_set(struct inode *inode, void *opaque)
29
+{
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;
33
+
34
+ vnode->volume = as->volume;
35
+ vnode->fid = *fid;
36
+ inode->i_ino = fid->vnode;
37
+ inode->i_generation = fid->unique;
38
+ return 0;
39
+}
40
+
41
+/*
42
+ * Create an inode for a dynamic root directory or an autocell dynamic
43
+ * automount dir.
44
+ */
45
+struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root)
46
+{
47
+ struct afs_super_info *as = AFS_FS_S(sb);
48
+ struct afs_vnode *vnode;
49
+ struct inode *inode;
50
+ struct afs_fid fid = {};
51
+
52
+ _enter("");
53
+
54
+ if (as->volume)
55
+ fid.vid = as->volume->vid;
56
+ if (root) {
57
+ fid.vnode = 1;
58
+ fid.unique = 1;
59
+ } else {
60
+ fid.vnode = atomic_inc_return(&afs_autocell_ino);
61
+ fid.unique = 0;
62
+ }
63
+
64
+ inode = iget5_locked(sb, fid.vnode,
65
+ afs_iget5_pseudo_test, afs_iget5_pseudo_set, &fid);
66
+ if (!inode) {
67
+ _leave(" = -ENOMEM");
68
+ return ERR_PTR(-ENOMEM);
69
+ }
70
+
71
+ _debug("GOT INODE %p { ino=%lu, vl=%llx, vn=%llx, u=%x }",
72
+ inode, inode->i_ino, fid.vid, fid.vnode, fid.unique);
73
+
74
+ vnode = AFS_FS_I(inode);
75
+
76
+ /* there shouldn't be an existing inode */
77
+ BUG_ON(!(inode->i_state & I_NEW));
78
+
79
+ inode->i_size = 0;
80
+ inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
81
+ if (root) {
82
+ inode->i_op = &afs_dynroot_inode_operations;
83
+ inode->i_fop = &simple_dir_operations;
84
+ } else {
85
+ inode->i_op = &afs_autocell_inode_operations;
86
+ }
87
+ set_nlink(inode, 2);
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);
91
+ inode->i_blocks = 0;
92
+ inode->i_generation = 0;
93
+
94
+ set_bit(AFS_VNODE_PSEUDODIR, &vnode->flags);
95
+ if (!root) {
96
+ set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags);
97
+ inode->i_flags |= S_AUTOMOUNT;
98
+ }
99
+
100
+ inode->i_flags |= S_NOATIME;
101
+ unlock_new_inode(inode);
102
+ _leave(" = %p", inode);
103
+ return inode;
104
+}
23105
24106 /*
25107 * Probe to see if a cell may exist. This prevents positive dentries from
....@@ -28,6 +110,7 @@
28110 static int afs_probe_cell_name(struct dentry *dentry)
29111 {
30112 struct afs_cell *cell;
113
+ struct afs_net *net = afs_d2net(dentry);
31114 const char *name = dentry->d_name.name;
32115 size_t len = dentry->d_name.len;
33116 int ret;
....@@ -40,13 +123,14 @@
40123 len--;
41124 }
42125
43
- cell = afs_lookup_cell_rcu(afs_d2net(dentry), name, len);
126
+ cell = afs_find_cell(net, name, len, afs_cell_trace_use_probe);
44127 if (!IS_ERR(cell)) {
45
- afs_put_cell(afs_d2net(dentry), cell);
128
+ afs_unuse_cell(net, cell, afs_cell_trace_unuse_probe);
46129 return 0;
47130 }
48131
49
- ret = dns_query("afsdb", name, len, "", NULL, NULL);
132
+ ret = dns_query(net->net, "afsdb", name, len, "srv=1",
133
+ NULL, NULL, false);
50134 if (ret == -ENODATA)
51135 ret = -EDESTADDRREQ;
52136 return ret;
....@@ -62,7 +146,7 @@
62146 struct inode *inode;
63147 int ret = -ENOENT;
64148
65
- _enter("%p{%pd}, {%x:%u}",
149
+ _enter("%p{%pd}, {%llx:%llu}",
66150 dentry, dentry, vnode->fid.vid, vnode->fid.vnode);
67151
68152 if (!test_bit(AFS_VNODE_AUTOCELL, &vnode->flags))
....@@ -95,7 +179,6 @@
95179 struct afs_cell *cell;
96180 struct afs_net *net = afs_d2net(dentry);
97181 struct dentry *ret;
98
- unsigned int seq = 0;
99182 char *name;
100183 int len;
101184
....@@ -107,17 +190,13 @@
107190 if (!name)
108191 goto out_p;
109192
110
- rcu_read_lock();
111
- do {
112
- read_seqbegin_or_lock(&net->cells_lock, &seq);
113
- cell = rcu_dereference_raw(net->ws_cell);
114
- if (cell) {
115
- len = cell->name_len;
116
- memcpy(name, cell->name, len + 1);
117
- }
118
- } while (need_seqretry(&net->cells_lock, seq));
119
- done_seqretry(&net->cells_lock, seq);
120
- rcu_read_unlock();
193
+ down_read(&net->cells_lock);
194
+ cell = net->ws_cell;
195
+ if (cell) {
196
+ len = cell->name_len;
197
+ memcpy(name, cell->name, len + 1);
198
+ }
199
+ up_read(&net->cells_lock);
121200
122201 ret = ERR_PTR(-ENOENT);
123202 if (!cell)
....@@ -264,8 +343,7 @@
264343 struct afs_net *net = afs_sb2net(sb);
265344 int ret;
266345
267
- if (mutex_lock_interruptible(&net->proc_cells_lock) < 0)
268
- return -ERESTARTSYS;
346
+ mutex_lock(&net->proc_cells_lock);
269347
270348 net->dynroot_sb = sb;
271349 hlist_for_each_entry(cell, &net->proc_cells, proc_link) {