]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
afs: Fix TTL on VL server and address lists
authorDavid Howells <dhowells@redhat.com>
Fri, 19 Oct 2018 23:57:57 +0000 (00:57 +0100)
committerDavid Howells <dhowells@redhat.com>
Tue, 23 Oct 2018 23:41:07 +0000 (00:41 +0100)
Currently the TTL on VL server and address lists isn't set in all
circumstances and may be set to poor choices in others, since the TTL is
derived from the SRV/AFSDB DNS record if and when available.

Fix the TTL by limiting the range to a minimum and maximum from the current
time.  At some point these can be made into sysctl knobs.  Further, use the
TTL we obtained from the upcall to set the expiry on negative results too;
in future a mechanism can be added to force reloading of such data.

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

index 963b6fa51fdf8a860abc287de970a8ece6e9743a..cf445dbd5f2e05d4c716dadb3123fb397537d4e6 100644 (file)
@@ -20,6 +20,8 @@
 #include "internal.h"
 
 static unsigned __read_mostly afs_cell_gc_delay = 10;
+static unsigned __read_mostly afs_cell_min_ttl = 10 * 60;
+static unsigned __read_mostly afs_cell_max_ttl = 24 * 60 * 60;
 
 static void afs_manage_cell(struct work_struct *);
 
@@ -171,6 +173,8 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
 
                rcu_assign_pointer(cell->vl_servers, vllist);
                cell->dns_expiry = TIME64_MAX;
+       } else {
+               cell->dns_expiry = ktime_get_real_seconds();
        }
 
        _leave(" = %p", cell);
@@ -358,25 +362,39 @@ int afs_cell_init(struct afs_net *net, const char *rootcell)
 static void afs_update_cell(struct afs_cell *cell)
 {
        struct afs_vlserver_list *vllist, *old;
-       time64_t now, expiry;
+       unsigned int min_ttl = READ_ONCE(afs_cell_min_ttl);
+       unsigned int max_ttl = READ_ONCE(afs_cell_max_ttl);
+       time64_t now, expiry = 0;
 
        _enter("%s", cell->name);
 
        vllist = afs_dns_query(cell, &expiry);
+
+       now = ktime_get_real_seconds();
+       if (min_ttl > max_ttl)
+               max_ttl = min_ttl;
+       if (expiry < now + min_ttl)
+               expiry = now + min_ttl;
+       else if (expiry > now + max_ttl)
+               expiry = now + max_ttl;
+
        if (IS_ERR(vllist)) {
                switch (PTR_ERR(vllist)) {
                case -ENODATA:
-                       /* The DNS said that the cell does not exist */
+               case -EDESTADDRREQ:
+                       /* The DNS said that the cell does not exist or there
+                        * weren't any addresses to be had.
+                        */
                        set_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags);
                        clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
-                       cell->dns_expiry = ktime_get_real_seconds() + 61;
+                       cell->dns_expiry = expiry;
                        break;
 
                case -EAGAIN:
                case -ECONNREFUSED:
                default:
                        set_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
-                       cell->dns_expiry = ktime_get_real_seconds() + 10;
+                       cell->dns_expiry = now + 10;
                        break;
                }
 
index 6585f4bec0d37db1313aceb435a9eab72ca33ca2..fc36c41641ab136e2771c9e20eaf03941038f0b1 100644 (file)
@@ -37,16 +37,24 @@ static inline struct afs_net *afs_seq2net_single(struct seq_file *m)
  */
 static int afs_proc_cells_show(struct seq_file *m, void *v)
 {
-       struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link);
+       struct afs_vlserver_list *vllist;
+       struct afs_cell *cell;
 
        if (v == SEQ_START_TOKEN) {
                /* display header on line 1 */
-               seq_puts(m, "USE NAME\n");
+               seq_puts(m, "USE    TTL SV NAME\n");
                return 0;
        }
 
+       cell = list_entry(v, struct afs_cell, proc_link);
+       vllist = rcu_dereference(cell->vl_servers);
+
        /* display one cell per line on subsequent lines */
-       seq_printf(m, "%3u %s\n", atomic_read(&cell->usage), cell->name);
+       seq_printf(m, "%3u %6lld %2u %s\n",
+                  atomic_read(&cell->usage),
+                  cell->dns_expiry - ktime_get_real_seconds(),
+                  vllist ? vllist->nr_servers : 0,
+                  cell->name);
        return 0;
 }