Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* AFS server record 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/sched.h>
0009 #include <linux/slab.h>
0010 #include "afs_fs.h"
0011 #include "internal.h"
0012 #include "protocol_yfs.h"
0013 
0014 static unsigned afs_server_gc_delay = 10;   /* Server record timeout in seconds */
0015 static atomic_t afs_server_debug_id;
0016 
0017 static struct afs_server *afs_maybe_use_server(struct afs_server *,
0018                            enum afs_server_trace);
0019 static void __afs_put_server(struct afs_net *, struct afs_server *);
0020 
0021 /*
0022  * Find a server by one of its addresses.
0023  */
0024 struct afs_server *afs_find_server(struct afs_net *net,
0025                    const struct sockaddr_rxrpc *srx)
0026 {
0027     const struct afs_addr_list *alist;
0028     struct afs_server *server = NULL;
0029     unsigned int i;
0030     int seq = 0, diff;
0031 
0032     rcu_read_lock();
0033 
0034     do {
0035         if (server)
0036             afs_unuse_server_notime(net, server, afs_server_trace_put_find_rsq);
0037         server = NULL;
0038         read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
0039 
0040         if (srx->transport.family == AF_INET6) {
0041             const struct sockaddr_in6 *a = &srx->transport.sin6, *b;
0042             hlist_for_each_entry_rcu(server, &net->fs_addresses6, addr6_link) {
0043                 alist = rcu_dereference(server->addresses);
0044                 for (i = alist->nr_ipv4; i < alist->nr_addrs; i++) {
0045                     b = &alist->addrs[i].transport.sin6;
0046                     diff = ((u16 __force)a->sin6_port -
0047                         (u16 __force)b->sin6_port);
0048                     if (diff == 0)
0049                         diff = memcmp(&a->sin6_addr,
0050                                   &b->sin6_addr,
0051                                   sizeof(struct in6_addr));
0052                     if (diff == 0)
0053                         goto found;
0054                 }
0055             }
0056         } else {
0057             const struct sockaddr_in *a = &srx->transport.sin, *b;
0058             hlist_for_each_entry_rcu(server, &net->fs_addresses4, addr4_link) {
0059                 alist = rcu_dereference(server->addresses);
0060                 for (i = 0; i < alist->nr_ipv4; i++) {
0061                     b = &alist->addrs[i].transport.sin;
0062                     diff = ((u16 __force)a->sin_port -
0063                         (u16 __force)b->sin_port);
0064                     if (diff == 0)
0065                         diff = ((u32 __force)a->sin_addr.s_addr -
0066                             (u32 __force)b->sin_addr.s_addr);
0067                     if (diff == 0)
0068                         goto found;
0069                 }
0070             }
0071         }
0072 
0073         server = NULL;
0074         continue;
0075     found:
0076         server = afs_maybe_use_server(server, afs_server_trace_get_by_addr);
0077 
0078     } while (need_seqretry(&net->fs_addr_lock, seq));
0079 
0080     done_seqretry(&net->fs_addr_lock, seq);
0081 
0082     rcu_read_unlock();
0083     return server;
0084 }
0085 
0086 /*
0087  * Look up a server by its UUID and mark it active.
0088  */
0089 struct afs_server *afs_find_server_by_uuid(struct afs_net *net, const uuid_t *uuid)
0090 {
0091     struct afs_server *server = NULL;
0092     struct rb_node *p;
0093     int diff, seq = 0;
0094 
0095     _enter("%pU", uuid);
0096 
0097     do {
0098         /* Unfortunately, rbtree walking doesn't give reliable results
0099          * under just the RCU read lock, so we have to check for
0100          * changes.
0101          */
0102         if (server)
0103             afs_unuse_server(net, server, afs_server_trace_put_uuid_rsq);
0104         server = NULL;
0105 
0106         read_seqbegin_or_lock(&net->fs_lock, &seq);
0107 
0108         p = net->fs_servers.rb_node;
0109         while (p) {
0110             server = rb_entry(p, struct afs_server, uuid_rb);
0111 
0112             diff = memcmp(uuid, &server->uuid, sizeof(*uuid));
0113             if (diff < 0) {
0114                 p = p->rb_left;
0115             } else if (diff > 0) {
0116                 p = p->rb_right;
0117             } else {
0118                 afs_use_server(server, afs_server_trace_get_by_uuid);
0119                 break;
0120             }
0121 
0122             server = NULL;
0123         }
0124     } while (need_seqretry(&net->fs_lock, seq));
0125 
0126     done_seqretry(&net->fs_lock, seq);
0127 
0128     _leave(" = %p", server);
0129     return server;
0130 }
0131 
0132 /*
0133  * Install a server record in the namespace tree.  If there's a clash, we stick
0134  * it into a list anchored on whichever afs_server struct is actually in the
0135  * tree.
0136  */
0137 static struct afs_server *afs_install_server(struct afs_cell *cell,
0138                          struct afs_server *candidate)
0139 {
0140     const struct afs_addr_list *alist;
0141     struct afs_server *server, *next;
0142     struct afs_net *net = cell->net;
0143     struct rb_node **pp, *p;
0144     int diff;
0145 
0146     _enter("%p", candidate);
0147 
0148     write_seqlock(&net->fs_lock);
0149 
0150     /* Firstly install the server in the UUID lookup tree */
0151     pp = &net->fs_servers.rb_node;
0152     p = NULL;
0153     while (*pp) {
0154         p = *pp;
0155         _debug("- consider %p", p);
0156         server = rb_entry(p, struct afs_server, uuid_rb);
0157         diff = memcmp(&candidate->uuid, &server->uuid, sizeof(uuid_t));
0158         if (diff < 0) {
0159             pp = &(*pp)->rb_left;
0160         } else if (diff > 0) {
0161             pp = &(*pp)->rb_right;
0162         } else {
0163             if (server->cell == cell)
0164                 goto exists;
0165 
0166             /* We have the same UUID representing servers in
0167              * different cells.  Append the new server to the list.
0168              */
0169             for (;;) {
0170                 next = rcu_dereference_protected(
0171                     server->uuid_next,
0172                     lockdep_is_held(&net->fs_lock.lock));
0173                 if (!next)
0174                     break;
0175                 server = next;
0176             }
0177             rcu_assign_pointer(server->uuid_next, candidate);
0178             candidate->uuid_prev = server;
0179             server = candidate;
0180             goto added_dup;
0181         }
0182     }
0183 
0184     server = candidate;
0185     rb_link_node(&server->uuid_rb, p, pp);
0186     rb_insert_color(&server->uuid_rb, &net->fs_servers);
0187     hlist_add_head_rcu(&server->proc_link, &net->fs_proc);
0188 
0189 added_dup:
0190     write_seqlock(&net->fs_addr_lock);
0191     alist = rcu_dereference_protected(server->addresses,
0192                       lockdep_is_held(&net->fs_addr_lock.lock));
0193 
0194     /* Secondly, if the server has any IPv4 and/or IPv6 addresses, install
0195      * it in the IPv4 and/or IPv6 reverse-map lists.
0196      *
0197      * TODO: For speed we want to use something other than a flat list
0198      * here; even sorting the list in terms of lowest address would help a
0199      * bit, but anything we might want to do gets messy and memory
0200      * intensive.
0201      */
0202     if (alist->nr_ipv4 > 0)
0203         hlist_add_head_rcu(&server->addr4_link, &net->fs_addresses4);
0204     if (alist->nr_addrs > alist->nr_ipv4)
0205         hlist_add_head_rcu(&server->addr6_link, &net->fs_addresses6);
0206 
0207     write_sequnlock(&net->fs_addr_lock);
0208 
0209 exists:
0210     afs_get_server(server, afs_server_trace_get_install);
0211     write_sequnlock(&net->fs_lock);
0212     return server;
0213 }
0214 
0215 /*
0216  * Allocate a new server record and mark it active.
0217  */
0218 static struct afs_server *afs_alloc_server(struct afs_cell *cell,
0219                        const uuid_t *uuid,
0220                        struct afs_addr_list *alist)
0221 {
0222     struct afs_server *server;
0223     struct afs_net *net = cell->net;
0224 
0225     _enter("");
0226 
0227     server = kzalloc(sizeof(struct afs_server), GFP_KERNEL);
0228     if (!server)
0229         goto enomem;
0230 
0231     refcount_set(&server->ref, 1);
0232     atomic_set(&server->active, 1);
0233     server->debug_id = atomic_inc_return(&afs_server_debug_id);
0234     RCU_INIT_POINTER(server->addresses, alist);
0235     server->addr_version = alist->version;
0236     server->uuid = *uuid;
0237     rwlock_init(&server->fs_lock);
0238     INIT_WORK(&server->initcb_work, afs_server_init_callback_work);
0239     init_waitqueue_head(&server->probe_wq);
0240     INIT_LIST_HEAD(&server->probe_link);
0241     spin_lock_init(&server->probe_lock);
0242     server->cell = cell;
0243     server->rtt = UINT_MAX;
0244 
0245     afs_inc_servers_outstanding(net);
0246     trace_afs_server(server->debug_id, 1, 1, afs_server_trace_alloc);
0247     _leave(" = %p", server);
0248     return server;
0249 
0250 enomem:
0251     _leave(" = NULL [nomem]");
0252     return NULL;
0253 }
0254 
0255 /*
0256  * Look up an address record for a server
0257  */
0258 static struct afs_addr_list *afs_vl_lookup_addrs(struct afs_cell *cell,
0259                          struct key *key, const uuid_t *uuid)
0260 {
0261     struct afs_vl_cursor vc;
0262     struct afs_addr_list *alist = NULL;
0263     int ret;
0264 
0265     ret = -ERESTARTSYS;
0266     if (afs_begin_vlserver_operation(&vc, cell, key)) {
0267         while (afs_select_vlserver(&vc)) {
0268             if (test_bit(AFS_VLSERVER_FL_IS_YFS, &vc.server->flags))
0269                 alist = afs_yfsvl_get_endpoints(&vc, uuid);
0270             else
0271                 alist = afs_vl_get_addrs_u(&vc, uuid);
0272         }
0273 
0274         ret = afs_end_vlserver_operation(&vc);
0275     }
0276 
0277     return ret < 0 ? ERR_PTR(ret) : alist;
0278 }
0279 
0280 /*
0281  * Get or create a fileserver record.
0282  */
0283 struct afs_server *afs_lookup_server(struct afs_cell *cell, struct key *key,
0284                      const uuid_t *uuid, u32 addr_version)
0285 {
0286     struct afs_addr_list *alist;
0287     struct afs_server *server, *candidate;
0288 
0289     _enter("%p,%pU", cell->net, uuid);
0290 
0291     server = afs_find_server_by_uuid(cell->net, uuid);
0292     if (server) {
0293         if (server->addr_version != addr_version)
0294             set_bit(AFS_SERVER_FL_NEEDS_UPDATE, &server->flags);
0295         return server;
0296     }
0297 
0298     alist = afs_vl_lookup_addrs(cell, key, uuid);
0299     if (IS_ERR(alist))
0300         return ERR_CAST(alist);
0301 
0302     candidate = afs_alloc_server(cell, uuid, alist);
0303     if (!candidate) {
0304         afs_put_addrlist(alist);
0305         return ERR_PTR(-ENOMEM);
0306     }
0307 
0308     server = afs_install_server(cell, candidate);
0309     if (server != candidate) {
0310         afs_put_addrlist(alist);
0311         kfree(candidate);
0312     } else {
0313         /* Immediately dispatch an asynchronous probe to each interface
0314          * on the fileserver.  This will make sure the repeat-probing
0315          * service is started.
0316          */
0317         afs_fs_probe_fileserver(cell->net, server, key, true);
0318     }
0319 
0320     return server;
0321 }
0322 
0323 /*
0324  * Set the server timer to fire after a given delay, assuming it's not already
0325  * set for an earlier time.
0326  */
0327 static void afs_set_server_timer(struct afs_net *net, time64_t delay)
0328 {
0329     if (net->live) {
0330         afs_inc_servers_outstanding(net);
0331         if (timer_reduce(&net->fs_timer, jiffies + delay * HZ))
0332             afs_dec_servers_outstanding(net);
0333     }
0334 }
0335 
0336 /*
0337  * Server management timer.  We have an increment on fs_outstanding that we
0338  * need to pass along to the work item.
0339  */
0340 void afs_servers_timer(struct timer_list *timer)
0341 {
0342     struct afs_net *net = container_of(timer, struct afs_net, fs_timer);
0343 
0344     _enter("");
0345     if (!queue_work(afs_wq, &net->fs_manager))
0346         afs_dec_servers_outstanding(net);
0347 }
0348 
0349 /*
0350  * Get a reference on a server object.
0351  */
0352 struct afs_server *afs_get_server(struct afs_server *server,
0353                   enum afs_server_trace reason)
0354 {
0355     unsigned int a;
0356     int r;
0357 
0358     __refcount_inc(&server->ref, &r);
0359     a = atomic_read(&server->active);
0360     trace_afs_server(server->debug_id, r + 1, a, reason);
0361     return server;
0362 }
0363 
0364 /*
0365  * Try to get a reference on a server object.
0366  */
0367 static struct afs_server *afs_maybe_use_server(struct afs_server *server,
0368                            enum afs_server_trace reason)
0369 {
0370     unsigned int a;
0371     int r;
0372 
0373     if (!__refcount_inc_not_zero(&server->ref, &r))
0374         return NULL;
0375 
0376     a = atomic_inc_return(&server->active);
0377     trace_afs_server(server->debug_id, r + 1, a, reason);
0378     return server;
0379 }
0380 
0381 /*
0382  * Get an active count on a server object.
0383  */
0384 struct afs_server *afs_use_server(struct afs_server *server, enum afs_server_trace reason)
0385 {
0386     unsigned int a;
0387     int r;
0388 
0389     __refcount_inc(&server->ref, &r);
0390     a = atomic_inc_return(&server->active);
0391 
0392     trace_afs_server(server->debug_id, r + 1, a, reason);
0393     return server;
0394 }
0395 
0396 /*
0397  * Release a reference on a server record.
0398  */
0399 void afs_put_server(struct afs_net *net, struct afs_server *server,
0400             enum afs_server_trace reason)
0401 {
0402     unsigned int a, debug_id = server->debug_id;
0403     bool zero;
0404     int r;
0405 
0406     if (!server)
0407         return;
0408 
0409     a = atomic_inc_return(&server->active);
0410     zero = __refcount_dec_and_test(&server->ref, &r);
0411     trace_afs_server(debug_id, r - 1, a, reason);
0412     if (unlikely(zero))
0413         __afs_put_server(net, server);
0414 }
0415 
0416 /*
0417  * Drop an active count on a server object without updating the last-unused
0418  * time.
0419  */
0420 void afs_unuse_server_notime(struct afs_net *net, struct afs_server *server,
0421                  enum afs_server_trace reason)
0422 {
0423     if (server) {
0424         unsigned int active = atomic_dec_return(&server->active);
0425 
0426         if (active == 0)
0427             afs_set_server_timer(net, afs_server_gc_delay);
0428         afs_put_server(net, server, reason);
0429     }
0430 }
0431 
0432 /*
0433  * Drop an active count on a server object.
0434  */
0435 void afs_unuse_server(struct afs_net *net, struct afs_server *server,
0436               enum afs_server_trace reason)
0437 {
0438     if (server) {
0439         server->unuse_time = ktime_get_real_seconds();
0440         afs_unuse_server_notime(net, server, reason);
0441     }
0442 }
0443 
0444 static void afs_server_rcu(struct rcu_head *rcu)
0445 {
0446     struct afs_server *server = container_of(rcu, struct afs_server, rcu);
0447 
0448     trace_afs_server(server->debug_id, refcount_read(&server->ref),
0449              atomic_read(&server->active), afs_server_trace_free);
0450     afs_put_addrlist(rcu_access_pointer(server->addresses));
0451     kfree(server);
0452 }
0453 
0454 static void __afs_put_server(struct afs_net *net, struct afs_server *server)
0455 {
0456     call_rcu(&server->rcu, afs_server_rcu);
0457     afs_dec_servers_outstanding(net);
0458 }
0459 
0460 static void afs_give_up_callbacks(struct afs_net *net, struct afs_server *server)
0461 {
0462     struct afs_addr_list *alist = rcu_access_pointer(server->addresses);
0463     struct afs_addr_cursor ac = {
0464         .alist  = alist,
0465         .index  = alist->preferred,
0466         .error  = 0,
0467     };
0468 
0469     afs_fs_give_up_all_callbacks(net, server, &ac, NULL);
0470 }
0471 
0472 /*
0473  * destroy a dead server
0474  */
0475 static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
0476 {
0477     if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags))
0478         afs_give_up_callbacks(net, server);
0479 
0480     flush_work(&server->initcb_work);
0481     afs_put_server(net, server, afs_server_trace_destroy);
0482 }
0483 
0484 /*
0485  * Garbage collect any expired servers.
0486  */
0487 static void afs_gc_servers(struct afs_net *net, struct afs_server *gc_list)
0488 {
0489     struct afs_server *server, *next, *prev;
0490     int active;
0491 
0492     while ((server = gc_list)) {
0493         gc_list = server->gc_next;
0494 
0495         write_seqlock(&net->fs_lock);
0496 
0497         active = atomic_read(&server->active);
0498         if (active == 0) {
0499             trace_afs_server(server->debug_id, refcount_read(&server->ref),
0500                      active, afs_server_trace_gc);
0501             next = rcu_dereference_protected(
0502                 server->uuid_next, lockdep_is_held(&net->fs_lock.lock));
0503             prev = server->uuid_prev;
0504             if (!prev) {
0505                 /* The one at the front is in the tree */
0506                 if (!next) {
0507                     rb_erase(&server->uuid_rb, &net->fs_servers);
0508                 } else {
0509                     rb_replace_node_rcu(&server->uuid_rb,
0510                                 &next->uuid_rb,
0511                                 &net->fs_servers);
0512                     next->uuid_prev = NULL;
0513                 }
0514             } else {
0515                 /* This server is not at the front */
0516                 rcu_assign_pointer(prev->uuid_next, next);
0517                 if (next)
0518                     next->uuid_prev = prev;
0519             }
0520 
0521             list_del(&server->probe_link);
0522             hlist_del_rcu(&server->proc_link);
0523             if (!hlist_unhashed(&server->addr4_link))
0524                 hlist_del_rcu(&server->addr4_link);
0525             if (!hlist_unhashed(&server->addr6_link))
0526                 hlist_del_rcu(&server->addr6_link);
0527         }
0528         write_sequnlock(&net->fs_lock);
0529 
0530         if (active == 0)
0531             afs_destroy_server(net, server);
0532     }
0533 }
0534 
0535 /*
0536  * Manage the records of servers known to be within a network namespace.  This
0537  * includes garbage collecting unused servers.
0538  *
0539  * Note also that we were given an increment on net->servers_outstanding by
0540  * whoever queued us that we need to deal with before returning.
0541  */
0542 void afs_manage_servers(struct work_struct *work)
0543 {
0544     struct afs_net *net = container_of(work, struct afs_net, fs_manager);
0545     struct afs_server *gc_list = NULL;
0546     struct rb_node *cursor;
0547     time64_t now = ktime_get_real_seconds(), next_manage = TIME64_MAX;
0548     bool purging = !net->live;
0549 
0550     _enter("");
0551 
0552     /* Trawl the server list looking for servers that have expired from
0553      * lack of use.
0554      */
0555     read_seqlock_excl(&net->fs_lock);
0556 
0557     for (cursor = rb_first(&net->fs_servers); cursor; cursor = rb_next(cursor)) {
0558         struct afs_server *server =
0559             rb_entry(cursor, struct afs_server, uuid_rb);
0560         int active = atomic_read(&server->active);
0561 
0562         _debug("manage %pU %u", &server->uuid, active);
0563 
0564         if (purging) {
0565             trace_afs_server(server->debug_id, refcount_read(&server->ref),
0566                      active, afs_server_trace_purging);
0567             if (active != 0)
0568                 pr_notice("Can't purge s=%08x\n", server->debug_id);
0569         }
0570 
0571         if (active == 0) {
0572             time64_t expire_at = server->unuse_time;
0573 
0574             if (!test_bit(AFS_SERVER_FL_VL_FAIL, &server->flags) &&
0575                 !test_bit(AFS_SERVER_FL_NOT_FOUND, &server->flags))
0576                 expire_at += afs_server_gc_delay;
0577             if (purging || expire_at <= now) {
0578                 server->gc_next = gc_list;
0579                 gc_list = server;
0580             } else if (expire_at < next_manage) {
0581                 next_manage = expire_at;
0582             }
0583         }
0584     }
0585 
0586     read_sequnlock_excl(&net->fs_lock);
0587 
0588     /* Update the timer on the way out.  We have to pass an increment on
0589      * servers_outstanding in the namespace that we are in to the timer or
0590      * the work scheduler.
0591      */
0592     if (!purging && next_manage < TIME64_MAX) {
0593         now = ktime_get_real_seconds();
0594 
0595         if (next_manage - now <= 0) {
0596             if (queue_work(afs_wq, &net->fs_manager))
0597                 afs_inc_servers_outstanding(net);
0598         } else {
0599             afs_set_server_timer(net, next_manage - now);
0600         }
0601     }
0602 
0603     afs_gc_servers(net, gc_list);
0604 
0605     afs_dec_servers_outstanding(net);
0606     _leave(" [%d]", atomic_read(&net->servers_outstanding));
0607 }
0608 
0609 static void afs_queue_server_manager(struct afs_net *net)
0610 {
0611     afs_inc_servers_outstanding(net);
0612     if (!queue_work(afs_wq, &net->fs_manager))
0613         afs_dec_servers_outstanding(net);
0614 }
0615 
0616 /*
0617  * Purge list of servers.
0618  */
0619 void afs_purge_servers(struct afs_net *net)
0620 {
0621     _enter("");
0622 
0623     if (del_timer_sync(&net->fs_timer))
0624         afs_dec_servers_outstanding(net);
0625 
0626     afs_queue_server_manager(net);
0627 
0628     _debug("wait");
0629     atomic_dec(&net->servers_outstanding);
0630     wait_var_event(&net->servers_outstanding,
0631                !atomic_read(&net->servers_outstanding));
0632     _leave("");
0633 }
0634 
0635 /*
0636  * Get an update for a server's address list.
0637  */
0638 static noinline bool afs_update_server_record(struct afs_operation *op,
0639                           struct afs_server *server)
0640 {
0641     struct afs_addr_list *alist, *discard;
0642 
0643     _enter("");
0644 
0645     trace_afs_server(server->debug_id, refcount_read(&server->ref),
0646              atomic_read(&server->active),
0647              afs_server_trace_update);
0648 
0649     alist = afs_vl_lookup_addrs(op->volume->cell, op->key, &server->uuid);
0650     if (IS_ERR(alist)) {
0651         if ((PTR_ERR(alist) == -ERESTARTSYS ||
0652              PTR_ERR(alist) == -EINTR) &&
0653             (op->flags & AFS_OPERATION_UNINTR) &&
0654             server->addresses) {
0655             _leave(" = t [intr]");
0656             return true;
0657         }
0658         op->error = PTR_ERR(alist);
0659         _leave(" = f [%d]", op->error);
0660         return false;
0661     }
0662 
0663     discard = alist;
0664     if (server->addr_version != alist->version) {
0665         write_lock(&server->fs_lock);
0666         discard = rcu_dereference_protected(server->addresses,
0667                             lockdep_is_held(&server->fs_lock));
0668         rcu_assign_pointer(server->addresses, alist);
0669         server->addr_version = alist->version;
0670         write_unlock(&server->fs_lock);
0671     }
0672 
0673     afs_put_addrlist(discard);
0674     _leave(" = t");
0675     return true;
0676 }
0677 
0678 /*
0679  * See if a server's address list needs updating.
0680  */
0681 bool afs_check_server_record(struct afs_operation *op, struct afs_server *server)
0682 {
0683     bool success;
0684     int ret, retries = 0;
0685 
0686     _enter("");
0687 
0688     ASSERT(server);
0689 
0690 retry:
0691     if (test_bit(AFS_SERVER_FL_UPDATING, &server->flags))
0692         goto wait;
0693     if (test_bit(AFS_SERVER_FL_NEEDS_UPDATE, &server->flags))
0694         goto update;
0695     _leave(" = t [good]");
0696     return true;
0697 
0698 update:
0699     if (!test_and_set_bit_lock(AFS_SERVER_FL_UPDATING, &server->flags)) {
0700         clear_bit(AFS_SERVER_FL_NEEDS_UPDATE, &server->flags);
0701         success = afs_update_server_record(op, server);
0702         clear_bit_unlock(AFS_SERVER_FL_UPDATING, &server->flags);
0703         wake_up_bit(&server->flags, AFS_SERVER_FL_UPDATING);
0704         _leave(" = %d", success);
0705         return success;
0706     }
0707 
0708 wait:
0709     ret = wait_on_bit(&server->flags, AFS_SERVER_FL_UPDATING,
0710               (op->flags & AFS_OPERATION_UNINTR) ?
0711               TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE);
0712     if (ret == -ERESTARTSYS) {
0713         op->error = ret;
0714         _leave(" = f [intr]");
0715         return false;
0716     }
0717 
0718     retries++;
0719     if (retries == 4) {
0720         _leave(" = f [stale]");
0721         ret = -ESTALE;
0722         return false;
0723     }
0724     goto retry;
0725 }