Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* AFS volume management
0003  *
0004  * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/slab.h>
0010 #include "internal.h"
0011 
0012 static unsigned __read_mostly afs_volume_record_life = 60 * 60;
0013 
0014 /*
0015  * Insert a volume into a cell.  If there's an existing volume record, that is
0016  * returned instead with a ref held.
0017  */
0018 static struct afs_volume *afs_insert_volume_into_cell(struct afs_cell *cell,
0019                               struct afs_volume *volume)
0020 {
0021     struct afs_volume *p;
0022     struct rb_node *parent = NULL, **pp;
0023 
0024     write_seqlock(&cell->volume_lock);
0025 
0026     pp = &cell->volumes.rb_node;
0027     while (*pp) {
0028         parent = *pp;
0029         p = rb_entry(parent, struct afs_volume, cell_node);
0030         if (p->vid < volume->vid) {
0031             pp = &(*pp)->rb_left;
0032         } else if (p->vid > volume->vid) {
0033             pp = &(*pp)->rb_right;
0034         } else {
0035             volume = afs_get_volume(p, afs_volume_trace_get_cell_insert);
0036             goto found;
0037         }
0038     }
0039 
0040     rb_link_node_rcu(&volume->cell_node, parent, pp);
0041     rb_insert_color(&volume->cell_node, &cell->volumes);
0042     hlist_add_head_rcu(&volume->proc_link, &cell->proc_volumes);
0043 
0044 found:
0045     write_sequnlock(&cell->volume_lock);
0046     return volume;
0047 
0048 }
0049 
0050 static void afs_remove_volume_from_cell(struct afs_volume *volume)
0051 {
0052     struct afs_cell *cell = volume->cell;
0053 
0054     if (!hlist_unhashed(&volume->proc_link)) {
0055         trace_afs_volume(volume->vid, refcount_read(&cell->ref),
0056                  afs_volume_trace_remove);
0057         write_seqlock(&cell->volume_lock);
0058         hlist_del_rcu(&volume->proc_link);
0059         rb_erase(&volume->cell_node, &cell->volumes);
0060         write_sequnlock(&cell->volume_lock);
0061     }
0062 }
0063 
0064 /*
0065  * Allocate a volume record and load it up from a vldb record.
0066  */
0067 static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params,
0068                        struct afs_vldb_entry *vldb,
0069                        unsigned long type_mask)
0070 {
0071     struct afs_server_list *slist;
0072     struct afs_volume *volume;
0073     int ret = -ENOMEM, nr_servers = 0, i;
0074 
0075     for (i = 0; i < vldb->nr_servers; i++)
0076         if (vldb->fs_mask[i] & type_mask)
0077             nr_servers++;
0078 
0079     volume = kzalloc(sizeof(struct afs_volume), GFP_KERNEL);
0080     if (!volume)
0081         goto error_0;
0082 
0083     volume->vid     = vldb->vid[params->type];
0084     volume->update_at   = ktime_get_real_seconds() + afs_volume_record_life;
0085     volume->cell        = afs_get_cell(params->cell, afs_cell_trace_get_vol);
0086     volume->type        = params->type;
0087     volume->type_force  = params->force;
0088     volume->name_len    = vldb->name_len;
0089 
0090     refcount_set(&volume->ref, 1);
0091     INIT_HLIST_NODE(&volume->proc_link);
0092     rwlock_init(&volume->servers_lock);
0093     rwlock_init(&volume->cb_v_break_lock);
0094     memcpy(volume->name, vldb->name, vldb->name_len + 1);
0095 
0096     slist = afs_alloc_server_list(params->cell, params->key, vldb, type_mask);
0097     if (IS_ERR(slist)) {
0098         ret = PTR_ERR(slist);
0099         goto error_1;
0100     }
0101 
0102     refcount_set(&slist->usage, 1);
0103     rcu_assign_pointer(volume->servers, slist);
0104     trace_afs_volume(volume->vid, 1, afs_volume_trace_alloc);
0105     return volume;
0106 
0107 error_1:
0108     afs_put_cell(volume->cell, afs_cell_trace_put_vol);
0109     kfree(volume);
0110 error_0:
0111     return ERR_PTR(ret);
0112 }
0113 
0114 /*
0115  * Look up or allocate a volume record.
0116  */
0117 static struct afs_volume *afs_lookup_volume(struct afs_fs_context *params,
0118                         struct afs_vldb_entry *vldb,
0119                         unsigned long type_mask)
0120 {
0121     struct afs_volume *candidate, *volume;
0122 
0123     candidate = afs_alloc_volume(params, vldb, type_mask);
0124     if (IS_ERR(candidate))
0125         return candidate;
0126 
0127     volume = afs_insert_volume_into_cell(params->cell, candidate);
0128     if (volume != candidate)
0129         afs_put_volume(params->net, candidate, afs_volume_trace_put_cell_dup);
0130     return volume;
0131 }
0132 
0133 /*
0134  * Look up a VLDB record for a volume.
0135  */
0136 static struct afs_vldb_entry *afs_vl_lookup_vldb(struct afs_cell *cell,
0137                          struct key *key,
0138                          const char *volname,
0139                          size_t volnamesz)
0140 {
0141     struct afs_vldb_entry *vldb = ERR_PTR(-EDESTADDRREQ);
0142     struct afs_vl_cursor vc;
0143     int ret;
0144 
0145     if (!afs_begin_vlserver_operation(&vc, cell, key))
0146         return ERR_PTR(-ERESTARTSYS);
0147 
0148     while (afs_select_vlserver(&vc)) {
0149         vldb = afs_vl_get_entry_by_name_u(&vc, volname, volnamesz);
0150     }
0151 
0152     ret = afs_end_vlserver_operation(&vc);
0153     return ret < 0 ? ERR_PTR(ret) : vldb;
0154 }
0155 
0156 /*
0157  * Look up a volume in the VL server and create a candidate volume record for
0158  * it.
0159  *
0160  * The volume name can be one of the following:
0161  *  "%[cell:]volume[.]"     R/W volume
0162  *  "#[cell:]volume[.]"     R/O or R/W volume (rwparent=0),
0163  *                   or R/W (rwparent=1) volume
0164  *  "%[cell:]volume.readonly"   R/O volume
0165  *  "#[cell:]volume.readonly"   R/O volume
0166  *  "%[cell:]volume.backup"     Backup volume
0167  *  "#[cell:]volume.backup"     Backup volume
0168  *
0169  * The cell name is optional, and defaults to the current cell.
0170  *
0171  * See "The Rules of Mount Point Traversal" in Chapter 5 of the AFS SysAdmin
0172  * Guide
0173  * - Rule 1: Explicit type suffix forces access of that type or nothing
0174  *           (no suffix, then use Rule 2 & 3)
0175  * - Rule 2: If parent volume is R/O, then mount R/O volume by preference, R/W
0176  *           if not available
0177  * - Rule 3: If parent volume is R/W, then only mount R/W volume unless
0178  *           explicitly told otherwise
0179  */
0180 struct afs_volume *afs_create_volume(struct afs_fs_context *params)
0181 {
0182     struct afs_vldb_entry *vldb;
0183     struct afs_volume *volume;
0184     unsigned long type_mask = 1UL << params->type;
0185 
0186     vldb = afs_vl_lookup_vldb(params->cell, params->key,
0187                   params->volname, params->volnamesz);
0188     if (IS_ERR(vldb))
0189         return ERR_CAST(vldb);
0190 
0191     if (test_bit(AFS_VLDB_QUERY_ERROR, &vldb->flags)) {
0192         volume = ERR_PTR(vldb->error);
0193         goto error;
0194     }
0195 
0196     /* Make the final decision on the type we want */
0197     volume = ERR_PTR(-ENOMEDIUM);
0198     if (params->force) {
0199         if (!(vldb->flags & type_mask))
0200             goto error;
0201     } else if (test_bit(AFS_VLDB_HAS_RO, &vldb->flags)) {
0202         params->type = AFSVL_ROVOL;
0203     } else if (test_bit(AFS_VLDB_HAS_RW, &vldb->flags)) {
0204         params->type = AFSVL_RWVOL;
0205     } else {
0206         goto error;
0207     }
0208 
0209     type_mask = 1UL << params->type;
0210     volume = afs_lookup_volume(params, vldb, type_mask);
0211 
0212 error:
0213     kfree(vldb);
0214     return volume;
0215 }
0216 
0217 /*
0218  * Destroy a volume record
0219  */
0220 static void afs_destroy_volume(struct afs_net *net, struct afs_volume *volume)
0221 {
0222     _enter("%p", volume);
0223 
0224 #ifdef CONFIG_AFS_FSCACHE
0225     ASSERTCMP(volume->cache, ==, NULL);
0226 #endif
0227 
0228     afs_remove_volume_from_cell(volume);
0229     afs_put_serverlist(net, rcu_access_pointer(volume->servers));
0230     afs_put_cell(volume->cell, afs_cell_trace_put_vol);
0231     trace_afs_volume(volume->vid, refcount_read(&volume->ref),
0232              afs_volume_trace_free);
0233     kfree_rcu(volume, rcu);
0234 
0235     _leave(" [destroyed]");
0236 }
0237 
0238 /*
0239  * Get a reference on a volume record.
0240  */
0241 struct afs_volume *afs_get_volume(struct afs_volume *volume,
0242                   enum afs_volume_trace reason)
0243 {
0244     if (volume) {
0245         int r;
0246 
0247         __refcount_inc(&volume->ref, &r);
0248         trace_afs_volume(volume->vid, r + 1, reason);
0249     }
0250     return volume;
0251 }
0252 
0253 
0254 /*
0255  * Drop a reference on a volume record.
0256  */
0257 void afs_put_volume(struct afs_net *net, struct afs_volume *volume,
0258             enum afs_volume_trace reason)
0259 {
0260     if (volume) {
0261         afs_volid_t vid = volume->vid;
0262         bool zero;
0263         int r;
0264 
0265         zero = __refcount_dec_and_test(&volume->ref, &r);
0266         trace_afs_volume(vid, r - 1, reason);
0267         if (zero)
0268             afs_destroy_volume(net, volume);
0269     }
0270 }
0271 
0272 /*
0273  * Activate a volume.
0274  */
0275 int afs_activate_volume(struct afs_volume *volume)
0276 {
0277 #ifdef CONFIG_AFS_FSCACHE
0278     struct fscache_volume *vcookie;
0279     char *name;
0280 
0281     name = kasprintf(GFP_KERNEL, "afs,%s,%llx",
0282              volume->cell->name, volume->vid);
0283     if (!name)
0284         return -ENOMEM;
0285 
0286     vcookie = fscache_acquire_volume(name, NULL, NULL, 0);
0287     if (IS_ERR(vcookie)) {
0288         if (vcookie != ERR_PTR(-EBUSY)) {
0289             kfree(name);
0290             return PTR_ERR(vcookie);
0291         }
0292         pr_err("AFS: Cache volume key already in use (%s)\n", name);
0293         vcookie = NULL;
0294     }
0295     volume->cache = vcookie;
0296     kfree(name);
0297 #endif
0298     return 0;
0299 }
0300 
0301 /*
0302  * Deactivate a volume.
0303  */
0304 void afs_deactivate_volume(struct afs_volume *volume)
0305 {
0306     _enter("%s", volume->name);
0307 
0308 #ifdef CONFIG_AFS_FSCACHE
0309     fscache_relinquish_volume(volume->cache, NULL,
0310                   test_bit(AFS_VOLUME_DELETED, &volume->flags));
0311     volume->cache = NULL;
0312 #endif
0313 
0314     _leave("");
0315 }
0316 
0317 /*
0318  * Query the VL service to update the volume status.
0319  */
0320 static int afs_update_volume_status(struct afs_volume *volume, struct key *key)
0321 {
0322     struct afs_server_list *new, *old, *discard;
0323     struct afs_vldb_entry *vldb;
0324     char idbuf[16];
0325     int ret, idsz;
0326 
0327     _enter("");
0328 
0329     /* We look up an ID by passing it as a decimal string in the
0330      * operation's name parameter.
0331      */
0332     idsz = sprintf(idbuf, "%llu", volume->vid);
0333 
0334     vldb = afs_vl_lookup_vldb(volume->cell, key, idbuf, idsz);
0335     if (IS_ERR(vldb)) {
0336         ret = PTR_ERR(vldb);
0337         goto error;
0338     }
0339 
0340     /* See if the volume got renamed. */
0341     if (vldb->name_len != volume->name_len ||
0342         memcmp(vldb->name, volume->name, vldb->name_len) != 0) {
0343         /* TODO: Use RCU'd string. */
0344         memcpy(volume->name, vldb->name, AFS_MAXVOLNAME);
0345         volume->name_len = vldb->name_len;
0346     }
0347 
0348     /* See if the volume's server list got updated. */
0349     new = afs_alloc_server_list(volume->cell, key,
0350                     vldb, (1 << volume->type));
0351     if (IS_ERR(new)) {
0352         ret = PTR_ERR(new);
0353         goto error_vldb;
0354     }
0355 
0356     write_lock(&volume->servers_lock);
0357 
0358     discard = new;
0359     old = rcu_dereference_protected(volume->servers,
0360                     lockdep_is_held(&volume->servers_lock));
0361     if (afs_annotate_server_list(new, old)) {
0362         new->seq = volume->servers_seq + 1;
0363         rcu_assign_pointer(volume->servers, new);
0364         smp_wmb();
0365         volume->servers_seq++;
0366         discard = old;
0367     }
0368 
0369     volume->update_at = ktime_get_real_seconds() + afs_volume_record_life;
0370     write_unlock(&volume->servers_lock);
0371     ret = 0;
0372 
0373     afs_put_serverlist(volume->cell->net, discard);
0374 error_vldb:
0375     kfree(vldb);
0376 error:
0377     _leave(" = %d", ret);
0378     return ret;
0379 }
0380 
0381 /*
0382  * Make sure the volume record is up to date.
0383  */
0384 int afs_check_volume_status(struct afs_volume *volume, struct afs_operation *op)
0385 {
0386     int ret, retries = 0;
0387 
0388     _enter("");
0389 
0390 retry:
0391     if (test_bit(AFS_VOLUME_WAIT, &volume->flags))
0392         goto wait;
0393     if (volume->update_at <= ktime_get_real_seconds() ||
0394         test_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags))
0395         goto update;
0396     _leave(" = 0");
0397     return 0;
0398 
0399 update:
0400     if (!test_and_set_bit_lock(AFS_VOLUME_UPDATING, &volume->flags)) {
0401         clear_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags);
0402         ret = afs_update_volume_status(volume, op->key);
0403         if (ret < 0)
0404             set_bit(AFS_VOLUME_NEEDS_UPDATE, &volume->flags);
0405         clear_bit_unlock(AFS_VOLUME_WAIT, &volume->flags);
0406         clear_bit_unlock(AFS_VOLUME_UPDATING, &volume->flags);
0407         wake_up_bit(&volume->flags, AFS_VOLUME_WAIT);
0408         _leave(" = %d", ret);
0409         return ret;
0410     }
0411 
0412 wait:
0413     if (!test_bit(AFS_VOLUME_WAIT, &volume->flags)) {
0414         _leave(" = 0 [no wait]");
0415         return 0;
0416     }
0417 
0418     ret = wait_on_bit(&volume->flags, AFS_VOLUME_WAIT,
0419               (op->flags & AFS_OPERATION_UNINTR) ?
0420               TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE);
0421     if (ret == -ERESTARTSYS) {
0422         _leave(" = %d", ret);
0423         return ret;
0424     }
0425 
0426     retries++;
0427     if (retries == 4) {
0428         _leave(" = -ESTALE");
0429         return -ESTALE;
0430     }
0431     goto retry;
0432 }