]> asedeno.scripts.mit.edu Git - linux.git/blob - fs/afs/volume.c
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux.git] / fs / afs / volume.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* AFS volume management
3  *
4  * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7
8 #include <linux/kernel.h>
9 #include <linux/slab.h>
10 #include "internal.h"
11
12 unsigned __read_mostly afs_volume_gc_delay = 10;
13 unsigned __read_mostly afs_volume_record_life = 60 * 60;
14
15 static const char *const afs_voltypes[] = { "R/W", "R/O", "BAK" };
16
17 /*
18  * Allocate a volume record and load it up from a vldb record.
19  */
20 static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params,
21                                            struct afs_vldb_entry *vldb,
22                                            unsigned long type_mask)
23 {
24         struct afs_server_list *slist;
25         struct afs_volume *volume;
26         int ret = -ENOMEM, nr_servers = 0, i;
27
28         for (i = 0; i < vldb->nr_servers; i++)
29                 if (vldb->fs_mask[i] & type_mask)
30                         nr_servers++;
31
32         volume = kzalloc(sizeof(struct afs_volume), GFP_KERNEL);
33         if (!volume)
34                 goto error_0;
35
36         volume->vid             = vldb->vid[params->type];
37         volume->update_at       = ktime_get_real_seconds() + afs_volume_record_life;
38         volume->cell            = afs_get_cell(params->cell);
39         volume->type            = params->type;
40         volume->type_force      = params->force;
41         volume->name_len        = vldb->name_len;
42
43         atomic_set(&volume->usage, 1);
44         INIT_LIST_HEAD(&volume->proc_link);
45         rwlock_init(&volume->servers_lock);
46         rwlock_init(&volume->cb_v_break_lock);
47         memcpy(volume->name, vldb->name, vldb->name_len + 1);
48
49         slist = afs_alloc_server_list(params->cell, params->key, vldb, type_mask);
50         if (IS_ERR(slist)) {
51                 ret = PTR_ERR(slist);
52                 goto error_1;
53         }
54
55         refcount_set(&slist->usage, 1);
56         volume->servers = slist;
57         return volume;
58
59 error_1:
60         afs_put_cell(params->net, volume->cell);
61         kfree(volume);
62 error_0:
63         return ERR_PTR(ret);
64 }
65
66 /*
67  * Look up a VLDB record for a volume.
68  */
69 static struct afs_vldb_entry *afs_vl_lookup_vldb(struct afs_cell *cell,
70                                                  struct key *key,
71                                                  const char *volname,
72                                                  size_t volnamesz)
73 {
74         struct afs_vldb_entry *vldb = ERR_PTR(-EDESTADDRREQ);
75         struct afs_vl_cursor vc;
76         int ret;
77
78         if (!afs_begin_vlserver_operation(&vc, cell, key))
79                 return ERR_PTR(-ERESTARTSYS);
80
81         while (afs_select_vlserver(&vc)) {
82                 vldb = afs_vl_get_entry_by_name_u(&vc, volname, volnamesz);
83         }
84
85         ret = afs_end_vlserver_operation(&vc);
86         return ret < 0 ? ERR_PTR(ret) : vldb;
87 }
88
89 /*
90  * Look up a volume in the VL server and create a candidate volume record for
91  * it.
92  *
93  * The volume name can be one of the following:
94  *      "%[cell:]volume[.]"             R/W volume
95  *      "#[cell:]volume[.]"             R/O or R/W volume (rwparent=0),
96  *                                       or R/W (rwparent=1) volume
97  *      "%[cell:]volume.readonly"       R/O volume
98  *      "#[cell:]volume.readonly"       R/O volume
99  *      "%[cell:]volume.backup"         Backup volume
100  *      "#[cell:]volume.backup"         Backup volume
101  *
102  * The cell name is optional, and defaults to the current cell.
103  *
104  * See "The Rules of Mount Point Traversal" in Chapter 5 of the AFS SysAdmin
105  * Guide
106  * - Rule 1: Explicit type suffix forces access of that type or nothing
107  *           (no suffix, then use Rule 2 & 3)
108  * - Rule 2: If parent volume is R/O, then mount R/O volume by preference, R/W
109  *           if not available
110  * - Rule 3: If parent volume is R/W, then only mount R/W volume unless
111  *           explicitly told otherwise
112  */
113 struct afs_volume *afs_create_volume(struct afs_fs_context *params)
114 {
115         struct afs_vldb_entry *vldb;
116         struct afs_volume *volume;
117         unsigned long type_mask = 1UL << params->type;
118
119         vldb = afs_vl_lookup_vldb(params->cell, params->key,
120                                   params->volname, params->volnamesz);
121         if (IS_ERR(vldb))
122                 return ERR_CAST(vldb);
123
124         if (test_bit(AFS_VLDB_QUERY_ERROR, &vldb->flags)) {
125                 volume = ERR_PTR(vldb->error);
126                 goto error;
127         }
128
129         /* Make the final decision on the type we want */
130         volume = ERR_PTR(-ENOMEDIUM);
131         if (params->force) {
132                 if (!(vldb->flags & type_mask))
133                         goto error;
134         } else if (test_bit(AFS_VLDB_HAS_RO, &vldb->flags)) {
135                 params->type = AFSVL_ROVOL;
136         } else if (test_bit(AFS_VLDB_HAS_RW, &vldb->flags)) {
137                 params->type = AFSVL_RWVOL;
138         } else {
139                 goto error;
140         }
141
142         type_mask = 1UL << params->type;
143         volume = afs_alloc_volume(params, vldb, type_mask);
144
145 error:
146         kfree(vldb);
147         return volume;
148 }
149
150 /*
151  * Destroy a volume record
152  */
153 static void afs_destroy_volume(struct afs_net *net, struct afs_volume *volume)
154 {
155         _enter("%p", volume);
156
157 #ifdef CONFIG_AFS_FSCACHE
158         ASSERTCMP(volume->cache, ==, NULL);
159 #endif
160
161         afs_put_serverlist(net, volume->servers);
162         afs_put_cell(net, volume->cell);
163         kfree(volume);
164
165         _leave(" [destroyed]");
166 }
167
168 /*
169  * Drop a reference on a volume record.
170  */
171 void afs_put_volume(struct afs_cell *cell, struct afs_volume *volume)
172 {
173         if (volume) {
174                 _enter("%s", volume->name);
175
176                 if (atomic_dec_and_test(&volume->usage))
177                         afs_destroy_volume(cell->net, volume);
178         }
179 }
180
181 /*
182  * Activate a volume.
183  */
184 void afs_activate_volume(struct afs_volume *volume)
185 {
186 #ifdef CONFIG_AFS_FSCACHE
187         volume->cache = fscache_acquire_cookie(volume->cell->cache,
188                                                &afs_volume_cache_index_def,
189                                                &volume->vid, sizeof(volume->vid),
190                                                NULL, 0,
191                                                volume, 0, true);
192 #endif
193
194         write_lock(&volume->cell->proc_lock);
195         list_add_tail(&volume->proc_link, &volume->cell->proc_volumes);
196         write_unlock(&volume->cell->proc_lock);
197 }
198
199 /*
200  * Deactivate a volume.
201  */
202 void afs_deactivate_volume(struct afs_volume *volume)
203 {
204         _enter("%s", volume->name);
205
206         write_lock(&volume->cell->proc_lock);
207         list_del_init(&volume->proc_link);
208         write_unlock(&volume->cell->proc_lock);
209
210 #ifdef CONFIG_AFS_FSCACHE
211         fscache_relinquish_cookie(volume->cache, NULL,
212                                   test_bit(AFS_VOLUME_DELETED, &volume->flags));
213         volume->cache = NULL;
214 #endif
215
216         _leave("");
217 }
218
219 /*
220  * Query the VL service to update the volume status.
221  */
222 static int afs_update_volume_status(struct afs_volume *volume, struct key *key)
223 {
224         struct afs_server_list *new, *old, *discard;
225         struct afs_vldb_entry *vldb;
226         char idbuf[16];
227         int ret, idsz;
228
229         _enter("");
230
231         /* We look up an ID by passing it as a decimal string in the
232          * operation's name parameter.
233          */
234         idsz = sprintf(idbuf, "%llu", volume->vid);
235
236         vldb = afs_vl_lookup_vldb(volume->cell, key, idbuf, idsz);
237         if (IS_ERR(vldb)) {
238                 ret = PTR_ERR(vldb);
239                 goto error;
240         }
241
242         /* See if the volume got renamed. */
243         if (vldb->name_len != volume->name_len ||
244             memcmp(vldb->name, volume->name, vldb->name_len) != 0) {
245                 /* TODO: Use RCU'd string. */
246                 memcpy(volume->name, vldb->name, AFS_MAXVOLNAME);
247                 volume->name_len = vldb->name_len;
248         }
249
250         /* See if the volume's server list got updated. */
251         new = afs_alloc_server_list(volume->cell, key,
252                                     vldb, (1 << volume->type));
253         if (IS_ERR(new)) {
254                 ret = PTR_ERR(new);
255                 goto error_vldb;
256         }
257
258         write_lock(&volume->servers_lock);
259
260         discard = new;
261         old = volume->servers;
262         if (afs_annotate_server_list(new, old)) {
263                 new->seq = volume->servers_seq + 1;
264                 volume->servers = new;
265                 smp_wmb();
266                 volume->servers_seq++;
267                 discard = old;
268         }
269
270         volume->update_at = ktime_get_real_seconds() + afs_volume_record_life;
271         clear_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags);
272         write_unlock(&volume->servers_lock);
273         ret = 0;
274
275         afs_put_serverlist(volume->cell->net, discard);
276 error_vldb:
277         kfree(vldb);
278 error:
279         _leave(" = %d", ret);
280         return ret;
281 }
282
283 /*
284  * Make sure the volume record is up to date.
285  */
286 int afs_check_volume_status(struct afs_volume *volume, struct key *key)
287 {
288         time64_t now = ktime_get_real_seconds();
289         int ret, retries = 0;
290
291         _enter("");
292
293         if (volume->update_at <= now)
294                 set_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags);
295
296 retry:
297         if (!test_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags) &&
298             !test_bit(AFS_VOLUME_WAIT, &volume->flags)) {
299                 _leave(" = 0");
300                 return 0;
301         }
302
303         if (!test_and_set_bit_lock(AFS_VOLUME_UPDATING, &volume->flags)) {
304                 ret = afs_update_volume_status(volume, key);
305                 clear_bit_unlock(AFS_VOLUME_WAIT, &volume->flags);
306                 clear_bit_unlock(AFS_VOLUME_UPDATING, &volume->flags);
307                 wake_up_bit(&volume->flags, AFS_VOLUME_WAIT);
308                 _leave(" = %d", ret);
309                 return ret;
310         }
311
312         if (!test_bit(AFS_VOLUME_WAIT, &volume->flags)) {
313                 _leave(" = 0 [no wait]");
314                 return 0;
315         }
316
317         ret = wait_on_bit(&volume->flags, AFS_VOLUME_WAIT, TASK_INTERRUPTIBLE);
318         if (ret == -ERESTARTSYS) {
319                 _leave(" = %d", ret);
320                 return ret;
321         }
322
323         retries++;
324         if (retries == 4) {
325                 _leave(" = -ESTALE");
326                 return -ESTALE;
327         }
328         goto retry;
329 }