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