hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/afs/volume.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* AFS volume management
23 *
34 * Copyright (C) 2002, 2007 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 License
8
- * as published by the Free Software Foundation; either version
9
- * 2 of the License, or (at your option) any later version.
106 */
117
128 #include <linux/kernel.h>
....@@ -16,12 +12,60 @@
1612 unsigned __read_mostly afs_volume_gc_delay = 10;
1713 unsigned __read_mostly afs_volume_record_life = 60 * 60;
1814
19
-static const char *const afs_voltypes[] = { "R/W", "R/O", "BAK" };
15
+/*
16
+ * Insert a volume into a cell. If there's an existing volume record, that is
17
+ * returned instead with a ref held.
18
+ */
19
+static struct afs_volume *afs_insert_volume_into_cell(struct afs_cell *cell,
20
+ struct afs_volume *volume)
21
+{
22
+ struct afs_volume *p;
23
+ struct rb_node *parent = NULL, **pp;
24
+
25
+ write_seqlock(&cell->volume_lock);
26
+
27
+ pp = &cell->volumes.rb_node;
28
+ while (*pp) {
29
+ parent = *pp;
30
+ p = rb_entry(parent, struct afs_volume, cell_node);
31
+ if (p->vid < volume->vid) {
32
+ pp = &(*pp)->rb_left;
33
+ } else if (p->vid > volume->vid) {
34
+ pp = &(*pp)->rb_right;
35
+ } else {
36
+ volume = afs_get_volume(p, afs_volume_trace_get_cell_insert);
37
+ goto found;
38
+ }
39
+ }
40
+
41
+ rb_link_node_rcu(&volume->cell_node, parent, pp);
42
+ rb_insert_color(&volume->cell_node, &cell->volumes);
43
+ hlist_add_head_rcu(&volume->proc_link, &cell->proc_volumes);
44
+
45
+found:
46
+ write_sequnlock(&cell->volume_lock);
47
+ return volume;
48
+
49
+}
50
+
51
+static void afs_remove_volume_from_cell(struct afs_volume *volume)
52
+{
53
+ struct afs_cell *cell = volume->cell;
54
+
55
+ if (!hlist_unhashed(&volume->proc_link)) {
56
+ trace_afs_volume(volume->vid, atomic_read(&volume->usage),
57
+ afs_volume_trace_remove);
58
+ write_seqlock(&cell->volume_lock);
59
+ hlist_del_rcu(&volume->proc_link);
60
+ rb_erase(&volume->cell_node, &cell->volumes);
61
+ write_sequnlock(&cell->volume_lock);
62
+ }
63
+}
2064
2165 /*
2266 * Allocate a volume record and load it up from a vldb record.
2367 */
24
-static struct afs_volume *afs_alloc_volume(struct afs_mount_params *params,
68
+static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params,
2569 struct afs_vldb_entry *vldb,
2670 unsigned long type_mask)
2771 {
....@@ -39,13 +83,13 @@
3983
4084 volume->vid = vldb->vid[params->type];
4185 volume->update_at = ktime_get_real_seconds() + afs_volume_record_life;
42
- volume->cell = afs_get_cell(params->cell);
86
+ volume->cell = afs_get_cell(params->cell, afs_cell_trace_get_vol);
4387 volume->type = params->type;
4488 volume->type_force = params->force;
4589 volume->name_len = vldb->name_len;
4690
4791 atomic_set(&volume->usage, 1);
48
- INIT_LIST_HEAD(&volume->proc_link);
92
+ INIT_HLIST_NODE(&volume->proc_link);
4993 rwlock_init(&volume->servers_lock);
5094 rwlock_init(&volume->cb_v_break_lock);
5195 memcpy(volume->name, vldb->name, vldb->name_len + 1);
....@@ -57,14 +101,34 @@
57101 }
58102
59103 refcount_set(&slist->usage, 1);
60
- volume->servers = slist;
104
+ rcu_assign_pointer(volume->servers, slist);
105
+ trace_afs_volume(volume->vid, 1, afs_volume_trace_alloc);
61106 return volume;
62107
63108 error_1:
64
- afs_put_cell(params->net, volume->cell);
109
+ afs_put_cell(volume->cell, afs_cell_trace_put_vol);
65110 kfree(volume);
66111 error_0:
67112 return ERR_PTR(ret);
113
+}
114
+
115
+/*
116
+ * Look up or allocate a volume record.
117
+ */
118
+static struct afs_volume *afs_lookup_volume(struct afs_fs_context *params,
119
+ struct afs_vldb_entry *vldb,
120
+ unsigned long type_mask)
121
+{
122
+ struct afs_volume *candidate, *volume;
123
+
124
+ candidate = afs_alloc_volume(params, vldb, type_mask);
125
+ if (IS_ERR(candidate))
126
+ return candidate;
127
+
128
+ volume = afs_insert_volume_into_cell(params->cell, candidate);
129
+ if (volume != candidate)
130
+ afs_put_volume(params->net, candidate, afs_volume_trace_put_cell_dup);
131
+ return volume;
68132 }
69133
70134 /*
....@@ -75,55 +139,19 @@
75139 const char *volname,
76140 size_t volnamesz)
77141 {
78
- struct afs_addr_cursor ac;
79
- struct afs_vldb_entry *vldb;
142
+ struct afs_vldb_entry *vldb = ERR_PTR(-EDESTADDRREQ);
143
+ struct afs_vl_cursor vc;
80144 int ret;
81145
82
- ret = afs_set_vl_cursor(&ac, cell);
83
- if (ret < 0)
84
- return ERR_PTR(ret);
146
+ if (!afs_begin_vlserver_operation(&vc, cell, key))
147
+ return ERR_PTR(-ERESTARTSYS);
85148
86
- while (afs_iterate_addresses(&ac)) {
87
- if (!test_bit(ac.index, &ac.alist->probed)) {
88
- ret = afs_vl_get_capabilities(cell->net, &ac, key);
89
- switch (ret) {
90
- case VL_SERVICE:
91
- clear_bit(ac.index, &ac.alist->yfs);
92
- set_bit(ac.index, &ac.alist->probed);
93
- ac.addr->srx_service = ret;
94
- break;
95
- case YFS_VL_SERVICE:
96
- set_bit(ac.index, &ac.alist->yfs);
97
- set_bit(ac.index, &ac.alist->probed);
98
- ac.addr->srx_service = ret;
99
- break;
100
- }
101
- }
102
-
103
- vldb = afs_vl_get_entry_by_name_u(cell->net, &ac, key,
104
- volname, volnamesz);
105
- switch (ac.error) {
106
- case 0:
107
- afs_end_cursor(&ac);
108
- return vldb;
109
- case -ECONNABORTED:
110
- ac.error = afs_abort_to_error(ac.abort_code);
111
- goto error;
112
- case -ENOMEM:
113
- case -ENONET:
114
- goto error;
115
- case -ENETUNREACH:
116
- case -EHOSTUNREACH:
117
- case -ECONNREFUSED:
118
- break;
119
- default:
120
- ac.error = -EIO;
121
- goto error;
122
- }
149
+ while (afs_select_vlserver(&vc)) {
150
+ vldb = afs_vl_get_entry_by_name_u(&vc, volname, volnamesz);
123151 }
124152
125
-error:
126
- return ERR_PTR(afs_end_cursor(&ac));
153
+ ret = afs_end_vlserver_operation(&vc);
154
+ return ret < 0 ? ERR_PTR(ret) : vldb;
127155 }
128156
129157 /*
....@@ -150,7 +178,7 @@
150178 * - Rule 3: If parent volume is R/W, then only mount R/W volume unless
151179 * explicitly told otherwise
152180 */
153
-struct afs_volume *afs_create_volume(struct afs_mount_params *params)
181
+struct afs_volume *afs_create_volume(struct afs_fs_context *params)
154182 {
155183 struct afs_vldb_entry *vldb;
156184 struct afs_volume *volume;
....@@ -180,7 +208,7 @@
180208 }
181209
182210 type_mask = 1UL << params->type;
183
- volume = afs_alloc_volume(params, vldb, type_mask);
211
+ volume = afs_lookup_volume(params, vldb, type_mask);
184212
185213 error:
186214 kfree(vldb);
....@@ -198,23 +226,42 @@
198226 ASSERTCMP(volume->cache, ==, NULL);
199227 #endif
200228
201
- afs_put_serverlist(net, volume->servers);
202
- afs_put_cell(net, volume->cell);
203
- kfree(volume);
229
+ afs_remove_volume_from_cell(volume);
230
+ afs_put_serverlist(net, rcu_access_pointer(volume->servers));
231
+ afs_put_cell(volume->cell, afs_cell_trace_put_vol);
232
+ trace_afs_volume(volume->vid, atomic_read(&volume->usage),
233
+ afs_volume_trace_free);
234
+ kfree_rcu(volume, rcu);
204235
205236 _leave(" [destroyed]");
206237 }
207238
208239 /*
209
- * Drop a reference on a volume record.
240
+ * Get a reference on a volume record.
210241 */
211
-void afs_put_volume(struct afs_cell *cell, struct afs_volume *volume)
242
+struct afs_volume *afs_get_volume(struct afs_volume *volume,
243
+ enum afs_volume_trace reason)
212244 {
213245 if (volume) {
214
- _enter("%s", volume->name);
246
+ int u = atomic_inc_return(&volume->usage);
247
+ trace_afs_volume(volume->vid, u, reason);
248
+ }
249
+ return volume;
250
+}
215251
216
- if (atomic_dec_and_test(&volume->usage))
217
- afs_destroy_volume(cell->net, volume);
252
+
253
+/*
254
+ * Drop a reference on a volume record.
255
+ */
256
+void afs_put_volume(struct afs_net *net, struct afs_volume *volume,
257
+ enum afs_volume_trace reason)
258
+{
259
+ if (volume) {
260
+ afs_volid_t vid = volume->vid;
261
+ int u = atomic_dec_return(&volume->usage);
262
+ trace_afs_volume(vid, u, reason);
263
+ if (u == 0)
264
+ afs_destroy_volume(net, volume);
218265 }
219266 }
220267
....@@ -230,10 +277,6 @@
230277 NULL, 0,
231278 volume, 0, true);
232279 #endif
233
-
234
- write_lock(&volume->cell->proc_lock);
235
- list_add_tail(&volume->proc_link, &volume->cell->proc_volumes);
236
- write_unlock(&volume->cell->proc_lock);
237280 }
238281
239282 /*
....@@ -242,10 +285,6 @@
242285 void afs_deactivate_volume(struct afs_volume *volume)
243286 {
244287 _enter("%s", volume->name);
245
-
246
- write_lock(&volume->cell->proc_lock);
247
- list_del_init(&volume->proc_link);
248
- write_unlock(&volume->cell->proc_lock);
249288
250289 #ifdef CONFIG_AFS_FSCACHE
251290 fscache_relinquish_cookie(volume->cache, NULL,
....@@ -271,7 +310,7 @@
271310 /* We look up an ID by passing it as a decimal string in the
272311 * operation's name parameter.
273312 */
274
- idsz = sprintf(idbuf, "%u", volume->vid);
313
+ idsz = sprintf(idbuf, "%llu", volume->vid);
275314
276315 vldb = afs_vl_lookup_vldb(volume->cell, key, idbuf, idsz);
277316 if (IS_ERR(vldb)) {
....@@ -298,17 +337,17 @@
298337 write_lock(&volume->servers_lock);
299338
300339 discard = new;
301
- old = volume->servers;
340
+ old = rcu_dereference_protected(volume->servers,
341
+ lockdep_is_held(&volume->servers_lock));
302342 if (afs_annotate_server_list(new, old)) {
303343 new->seq = volume->servers_seq + 1;
304
- volume->servers = new;
344
+ rcu_assign_pointer(volume->servers, new);
305345 smp_wmb();
306346 volume->servers_seq++;
307347 discard = old;
308348 }
309349
310350 volume->update_at = ktime_get_real_seconds() + afs_volume_record_life;
311
- clear_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags);
312351 write_unlock(&volume->servers_lock);
313352 ret = 0;
314353
....@@ -323,25 +362,27 @@
323362 /*
324363 * Make sure the volume record is up to date.
325364 */
326
-int afs_check_volume_status(struct afs_volume *volume, struct key *key)
365
+int afs_check_volume_status(struct afs_volume *volume, struct afs_operation *op)
327366 {
328
- time64_t now = ktime_get_real_seconds();
329367 int ret, retries = 0;
330368
331369 _enter("");
332370
333
- if (volume->update_at <= now)
334
- set_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags);
335
-
336371 retry:
337
- if (!test_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags) &&
338
- !test_bit(AFS_VOLUME_WAIT, &volume->flags)) {
339
- _leave(" = 0");
340
- return 0;
341
- }
372
+ if (test_bit(AFS_VOLUME_WAIT, &volume->flags))
373
+ goto wait;
374
+ if (volume->update_at <= ktime_get_real_seconds() ||
375
+ test_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags))
376
+ goto update;
377
+ _leave(" = 0");
378
+ return 0;
342379
380
+update:
343381 if (!test_and_set_bit_lock(AFS_VOLUME_UPDATING, &volume->flags)) {
344
- ret = afs_update_volume_status(volume, key);
382
+ clear_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags);
383
+ ret = afs_update_volume_status(volume, op->key);
384
+ if (ret < 0)
385
+ set_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags);
345386 clear_bit_unlock(AFS_VOLUME_WAIT, &volume->flags);
346387 clear_bit_unlock(AFS_VOLUME_UPDATING, &volume->flags);
347388 wake_up_bit(&volume->flags, AFS_VOLUME_WAIT);
....@@ -349,12 +390,15 @@
349390 return ret;
350391 }
351392
393
+wait:
352394 if (!test_bit(AFS_VOLUME_WAIT, &volume->flags)) {
353395 _leave(" = 0 [no wait]");
354396 return 0;
355397 }
356398
357
- ret = wait_on_bit(&volume->flags, AFS_VOLUME_WAIT, TASK_INTERRUPTIBLE);
399
+ ret = wait_on_bit(&volume->flags, AFS_VOLUME_WAIT,
400
+ (op->flags & AFS_OPERATION_UNINTR) ?
401
+ TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE);
358402 if (ret == -ERESTARTSYS) {
359403 _leave(" = %d", ret);
360404 return ret;