diff --git a/src/_zkapauthorizer/_storage_client.py b/src/_zkapauthorizer/_storage_client.py
index eafc1196f95d5a826cc846f079c452b9c91bfd43..8a9acdf15b9dedec2db6226c2932c5f80275f484 100644
--- a/src/_zkapauthorizer/_storage_client.py
+++ b/src/_zkapauthorizer/_storage_client.py
@@ -25,7 +25,10 @@ import attr
 from zope.interface import (
     implementer,
 )
-
+from twisted.internet.defer import (
+    inlineCallbacks,
+    returnValue,
+)
 from allmydata.interfaces import (
     IStorageServer,
 )
@@ -38,6 +41,7 @@ from .storage_common import (
     renew_lease_message,
     slot_testv_and_readv_and_writev_message,
     has_writes,
+    get_implied_data_length,
 )
 
 @implementer(IStorageServer)
@@ -164,6 +168,7 @@ class ZKAPAuthorizerStorageClient(object):
             reason,
         )
 
+    @inlineCallbacks
     def slot_testv_and_readv_and_writev(
             self,
             storage_index,
@@ -172,17 +177,41 @@ class ZKAPAuthorizerStorageClient(object):
             r_vector,
     ):
         if has_writes(tw_vectors):
-            passes = self._get_encoded_passes(slot_testv_and_readv_and_writev_message(storage_index), 1)
+            current_size = yield self._rref.callRemote(
+                "slot_share_sizes",
+                storage_index,
+                set(tw_vectors),
+            )
+            if current_size is None:
+                current_pass_count = 0
+            else:
+                current_pass_count = required_passes(BYTES_PER_PASS, {0}, current_size)
+            new_size = sum(
+                (
+                    get_implied_data_length(data_vector, length)
+                    for (_, data_vector, length)
+                    in tw_vectors.values()
+                ),
+                0,
+            )
+            new_pass_count = required_passes(BYTES_PER_PASS, {0}, new_size)
+            pass_count_increase = new_pass_count - current_pass_count
+            passes = self._get_encoded_passes(
+                slot_testv_and_readv_and_writev_message(storage_index),
+                pass_count_increase,
+            )
         else:
             passes = []
-        return self._rref.callRemote(
-            "slot_testv_and_readv_and_writev",
-            passes,
-            storage_index,
-            secrets,
-            tw_vectors,
-            r_vector,
-        )
+        returnValue((
+            yield self._rref.callRemote(
+                "slot_testv_and_readv_and_writev",
+                passes,
+                storage_index,
+                secrets,
+                tw_vectors,
+                r_vector,
+            )
+        ))
 
     def slot_readv(
             self,
diff --git a/src/_zkapauthorizer/_storage_server.py b/src/_zkapauthorizer/_storage_server.py
index 061d6136125bc20877a4624e97d806e58440e86c..d57fb9c2d9cadb862d68dfa9b07de72416cc8aab 100644
--- a/src/_zkapauthorizer/_storage_server.py
+++ b/src/_zkapauthorizer/_storage_server.py
@@ -24,6 +24,10 @@ from __future__ import (
     absolute_import,
 )
 
+from errno import (
+    ENOENT,
+)
+
 from functools import (
     partial,
 )
@@ -234,6 +238,14 @@ class ZKAPAuthorizerStorageServer(Referenceable):
         """
         return self._original.remote_advise_corrupt_share(*a, **kw)
 
+    def remote_slot_share_sizes(self, storage_index, sharenums):
+        try:
+            return get_slot_share_size(self._original, storage_index, sharenums)
+        except OSError as e:
+            if e.errno == ENOENT:
+                return None
+            raise
+
     def remote_slot_testv_and_readv_and_writev(
             self,
             passes,
diff --git a/src/_zkapauthorizer/foolscap.py b/src/_zkapauthorizer/foolscap.py
index 948aff38eb681754af6e24e57d5252ce34254196..088dbccd0f825265cf94c2788561562a7d11e49e 100644
--- a/src/_zkapauthorizer/foolscap.py
+++ b/src/_zkapauthorizer/foolscap.py
@@ -6,7 +6,9 @@ from foolscap.constraint import (
     ByteStringConstraint,
 )
 from foolscap.api import (
+    SetOf,
     ListOf,
+    ChoiceOf,
 )
 from foolscap.remoteinterface import (
     RemoteMethodSchema,
@@ -14,7 +16,10 @@ from foolscap.remoteinterface import (
 )
 
 from allmydata.interfaces import (
+    MAX_BUCKETS,
+    StorageIndex,
     RIStorageServer,
+    Offset,
 )
 
 # The Foolscap convention seems to be to try to constrain inputs to valid
@@ -110,6 +115,16 @@ class RIPrivacyPassAuthorizedStorageServer(RemoteInterface):
 
     get_buckets = RIStorageServer["get_buckets"]
 
+    def slot_share_sizes(
+            storage_index=StorageIndex,
+            sharenums=SetOf(int, maxLength=MAX_BUCKETS),
+    ):
+        """
+        Get the size of the given shares in the given storage index.  If there are
+        no shares, ``None``.
+        """
+        return ChoiceOf(None, Offset)
+
     slot_readv = RIStorageServer["slot_readv"]
 
     slot_testv_and_readv_and_writev = add_passes(