afs: Fix afs_cell records to always have a VL server list record
authorDavid Howells <dhowells@redhat.com>
Tue, 7 May 2019 14:30:34 +0000 (15:30 +0100)
committerDavid Howells <dhowells@redhat.com>
Wed, 15 May 2019 16:35:53 +0000 (17:35 +0100)
Fix it such that afs_cell records always have a VL server list record
attached, even if it's a dummy one, so that various checks can be removed.

Signed-off-by: David Howells <dhowells@redhat.com>
fs/afs/cell.c
fs/afs/proc.c
fs/afs/vl_list.c
fs/afs/vl_rotate.c

index 9ca075e..47f96be 100644 (file)
@@ -123,6 +123,7 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
                                       const char *name, unsigned int namelen,
                                       const char *addresses)
 {
+       struct afs_vlserver_list *vllist;
        struct afs_cell *cell;
        int i, ret;
 
@@ -157,12 +158,10 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
        rwlock_init(&cell->proc_lock);
        rwlock_init(&cell->vl_servers_lock);
 
-       /* Fill in the VL server list if we were given a list of addresses to
-        * use.
+       /* Provide a VL server list, filling it in if we were given a list of
+        * addresses to use.
         */
        if (addresses) {
-               struct afs_vlserver_list *vllist;
-
                vllist = afs_parse_text_addrs(net,
                                              addresses, strlen(addresses), ':',
                                              VL_SERVICE, AFS_VL_PORT);
@@ -171,19 +170,24 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
                        goto parse_failed;
                }
 
-               rcu_assign_pointer(cell->vl_servers, vllist);
                cell->dns_expiry = TIME64_MAX;
-               __clear_bit(AFS_CELL_FL_NO_LOOKUP_YET, &cell->flags);
        } else {
+               ret = -ENOMEM;
+               vllist = afs_alloc_vlserver_list(0);
+               if (!vllist)
+                       goto error;
                cell->dns_expiry = ktime_get_real_seconds();
        }
 
+       rcu_assign_pointer(cell->vl_servers, vllist);
+
        _leave(" = %p", cell);
        return cell;
 
 parse_failed:
        if (ret == -EINVAL)
                printk(KERN_ERR "kAFS: bad VL server IP address\n");
+error:
        kfree(cell);
        _leave(" = %d", ret);
        return ERR_PTR(ret);
@@ -410,8 +414,7 @@ static void afs_update_cell(struct afs_cell *cell)
                cell->dns_expiry = expiry;
                write_unlock(&cell->vl_servers_lock);
 
-               if (old)
-                       afs_put_vlserverlist(cell->net, old);
+               afs_put_vlserverlist(cell->net, old);
        }
 
        if (test_and_clear_bit(AFS_CELL_FL_NO_LOOKUP_YET, &cell->flags))
index be2ee3b..371501d 100644 (file)
@@ -53,7 +53,7 @@ static int afs_proc_cells_show(struct seq_file *m, void *v)
        seq_printf(m, "%3u %6lld %2u %s\n",
                   atomic_read(&cell->usage),
                   cell->dns_expiry - ktime_get_real_seconds(),
-                  vllist ? vllist->nr_servers : 0,
+                  vllist->nr_servers,
                   cell->name);
        return 0;
 }
@@ -296,8 +296,8 @@ static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v)
 
        if (v == SEQ_START_TOKEN) {
                seq_printf(m, "# source %s, status %s\n",
-                          dns_record_sources[vllist->source],
-                          dns_lookup_statuses[vllist->status]);
+                          dns_record_sources[vllist ? vllist->source : 0],
+                          dns_lookup_statuses[vllist ? vllist->status : 0]);
                return 0;
        }
 
@@ -336,7 +336,7 @@ static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos)
        if (pos == 0)
                return SEQ_START_TOKEN;
 
-       if (!vllist || pos - 1 >= vllist->nr_servers)
+       if (pos - 1 >= vllist->nr_servers)
                return NULL;
 
        return &vllist->servers[pos - 1];
index b4f1a84..61e2501 100644 (file)
@@ -232,18 +232,16 @@ struct afs_vlserver_list *afs_extract_vlserver_list(struct afs_cell *cell,
                if (bs.status > NR__dns_lookup_status)
                        bs.status = NR__dns_lookup_status;
 
+               /* See if we can update an old server record */
                server = NULL;
-               if (previous) {
-                       /* See if we can update an old server record */
-                       for (i = 0; i < previous->nr_servers; i++) {
-                               struct afs_vlserver *p = previous->servers[i].server;
-
-                               if (p->name_len == bs.name_len &&
-                                   p->port == bs.port &&
-                                   strncasecmp(b, p->name, bs.name_len) == 0) {
-                                       server = afs_get_vlserver(p);
-                                       break;
-                               }
+               for (i = 0; i < previous->nr_servers; i++) {
+                       struct afs_vlserver *p = previous->servers[i].server;
+
+                       if (p->name_len == bs.name_len &&
+                           p->port == bs.port &&
+                           strncasecmp(b, p->name, bs.name_len) == 0) {
+                               server = afs_get_vlserver(p);
+                               break;
                        }
                }
 
index 7adde83..65629d7 100644 (file)
@@ -55,7 +55,7 @@ static bool afs_start_vl_iteration(struct afs_vl_cursor *vc)
                rcu_dereference_protected(cell->vl_servers,
                                          lockdep_is_held(&cell->vl_servers_lock)));
        read_unlock(&cell->vl_servers_lock);
-       if (!vc->server_list || !vc->server_list->nr_servers)
+       if (!vc->server_list->nr_servers)
                return false;
 
        vc->untried = (1UL << vc->server_list->nr_servers) - 1;