1 /* AFS volume management
3 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
12 #include <linux/kernel.h>
13 #include <linux/slab.h>
16 unsigned __read_mostly afs_volume_gc_delay
= 10;
17 unsigned __read_mostly afs_volume_record_life
= 60 * 60;
19 static const char *const afs_voltypes
[] = { "R/W", "R/O", "BAK" };
22 * Allocate a volume record and load it up from a vldb record.
24 static struct afs_volume
*afs_alloc_volume(struct afs_fs_context
*params
,
25 struct afs_vldb_entry
*vldb
,
26 unsigned long type_mask
)
28 struct afs_server_list
*slist
;
29 struct afs_volume
*volume
;
30 int ret
= -ENOMEM
, nr_servers
= 0, i
;
32 for (i
= 0; i
< vldb
->nr_servers
; i
++)
33 if (vldb
->fs_mask
[i
] & type_mask
)
36 volume
= kzalloc(sizeof(struct afs_volume
), GFP_KERNEL
);
40 volume
->vid
= vldb
->vid
[params
->type
];
41 volume
->update_at
= ktime_get_real_seconds() + afs_volume_record_life
;
42 volume
->cell
= afs_get_cell(params
->cell
);
43 volume
->type
= params
->type
;
44 volume
->type_force
= params
->force
;
45 volume
->name_len
= vldb
->name_len
;
47 atomic_set(&volume
->usage
, 1);
48 INIT_LIST_HEAD(&volume
->proc_link
);
49 rwlock_init(&volume
->servers_lock
);
50 memcpy(volume
->name
, vldb
->name
, vldb
->name_len
+ 1);
52 slist
= afs_alloc_server_list(params
->cell
, params
->key
, vldb
, type_mask
);
58 refcount_set(&slist
->usage
, 1);
59 volume
->servers
= slist
;
63 afs_put_cell(params
->net
, volume
->cell
);
70 * Look up a VLDB record for a volume.
72 static struct afs_vldb_entry
*afs_vl_lookup_vldb(struct afs_cell
*cell
,
77 struct afs_vldb_entry
*vldb
= ERR_PTR(-EDESTADDRREQ
);
78 struct afs_vl_cursor vc
;
81 if (!afs_begin_vlserver_operation(&vc
, cell
, key
))
82 return ERR_PTR(-ERESTARTSYS
);
84 while (afs_select_vlserver(&vc
)) {
85 vldb
= afs_vl_get_entry_by_name_u(&vc
, volname
, volnamesz
);
88 ret
= afs_end_vlserver_operation(&vc
);
89 return ret
< 0 ? ERR_PTR(ret
) : vldb
;
93 * Look up a volume in the VL server and create a candidate volume record for
96 * The volume name can be one of the following:
97 * "%[cell:]volume[.]" R/W volume
98 * "#[cell:]volume[.]" R/O or R/W volume (rwparent=0),
99 * or R/W (rwparent=1) volume
100 * "%[cell:]volume.readonly" R/O volume
101 * "#[cell:]volume.readonly" R/O volume
102 * "%[cell:]volume.backup" Backup volume
103 * "#[cell:]volume.backup" Backup volume
105 * The cell name is optional, and defaults to the current cell.
107 * See "The Rules of Mount Point Traversal" in Chapter 5 of the AFS SysAdmin
109 * - Rule 1: Explicit type suffix forces access of that type or nothing
110 * (no suffix, then use Rule 2 & 3)
111 * - Rule 2: If parent volume is R/O, then mount R/O volume by preference, R/W
113 * - Rule 3: If parent volume is R/W, then only mount R/W volume unless
114 * explicitly told otherwise
116 struct afs_volume
*afs_create_volume(struct afs_fs_context
*params
)
118 struct afs_vldb_entry
*vldb
;
119 struct afs_volume
*volume
;
120 unsigned long type_mask
= 1UL << params
->type
;
122 vldb
= afs_vl_lookup_vldb(params
->cell
, params
->key
,
123 params
->volname
, params
->volnamesz
);
125 return ERR_CAST(vldb
);
127 if (test_bit(AFS_VLDB_QUERY_ERROR
, &vldb
->flags
)) {
128 volume
= ERR_PTR(vldb
->error
);
132 /* Make the final decision on the type we want */
133 volume
= ERR_PTR(-ENOMEDIUM
);
135 if (!(vldb
->flags
& type_mask
))
137 } else if (test_bit(AFS_VLDB_HAS_RO
, &vldb
->flags
)) {
138 params
->type
= AFSVL_ROVOL
;
139 } else if (test_bit(AFS_VLDB_HAS_RW
, &vldb
->flags
)) {
140 params
->type
= AFSVL_RWVOL
;
145 type_mask
= 1UL << params
->type
;
146 volume
= afs_alloc_volume(params
, vldb
, type_mask
);
154 * Destroy a volume record
156 static void afs_destroy_volume(struct afs_net
*net
, struct afs_volume
*volume
)
158 _enter("%p", volume
);
160 #ifdef CONFIG_AFS_FSCACHE
161 ASSERTCMP(volume
->cache
, ==, NULL
);
164 afs_put_serverlist(net
, volume
->servers
);
165 afs_put_cell(net
, volume
->cell
);
168 _leave(" [destroyed]");
172 * Drop a reference on a volume record.
174 void afs_put_volume(struct afs_cell
*cell
, struct afs_volume
*volume
)
177 _enter("%s", volume
->name
);
179 if (atomic_dec_and_test(&volume
->usage
))
180 afs_destroy_volume(cell
->net
, volume
);
187 void afs_activate_volume(struct afs_volume
*volume
)
189 #ifdef CONFIG_AFS_FSCACHE
190 volume
->cache
= fscache_acquire_cookie(volume
->cell
->cache
,
191 &afs_volume_cache_index_def
,
192 &volume
->vid
, sizeof(volume
->vid
),
197 write_lock(&volume
->cell
->proc_lock
);
198 list_add_tail(&volume
->proc_link
, &volume
->cell
->proc_volumes
);
199 write_unlock(&volume
->cell
->proc_lock
);
203 * Deactivate a volume.
205 void afs_deactivate_volume(struct afs_volume
*volume
)
207 _enter("%s", volume
->name
);
209 write_lock(&volume
->cell
->proc_lock
);
210 list_del_init(&volume
->proc_link
);
211 write_unlock(&volume
->cell
->proc_lock
);
213 #ifdef CONFIG_AFS_FSCACHE
214 fscache_relinquish_cookie(volume
->cache
, NULL
,
215 test_bit(AFS_VOLUME_DELETED
, &volume
->flags
));
216 volume
->cache
= NULL
;
223 * Query the VL service to update the volume status.
225 static int afs_update_volume_status(struct afs_volume
*volume
, struct key
*key
)
227 struct afs_server_list
*new, *old
, *discard
;
228 struct afs_vldb_entry
*vldb
;
234 /* We look up an ID by passing it as a decimal string in the
235 * operation's name parameter.
237 idsz
= sprintf(idbuf
, "%llu", volume
->vid
);
239 vldb
= afs_vl_lookup_vldb(volume
->cell
, key
, idbuf
, idsz
);
245 /* See if the volume got renamed. */
246 if (vldb
->name_len
!= volume
->name_len
||
247 memcmp(vldb
->name
, volume
->name
, vldb
->name_len
) != 0) {
248 /* TODO: Use RCU'd string. */
249 memcpy(volume
->name
, vldb
->name
, AFS_MAXVOLNAME
);
250 volume
->name_len
= vldb
->name_len
;
253 /* See if the volume's server list got updated. */
254 new = afs_alloc_server_list(volume
->cell
, key
,
255 vldb
, (1 << volume
->type
));
261 write_lock(&volume
->servers_lock
);
264 old
= volume
->servers
;
265 if (afs_annotate_server_list(new, old
)) {
266 new->seq
= volume
->servers_seq
+ 1;
267 volume
->servers
= new;
269 volume
->servers_seq
++;
273 volume
->update_at
= ktime_get_real_seconds() + afs_volume_record_life
;
274 clear_bit(AFS_VOLUME_NEEDS_UPDATE
, &volume
->flags
);
275 write_unlock(&volume
->servers_lock
);
278 afs_put_serverlist(volume
->cell
->net
, discard
);
282 _leave(" = %d", ret
);
287 * Make sure the volume record is up to date.
289 int afs_check_volume_status(struct afs_volume
*volume
, struct key
*key
)
291 time64_t now
= ktime_get_real_seconds();
292 int ret
, retries
= 0;
296 if (volume
->update_at
<= now
)
297 set_bit(AFS_VOLUME_NEEDS_UPDATE
, &volume
->flags
);
300 if (!test_bit(AFS_VOLUME_NEEDS_UPDATE
, &volume
->flags
) &&
301 !test_bit(AFS_VOLUME_WAIT
, &volume
->flags
)) {
306 if (!test_and_set_bit_lock(AFS_VOLUME_UPDATING
, &volume
->flags
)) {
307 ret
= afs_update_volume_status(volume
, key
);
308 clear_bit_unlock(AFS_VOLUME_WAIT
, &volume
->flags
);
309 clear_bit_unlock(AFS_VOLUME_UPDATING
, &volume
->flags
);
310 wake_up_bit(&volume
->flags
, AFS_VOLUME_WAIT
);
311 _leave(" = %d", ret
);
315 if (!test_bit(AFS_VOLUME_WAIT
, &volume
->flags
)) {
316 _leave(" = 0 [no wait]");
320 ret
= wait_on_bit(&volume
->flags
, AFS_VOLUME_WAIT
, TASK_INTERRUPTIBLE
);
321 if (ret
== -ERESTARTSYS
) {
322 _leave(" = %d", ret
);
328 _leave(" = -ESTALE");