#define AFS_VOL_VTM_RW 0x01 /* R/W version of the volume is available (on this server) */
 #define AFS_VOL_VTM_RO 0x02 /* R/O version of the volume is available (on this server) */
 #define AFS_VOL_VTM_BAK        0x04 /* backup version of the volume is available (on this server) */
+       u8                      vlsf_flags[AFS_NMAXNSERVERS];
        short                   error;
        u8                      nr_servers;     /* Number of server records */
        u8                      name_len;
        spinlock_t              probe_lock;
 };
 
+enum afs_ro_replicating {
+       AFS_RO_NOT_REPLICATING,                 /* Not doing replication */
+       AFS_RO_REPLICATING_USE_OLD,             /* Replicating; use old version */
+       AFS_RO_REPLICATING_USE_NEW,             /* Replicating; switch to new version */
+} __mode(byte);
+
 /*
  * Replaceable volume server list.
  */
        struct afs_server       *server;
        struct afs_volume       *volume;
        struct list_head        slink;          /* Link in server->volumes */
+       unsigned long           flags;
+#define AFS_SE_EXCLUDED                0               /* Set if server is to be excluded in rotation */
 };
 
 struct afs_server_list {
        struct rcu_head         rcu;
        refcount_t              usage;
        bool                    attached;       /* T if attached to servers */
+       enum afs_ro_replicating ro_replicating; /* RW->RO update (probably) in progress */
        unsigned char           nr_servers;
        unsigned char           preferred;      /* Preferred server */
        unsigned short          vnovol_mask;    /* Servers to be skipped due to VNOVOL */
 
        struct afs_server_list *slist;
        struct afs_server *server;
        unsigned int type_mask = 1 << volume->type;
-       int ret = -ENOMEM, nr_servers = 0, i, j;
-
-       for (i = 0; i < vldb->nr_servers; i++)
-               if (vldb->fs_mask[i] & type_mask)
-                       nr_servers++;
+       bool use_newrepsites = false;
+       int ret = -ENOMEM, nr_servers = 0, newrep = 0, i, j, usable = 0;
+
+       /* Work out if we're going to restrict to NEWREPSITE-marked servers or
+        * not.  If at least one site is marked as NEWREPSITE, then it's likely
+        * that "vos release" is busy updating RO sites.  We cut over from one
+        * to the other when >=50% of the sites have been updated.  Sites that
+        * are in the process of being updated are marked DONTUSE.
+        */
+       for (i = 0; i < vldb->nr_servers; i++) {
+               if (!(vldb->fs_mask[i] & type_mask))
+                       continue;
+               nr_servers++;
+               if (vldb->vlsf_flags[i] & AFS_VLSF_DONTUSE)
+                       continue;
+               usable++;
+               if (vldb->vlsf_flags[i] & AFS_VLSF_NEWREPSITE)
+                       newrep++;
+       }
 
        slist = kzalloc(struct_size(slist, servers, nr_servers), GFP_KERNEL);
        if (!slist)
                goto error;
 
+       if (newrep) {
+               if (newrep < usable / 2) {
+                       slist->ro_replicating = AFS_RO_REPLICATING_USE_OLD;
+               } else {
+                       slist->ro_replicating = AFS_RO_REPLICATING_USE_NEW;
+                       use_newrepsites = true;
+               }
+       }
+
        refcount_set(&slist->usage, 1);
        rwlock_init(&slist->lock);
 
        /* Make sure a records exists for each server in the list. */
        for (i = 0; i < vldb->nr_servers; i++) {
+               unsigned long se_flags = 0;
+               bool newrepsite = vldb->vlsf_flags[i] & AFS_VLSF_NEWREPSITE;
+
                if (!(vldb->fs_mask[i] & type_mask))
                        continue;
+               if (vldb->vlsf_flags[i] & AFS_VLSF_DONTUSE)
+                       __set_bit(AFS_SE_EXCLUDED, &se_flags);
+               if (newrep && (newrepsite ^ use_newrepsites))
+                       __set_bit(AFS_SE_EXCLUDED, &se_flags);
 
                server = afs_lookup_server(volume->cell, key, &vldb->fs_server[i],
                                           vldb->addr_version[i]);
 
                slist->servers[j].server = server;
                slist->servers[j].volume = volume;
+               slist->servers[j].flags = se_flags;
                slist->nr_servers++;
        }
 
 bool afs_annotate_server_list(struct afs_server_list *new,
                              struct afs_server_list *old)
 {
+       unsigned long mask = 1UL << AFS_SE_EXCLUDED;
        struct afs_server *cur;
        int i, j;
 
-       if (old->nr_servers != new->nr_servers)
+       if (old->nr_servers != new->nr_servers ||
+           old->ro_replicating != new->ro_replicating)
                goto changed;
 
-       for (i = 0; i < old->nr_servers; i++)
+       for (i = 0; i < old->nr_servers; i++) {
                if (old->servers[i].server != new->servers[i].server)
                        goto changed;
-
+               if ((old->servers[i].flags & mask) != (new->servers[i].flags & mask))
+                       goto changed;
+       }
        return false;
 
 changed:
        cur = old->servers[old->preferred].server;
        for (j = 0; j < new->nr_servers; j++) {
                if (new->servers[j].server == cur) {
-                       new->preferred = j;
+                       if (!test_bit(AFS_SE_EXCLUDED, &new->servers[j].flags))
+                               new->preferred = j;
                        break;
                }
        }
 
 {
        struct afs_uvldbentry__xdr *uvldb;
        struct afs_vldb_entry *entry;
-       bool new_only = false;
-       u32 tmp, nr_servers, vlflags;
+       u32 nr_servers, vlflags;
        int i, ret;
 
        _enter("");
        entry->name[i] = 0;
        entry->name_len = strlen(entry->name);
 
-       /* If there is a new replication site that we can use, ignore all the
-        * sites that aren't marked as new.
-        */
-       for (i = 0; i < nr_servers; i++) {
-               tmp = ntohl(uvldb->serverFlags[i]);
-               if (!(tmp & AFS_VLSF_DONTUSE) &&
-                   (tmp & AFS_VLSF_NEWREPSITE))
-                       new_only = true;
-       }
-
        vlflags = ntohl(uvldb->flags);
        for (i = 0; i < nr_servers; i++) {
                struct afs_uuid__xdr *xdr;
                struct afs_uuid *uuid;
+               u32 tmp = ntohl(uvldb->serverFlags[i]);
                int j;
                int n = entry->nr_servers;
 
-               tmp = ntohl(uvldb->serverFlags[i]);
-               if (tmp & AFS_VLSF_DONTUSE ||
-                   (new_only && !(tmp & AFS_VLSF_NEWREPSITE)))
-                       continue;
                if (tmp & AFS_VLSF_RWVOL) {
                        entry->fs_mask[n] |= AFS_VOL_VTM_RW;
                        if (vlflags & AFS_VLF_BACKEXISTS)
                for (j = 0; j < 6; j++)
                        uuid->node[j] = (u8)ntohl(xdr->node[j]);
 
+               entry->vlsf_flags[n] = tmp;
                entry->addr_version[n] = ntohl(uvldb->serverUnique[i]);
                entry->nr_servers++;
        }