Repository: googleapis/java-storage
Pull request #1457 (2022-06-16 22:48:15)

docs: Clarified how clients should work with resumable uploads
- [ ] Regenerate this pull request now.

docs: Clarified ListNotifications pagination
docs: Made "live generation" wording consistent with docs for other Cloud Storage APIs
fix: Made negative offsets larger in magnitude that object size return the full object for ReadObject operations
fix: Made naming format for Logging.log_bucket be a path rather than raw bucket name, to be consistent with the rest of the API
feat: Changed Custom Dual Regions to be specified in a proto message rather than a syntactic encoding within the bucket location
feat: Added etag support

PiperOrigin-RevId: 455465509

Source-Link: https://github.com/googleapis/googleapis/commit/0470cd6d5019a397cc132b34551a83d2bc309d35

Source-Link: https://github.com/googleapis/googleapis-gen/commit/1b1667395e707a60abca093e8ffd512f4a0a0116
Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiMWIxNjY3Mzk1ZTcwN2E2MGFiY2EwOTNlOGZmZDUxMmY0YTBhMDExNiJ9


Patch:
diff --git a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java
index 755b46a2..a34219f9 100644
--- a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java
+++ b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java
@@ -2035,8 +2035,8 @@ public class StorageClient implements BackgroundResource {
    *
    * @param object The object to update. The object's bucket and name fields are used to identify
    *     the object to update. If present, the object's generation field selects a specific revision
-   *     of this object whose metadata should be updated. Otherwise, assumes the current, live
-   *     version of the object.
+   *     of this object whose metadata should be updated. Otherwise, assumes the live version of the
+   *     object.
    * @param updateMask List of fields to be updated.
    *     <p>To specify ALL fields, equivalent to the JSON API's "update" function, specify a single
    *     field with the value `&#42;`. Note: not recommended. If a new field is introduced at a
@@ -2125,12 +2125,29 @@ public class StorageClient implements BackgroundResource {
    * preconditions. Additionally, the final message must set 'finish_write' to true, or else it is
    * an error.
    *
-   * <p>For a resumable write, the client should instead call `StartResumableWrite()` and provide
-   * that method an `WriteObjectSpec.` They should then attach the returned `upload_id` to the first
-   * message of each following call to `Create`. If there is an error or the connection is broken
-   * during the resumable `Create()`, the client should check the status of the `Create()` by
-   * calling `QueryWriteStatus()` and continue writing from the returned `persisted_size`. This may
-   * be less than the amount of data the client previously sent.
+   * <p>For a resumable write, the client should instead call `StartResumableWrite()`, populating a
+   * `WriteObjectSpec` into that request. They should then attach the returned `upload_id` to the
+   * first message of each following call to `WriteObject`. If the stream is closed before finishing
+   * the upload (either explicitly by the client or due to a network error or an error response from
+   * the server), the client should do as follows: - Check the result Status of the stream, to
+   * determine if writing can be resumed on this stream or must be restarted from scratch (by
+   * calling `StartResumableWrite()`). The resumable errors are DEADLINE_EXCEEDED, INTERNAL, and
+   * UNAVAILABLE. For each case, the client should use binary exponential backoff before retrying.
+   * Additionally, writes can be resumed after RESOURCE_EXHAUSTED errors, but only after taking
+   * appropriate measures, which may include reducing aggregate send rate across clients and/or
+   * requesting a quota increase for your project. - If the call to `WriteObject` returns `ABORTED`,
+   * that indicates concurrent attempts to update the resumable write, caused either by multiple
+   * racing clients or by a single client where the previous request was timed out on the client
+   * side but nonetheless reached the server. In this case the client should take steps to prevent
+   * further concurrent writes (e.g., increase the timeouts, stop using more than one process to
+   * perform the upload, etc.), and then should follow the steps below for resuming the upload. -
+   * For resumable errors, the client should call `QueryWriteStatus()` and then continue writing
+   * from the returned `persisted_size`. This may be less than the amount of data the client
+   * previously sent. Note also that it is acceptable to send data starting at an offset earlier
+   * than the returned `persisted_size`; in this case, the service will skip data at offsets that
+   * were already persisted (without checking that it matches the previously written data), and
+   * write only the data starting from the persisted offset. This behavior can make client-side
+   * handling simpler in some cases.
    *
    * <p>The service will not view the object as complete until the client has sent a
    * `WriteObjectRequest` with `finish_write` set to `true`. Sending any requests on a stream after
@@ -2138,6 +2155,9 @@ public class StorageClient implements BackgroundResource {
    * &#42;&#42;should&#42;&#42; check the response it receives to determine how much data the
    * service was able to commit and whether the service views the object as complete.
    *
+   * <p>Attempting to resume an already finalized object will result in an OK status, with a
+   * WriteObjectResponse containing the finalized object's metadata.
+   *
    * <p>Sample code:
    *
    * <pre>{@code
diff --git a/grpc-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageGrpc.java b/grpc-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageGrpc.java
index f3774e9a..9ad35499 100644
--- a/grpc-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageGrpc.java
+++ b/grpc-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageGrpc.java
@@ -1579,19 +1579,46 @@ public final class StorageGrpc {
      * preconditions. Additionally, the final message must set 'finish_write' to
      * true, or else it is an error.
      * For a resumable write, the client should instead call
-     * `StartResumableWrite()` and provide that method an `WriteObjectSpec.`
+     * `StartResumableWrite()`, populating a `WriteObjectSpec` into that request.
      * They should then attach the returned `upload_id` to the first message of
-     * each following call to `Create`. If there is an error or the connection is
-     * broken during the resumable `Create()`, the client should check the status
-     * of the `Create()` by calling `QueryWriteStatus()` and continue writing from
-     * the returned `persisted_size`. This may be less than the amount of data the
-     * client previously sent.
+     * each following call to `WriteObject`. If the stream is closed before
+     * finishing the upload (either explicitly by the client or due to a network
+     * error or an error response from the server), the client should do as
+     * follows:
+     *   - Check the result Status of the stream, to determine if writing can be
+     *     resumed on this stream or must be restarted from scratch (by calling
+     *     `StartResumableWrite()`). The resumable errors are DEADLINE_EXCEEDED,
+     *     INTERNAL, and UNAVAILABLE. For each case, the client should use binary
+     *     exponential backoff before retrying.  Additionally, writes can be
+     *     resumed after RESOURCE_EXHAUSTED errors, but only after taking
+     *     appropriate measures, which may include reducing aggregate send rate
+     *     across clients and/or requesting a quota increase for your project.
+     *   - If the call to `WriteObject` returns `ABORTED`, that indicates
+     *     concurrent attempts to update the resumable write, caused either by
+     *     multiple racing clients or by a single client where the previous
+     *     request was timed out on the client side but nonetheless reached the
+     *     server. In this case the client should take steps to prevent further
+     *     concurrent writes (e.g., increase the timeouts, stop using more than
+     *     one process to perform the upload, etc.), and then should follow the
+     *     steps below for resuming the upload.
+     *   - For resumable errors, the client should call `QueryWriteStatus()` and
+     *     then continue writing from the returned `persisted_size`. This may be
+     *     less than the amount of data the client previously sent. Note also that
+     *     it is acceptable to send data starting at an offset earlier than the
+     *     returned `persisted_size`; in this case, the service will skip data at
+     *     offsets that were already persisted (without checking that it matches
+     *     the previously written data), and write only the data starting from the
+     *     persisted offset. This behavior can make client-side handling simpler
+     *     in some cases.
      * The service will not view the object as complete until the client has
      * sent a `WriteObjectRequest` with `finish_write` set to `true`. Sending any
      * requests on a stream after sending a request with `finish_write` set to
      * `true` will cause an error. The client **should** check the response it
      * receives to determine how much data the service was able to commit and
      * whether the service views the object as complete.
+     * Attempting to resume an already finalized object will result in an OK
+     * status, with a WriteObjectResponse containing the finalized object's
+     * metadata.
      * </pre>
      */
     public io.grpc.stub.StreamObserver<com.google.storage.v2.WriteObjectRequest> writeObject(
@@ -2277,19 +2304,46 @@ public final class StorageGrpc {
      * preconditions. Additionally, the final message must set 'finish_write' to
      * true, or else it is an error.
      * For a resumable write, the client should instead call
-     * `StartResumableWrite()` and provide that method an `WriteObjectSpec.`
+     * `StartResumableWrite()`, populating a `WriteObjectSpec` into that request.
      * They should then attach the returned `upload_id` to the first message of
-     * each following call to `Create`. If there is an error or the connection is
-     * broken during the resumable `Create()`, the client should check the status
-     * of the `Create()` by calling `QueryWriteStatus()` and continue writing from
-     * the returned `persisted_size`. This may be less than the amount of data the
-     * client previously sent.
+     * each following call to `WriteObject`. If the stream is closed before
+     * finishing the upload (either explicitly by the client or due to a network
+     * error or an error response from the server), the client should do as
+     * follows:
+     *   - Check the result Status of the stream, to determine if writing can be
+     *     resumed on this stream or must be restarted from scratch (by calling
+     *     `StartResumableWrite()`). The resumable errors are DEADLINE_EXCEEDED,
+     *     INTERNAL, and UNAVAILABLE. For each case, the client should use binary
+     *     exponential backoff before retrying.  Additionally, writes can be
+     *     resumed after RESOURCE_EXHAUSTED errors, but only after taking
+     *     appropriate measures, which may include reducing aggregate send rate
+     *     across clients and/or requesting a quota increase for your project.
+     *   - If the call to `WriteObject` returns `ABORTED`, that indicates
+     *     concurrent attempts to update the resumable write, caused either by
+     *     multiple racing clients or by a single client where the previous
+     *     request was timed out on the client side but nonetheless reached the
+     *     server. In this case the client should take steps to prevent further
+     *     concurrent writes (e.g., increase the timeouts, stop using more than
+     *     one process to perform the upload, etc.), and then should follow the
+     *     steps below for resuming the upload.
+     *   - For resumable errors, the client should call `QueryWriteStatus()` and
+     *     then continue writing from the returned `persisted_size`. This may be
+     *     less than the amount of data the client previously sent. Note also that
+     *     it is acceptable to send data starting at an offset earlier than the
+     *     returned `persisted_size`; in this case, the service will skip data at
+     *     offsets that were already persisted (without checking that it matches
+     *     the previously written data), and write only the data starting from the
+     *     persisted offset. This behavior can make client-side handling simpler
+     *     in some cases.
      * The service will not view the object as complete until the client has
      * sent a `WriteObjectRequest` with `finish_write` set to `true`. Sending any
      * requests on a stream after sending a request with `finish_write` set to
      * `true` will cause an error. The client **should** check the response it
      * receives to determine how much data the service was able to commit and
      * whether the service views the object as complete.
+     * Attempting to resume an already finalized object will result in an OK
+     * status, with a WriteObjectResponse containing the finalized object's
+     * metadata.
      * </pre>
      */
     public io.grpc.stub.StreamObserver<com.google.storage.v2.WriteObjectRequest> writeObject(
diff --git a/proto-google-cloud-storage-v2/clirr-ignored-differences.xml b/proto-google-cloud-storage-v2/clirr-ignored-differences.xml
index af53e7fa..4a3695b3 100644
--- a/proto-google-cloud-storage-v2/clirr-ignored-differences.xml
+++ b/proto-google-cloud-storage-v2/clirr-ignored-differences.xml
@@ -17,4 +17,15 @@
     <method>* *CommonRequestParams*(*)</method>
   </difference>
 
+  <difference>
+    <differenceType>7012</differenceType>
+    <className>com/google/storage/v2/*OrBuilder</className>
+    <method>* *Etag*(*)</method>
+  </difference>
+  <difference>
+    <differenceType>7012</differenceType>
+    <className>com/google/storage/v2/*OrBuilder</className>
+    <method>* *CustomPlacementConfig*(*)</method>
+  </difference>
+
 </differences>
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Bucket.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Bucket.java
index c5893b6f..1c12c9dd 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Bucket.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Bucket.java
@@ -40,6 +40,7 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
   private Bucket() {
     name_ = "";
     bucketId_ = "";
+    etag_ = "";
     project_ = "";
     location_ = "";
     locationType_ = "";
@@ -353,6 +354,23 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
           case 200:
             {
               satisfiesPzs_ = input.readBool();
+              break;
+            }
+          case 210:
+            {
+              com.google.storage.v2.Bucket.CustomPlacementConfig.Builder subBuilder = null;
+              if (customPlacementConfig_ != null) {
+                subBuilder = customPlacementConfig_.toBuilder();
+              }
+              customPlacementConfig_ =
+                  input.readMessage(
+                      com.google.storage.v2.Bucket.CustomPlacementConfig.parser(),
+                      extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(customPlacementConfig_);
+                customPlacementConfig_ = subBuilder.buildPartial();
+              }
+
               break;
             }
           case 218:
@@ -376,6 +394,13 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
                 autoclass_ = subBuilder.buildPartial();
               }
 
+              break;
+            }
+          case 234:
+            {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              etag_ = s;
               break;
             }
           default:
@@ -11600,7 +11625,8 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
      *
      *
      * <pre>
-     * The destination bucket where the current bucket's logs should be placed.
+     * The destination bucket where the current bucket's logs should be placed,
+     * using path format (like `projects/123456/buckets/foo`).
      * </pre>
      *
      * <code>string log_bucket = 1;</code>
@@ -11612,7 +11638,8 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
      *
      *
      * <pre>
-     * The destination bucket where the current bucket's logs should be placed.
+     * The destination bucket where the current bucket's logs should be placed,
+     * using path format (like `projects/123456/buckets/foo`).
      * </pre>
      *
      * <code>string log_bucket = 1;</code>
@@ -11755,7 +11782,8 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
      *
      *
      * <pre>
-     * The destination bucket where the current bucket's logs should be placed.
+     * The destination bucket where the current bucket's logs should be placed,
+     * using path format (like `projects/123456/buckets/foo`).
      * </pre>
      *
      * <code>string log_bucket = 1;</code>
@@ -11778,7 +11806,8 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
      *
      *
      * <pre>
-     * The destination bucket where the current bucket's logs should be placed.
+     * The destination bucket where the current bucket's logs should be placed,
+     * using path format (like `projects/123456/buckets/foo`).
      * </pre>
      *
      * <code>string log_bucket = 1;</code>
@@ -12187,7 +12216,8 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
        *
        *
        * <pre>
-       * The destination bucket where the current bucket's logs should be placed.
+       * The destination bucket where the current bucket's logs should be placed,
+       * using path format (like `projects/123456/buckets/foo`).
        * </pre>
        *
        * <code>string log_bucket = 1;</code>
@@ -12209,7 +12239,8 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
        *
        *
        * <pre>
-       * The destination bucket where the current bucket's logs should be placed.
+       * The destination bucket where the current bucket's logs should be placed,
+       * using path format (like `projects/123456/buckets/foo`).
        * </pre>
        *
        * <code>string log_bucket = 1;</code>
@@ -12231,7 +12262,8 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
        *
        *
        * <pre>
-       * The destination bucket where the current bucket's logs should be placed.
+       * The destination bucket where the current bucket's logs should be placed,
+       * using path format (like `projects/123456/buckets/foo`).
        * </pre>
        *
        * <code>string log_bucket = 1;</code>
@@ -12252,7 +12284,8 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
        *
        *
        * <pre>
-       * The destination bucket where the current bucket's logs should be placed.
+       * The destination bucket where the current bucket's logs should be placed,
+       * using path format (like `projects/123456/buckets/foo`).
        * </pre>
        *
        * <code>string log_bucket = 1;</code>
@@ -12269,7 +12302,8 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
        *
        *
        * <pre>
-       * The destination bucket where the current bucket's logs should be placed.
+       * The destination bucket where the current bucket's logs should be placed,
+       * using path format (like `projects/123456/buckets/foo`).
        * </pre>
        *
        * <code>string log_bucket = 1;</code>
@@ -14915,99 +14949,91 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
     }
   }
 
-  public interface AutoclassOrBuilder
+  public interface CustomPlacementConfigOrBuilder
       extends
-      // @@protoc_insertion_point(interface_extends:google.storage.v2.Bucket.Autoclass)
+      // @@protoc_insertion_point(interface_extends:google.storage.v2.Bucket.CustomPlacementConfig)
       com.google.protobuf.MessageOrBuilder {
 
     /**
      *
      *
      * <pre>
-     * Enables Autoclass.
+     * List of locations to use for data placement.
      * </pre>
      *
-     * <code>bool enabled = 1;</code>
+     * <code>repeated string data_locations = 1;</code>
      *
-     * @return The enabled.
+     * @return A list containing the dataLocations.
      */
-    boolean getEnabled();
-
+    java.util.List<java.lang.String> getDataLocationsList();
     /**
      *
      *
      * <pre>
-     * Output only. Latest instant at which the `enabled` field was set to true after being
-     * disabled/unconfigured or set to false after being enabled. If Autoclass
-     * is enabled when the bucket is created, the toggle_time is set to the
-     * bucket creation time.
+     * List of locations to use for data placement.
      * </pre>
      *
-     * <code>
-     * .google.protobuf.Timestamp toggle_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];
-     * </code>
+     * <code>repeated string data_locations = 1;</code>
      *
-     * @return Whether the toggleTime field is set.
+     * @return The count of dataLocations.
      */
-    boolean hasToggleTime();
+    int getDataLocationsCount();
     /**
      *
      *
      * <pre>
-     * Output only. Latest instant at which the `enabled` field was set to true after being
-     * disabled/unconfigured or set to false after being enabled. If Autoclass
-     * is enabled when the bucket is created, the toggle_time is set to the
-     * bucket creation time.
+     * List of locations to use for data placement.
      * </pre>
      *
-     * <code>
-     * .google.protobuf.Timestamp toggle_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];
-     * </code>
+     * <code>repeated string data_locations = 1;</code>
      *
-     * @return The toggleTime.
+     * @param index The index of the element to return.
+     * @return The dataLocations at the given index.
      */
-    com.google.protobuf.Timestamp getToggleTime();
+    java.lang.String getDataLocations(int index);
     /**
      *
      *
      * <pre>
-     * Output only. Latest instant at which the `enabled` field was set to true after being
-     * disabled/unconfigured or set to false after being enabled. If Autoclass
-     * is enabled when the bucket is created, the toggle_time is set to the
-     * bucket creation time.
+     * List of locations to use for data placement.
      * </pre>
      *
-     * <code>
-     * .google.protobuf.Timestamp toggle_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];
-     * </code>
+     * <code>repeated string data_locations = 1;</code>
+     *
+     * @param index The index of the value to return.
+     * @return The bytes of the dataLocations at the given index.
      */
-    com.google.protobuf.TimestampOrBuilder getToggleTimeOrBuilder();
+    com.google.protobuf.ByteString getDataLocationsBytes(int index);
   }
   /**
    *
    *
    * <pre>
-   * Configuration for a bucket's Autoclass feature.
+   * Configuration for Custom Dual Regions.  It should specify precisely two
+   * eligible regions within the same Multiregion. More information on regions
+   * may be found [https://cloud.google.com/storage/docs/locations][here].
    * </pre>
    *
-   * Protobuf type {@code google.storage.v2.Bucket.Autoclass}
+   * Protobuf type {@code google.storage.v2.Bucket.CustomPlacementConfig}
    */
-  public static final class Autoclass extends com.google.protobuf.GeneratedMessageV3
+  public static final class CustomPlacementConfig extends com.google.protobuf.GeneratedMessageV3
       implements
-      // @@protoc_insertion_point(message_implements:google.storage.v2.Bucket.Autoclass)
-      AutoclassOrBuilder {
+      // @@protoc_insertion_point(message_implements:google.storage.v2.Bucket.CustomPlacementConfig)
+      CustomPlacementConfigOrBuilder {
     private static final long serialVersionUID = 0L;
-    // Use Autoclass.newBuilder() to construct.
-    private Autoclass(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    // Use CustomPlacementConfig.newBuilder() to construct.
+    private CustomPlacementConfig(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
       super(builder);
     }
 
-    private Autoclass() {}
+    private CustomPlacementConfig() {
+      dataLocations_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+    }
 
     @java.lang.Override
     @SuppressWarnings({"unused"})
     protected java.lang.Object newInstance(UnusedPrivateParameter unused) {
-      return new Autoclass();
+      return new CustomPlacementConfig();
     }
 
     @java.lang.Override
@@ -15015,7 +15041,7 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       return this.unknownFields;
     }
 
-    private Autoclass(
+    private CustomPlacementConfig(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -15023,6 +15049,7 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       if (extensionRegistry == null) {
         throw new java.lang.NullPointerException();
       }
+      int mutable_bitField0_ = 0;
       com.google.protobuf.UnknownFieldSet.Builder unknownFields =
           com.google.protobuf.UnknownFieldSet.newBuilder();
       try {
@@ -15033,24 +15060,14 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
             case 0:
               done = true;
               break;
-            case 8:
-              {
-                enabled_ = input.readBool();
-                break;
-              }
-            case 18:
+            case 10:
               {
-                com.google.protobuf.Timestamp.Builder subBuilder = null;
-                if (toggleTime_ != null) {
-                  subBuilder = toggleTime_.toBuilder();
-                }
-                toggleTime_ =
-                    input.readMessage(com.google.protobuf.Timestamp.parser(), extensionRegistry);
-                if (subBuilder != null) {
-                  subBuilder.mergeFrom(toggleTime_);
-                  toggleTime_ = subBuilder.buildPartial();
+                java.lang.String s = input.readStringRequireUtf8();
+                if (!((mutable_bitField0_ & 0x00000001) != 0)) {
+                  dataLocations_ = new com.google.protobuf.LazyStringArrayList();
+                  mutable_bitField0_ |= 0x00000001;
                 }
-
+                dataLocations_.add(s);
                 break;
               }
             default:
@@ -15069,6 +15086,9 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       } catch (java.io.IOException e) {
         throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this);
       } finally {
+        if (((mutable_bitField0_ & 0x00000001) != 0)) {
+          dataLocations_ = dataLocations_.getUnmodifiableView();
+        }
         this.unknownFields = unknownFields.build();
         makeExtensionsImmutable();
       }
@@ -15076,96 +15096,78 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
 
     public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
       return com.google.storage.v2.StorageProto
-          .internal_static_google_storage_v2_Bucket_Autoclass_descriptor;
+          .internal_static_google_storage_v2_Bucket_CustomPlacementConfig_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
         internalGetFieldAccessorTable() {
       return com.google.storage.v2.StorageProto
-          .internal_static_google_storage_v2_Bucket_Autoclass_fieldAccessorTable
+          .internal_static_google_storage_v2_Bucket_CustomPlacementConfig_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              com.google.storage.v2.Bucket.Autoclass.class,
-              com.google.storage.v2.Bucket.Autoclass.Builder.class);
+              com.google.storage.v2.Bucket.CustomPlacementConfig.class,
+              com.google.storage.v2.Bucket.CustomPlacementConfig.Builder.class);
     }
 
-    public static final int ENABLED_FIELD_NUMBER = 1;
-    private boolean enabled_;
+    public static final int DATA_LOCATIONS_FIELD_NUMBER = 1;
+    private com.google.protobuf.LazyStringList dataLocations_;
     /**
      *
      *
      * <pre>
-     * Enables Autoclass.
+     * List of locations to use for data placement.
      * </pre>
      *
-     * <code>bool enabled = 1;</code>
+     * <code>repeated string data_locations = 1;</code>
      *
-     * @return The enabled.
+     * @return A list containing the dataLocations.
      */
-    @java.lang.Override
-    public boolean getEnabled() {
-      return enabled_;
+    public com.google.protobuf.ProtocolStringList getDataLocationsList() {
+      return dataLocations_;
     }
-
-    public static final int TOGGLE_TIME_FIELD_NUMBER = 2;
-    private com.google.protobuf.Timestamp toggleTime_;
     /**
      *
      *
      * <pre>
-     * Output only. Latest instant at which the `enabled` field was set to true after being
-     * disabled/unconfigured or set to false after being enabled. If Autoclass
-     * is enabled when the bucket is created, the toggle_time is set to the
-     * bucket creation time.
+     * List of locations to use for data placement.
      * </pre>
      *
-     * <code>
-     * .google.protobuf.Timestamp toggle_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];
-     * </code>
+     * <code>repeated string data_locations = 1;</code>
      *
-     * @return Whether the toggleTime field is set.
+     * @return The count of dataLocations.
      */
-    @java.lang.Override
-    public boolean hasToggleTime() {
-      return toggleTime_ != null;
+    public int getDataLocationsCount() {
+      return dataLocations_.size();
     }
     /**
      *
      *
      * <pre>
-     * Output only. Latest instant at which the `enabled` field was set to true after being
-     * disabled/unconfigured or set to false after being enabled. If Autoclass
-     * is enabled when the bucket is created, the toggle_time is set to the
-     * bucket creation time.
+     * List of locations to use for data placement.
      * </pre>
      *
-     * <code>
-     * .google.protobuf.Timestamp toggle_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];
-     * </code>
+     * <code>repeated string data_locations = 1;</code>
      *
-     * @return The toggleTime.
+     * @param index The index of the element to return.
+     * @return The dataLocations at the given index.
      */
-    @java.lang.Override
-    public com.google.protobuf.Timestamp getToggleTime() {
-      return toggleTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : toggleTime_;
+    public java.lang.String getDataLocations(int index) {
+      return dataLocations_.get(index);
     }
     /**
      *
      *
      * <pre>
-     * Output only. Latest instant at which the `enabled` field was set to true after being
-     * disabled/unconfigured or set to false after being enabled. If Autoclass
-     * is enabled when the bucket is created, the toggle_time is set to the
-     * bucket creation time.
+     * List of locations to use for data placement.
      * </pre>
      *
-     * <code>
-     * .google.protobuf.Timestamp toggle_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];
-     * </code>
+     * <code>repeated string data_locations = 1;</code>
+     *
+     * @param index The index of the value to return.
+     * @return The bytes of the dataLocations at the given index.
      */
-    @java.lang.Override
-    public com.google.protobuf.TimestampOrBuilder getToggleTimeOrBuilder() {
-      return getToggleTime();
+    public com.google.protobuf.ByteString getDataLocationsBytes(int index) {
+      return dataLocations_.getByteString(index);
     }
 
     private byte memoizedIsInitialized = -1;
@@ -15182,11 +15184,8 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
 
     @java.lang.Override
     public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
-      if (enabled_ != false) {
-        output.writeBool(1, enabled_);
-      }
-      if (toggleTime_ != null) {
-        output.writeMessage(2, getToggleTime());
+      for (int i = 0; i < dataLocations_.size(); i++) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 1, dataLocations_.getRaw(i));
       }
       unknownFields.writeTo(output);
     }
@@ -15197,11 +15196,13 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       if (size != -1) return size;
 
       size = 0;
-      if (enabled_ != false) {
-        size += com.google.protobuf.CodedOutputStream.computeBoolSize(1, enabled_);
-      }
-      if (toggleTime_ != null) {
-        size += com.google.protobuf.CodedOutputStream.computeMessageSize(2, getToggleTime());
+      {
+        int dataSize = 0;
+        for (int i = 0; i < dataLocations_.size(); i++) {
+          dataSize += computeStringSizeNoTag(dataLocations_.getRaw(i));
+        }
+        size += dataSize;
+        size += 1 * getDataLocationsList().size();
       }
       size += unknownFields.getSerializedSize();
       memoizedSize = size;
@@ -15213,16 +15214,13 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       if (obj == this) {
         return true;
       }
-      if (!(obj instanceof com.google.storage.v2.Bucket.Autoclass)) {
+      if (!(obj instanceof com.google.storage.v2.Bucket.CustomPlacementConfig)) {
         return super.equals(obj);
       }
-      com.google.storage.v2.Bucket.Autoclass other = (com.google.storage.v2.Bucket.Autoclass) obj;
+      com.google.storage.v2.Bucket.CustomPlacementConfig other =
+          (com.google.storage.v2.Bucket.CustomPlacementConfig) obj;
 
-      if (getEnabled() != other.getEnabled()) return false;
-      if (hasToggleTime() != other.hasToggleTime()) return false;
-      if (hasToggleTime()) {
-        if (!getToggleTime().equals(other.getToggleTime())) return false;
-      }
+      if (!getDataLocationsList().equals(other.getDataLocationsList())) return false;
       if (!unknownFields.equals(other.unknownFields)) return false;
       return true;
     }
@@ -15234,82 +15232,80 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       }
       int hash = 41;
       hash = (19 * hash) + getDescriptor().hashCode();
-      hash = (37 * hash) + ENABLED_FIELD_NUMBER;
-      hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(getEnabled());
-      if (hasToggleTime()) {
-        hash = (37 * hash) + TOGGLE_TIME_FIELD_NUMBER;
-        hash = (53 * hash) + getToggleTime().hashCode();
+      if (getDataLocationsCount() > 0) {
+        hash = (37 * hash) + DATA_LOCATIONS_FIELD_NUMBER;
+        hash = (53 * hash) + getDataLocationsList().hashCode();
       }
       hash = (29 * hash) + unknownFields.hashCode();
       memoizedHashCode = hash;
       return hash;
     }
 
-    public static com.google.storage.v2.Bucket.Autoclass parseFrom(java.nio.ByteBuffer data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig parseFrom(
+        java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
 
-    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig parseFrom(
         java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
 
-    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
 
-    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
 
-    public static com.google.storage.v2.Bucket.Autoclass parseFrom(byte[] data)
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
 
-    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig parseFrom(
         byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
 
-    public static com.google.storage.v2.Bucket.Autoclass parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig parseFrom(
+        java.io.InputStream input) throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
     }
 
-    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig parseFrom(
         java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
           PARSER, input, extensionRegistry);
     }
 
-    public static com.google.storage.v2.Bucket.Autoclass parseDelimitedFrom(
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig parseDelimitedFrom(
         java.io.InputStream input) throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input);
     }
 
-    public static com.google.storage.v2.Bucket.Autoclass parseDelimitedFrom(
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig parseDelimitedFrom(
         java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(
           PARSER, input, extensionRegistry);
     }
 
-    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig parseFrom(
         com.google.protobuf.CodedInputStream input) throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
     }
 
-    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -15326,7 +15322,7 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       return DEFAULT_INSTANCE.toBuilder();
     }
 
-    public static Builder newBuilder(com.google.storage.v2.Bucket.Autoclass prototype) {
+    public static Builder newBuilder(com.google.storage.v2.Bucket.CustomPlacementConfig prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
 
@@ -15345,32 +15341,34 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
      *
      *
      * <pre>
-     * Configuration for a bucket's Autoclass feature.
+     * Configuration for Custom Dual Regions.  It should specify precisely two
+     * eligible regions within the same Multiregion. More information on regions
+     * may be found [https://cloud.google.com/storage/docs/locations][here].
      * </pre>
      *
-     * Protobuf type {@code google.storage.v2.Bucket.Autoclass}
+     * Protobuf type {@code google.storage.v2.Bucket.CustomPlacementConfig}
      */
     public static final class Builder
         extends com.google.protobuf.GeneratedMessageV3.Builder<Builder>
         implements
-        // @@protoc_insertion_point(builder_implements:google.storage.v2.Bucket.Autoclass)
-        com.google.storage.v2.Bucket.AutoclassOrBuilder {
+        // @@protoc_insertion_point(builder_implements:google.storage.v2.Bucket.CustomPlacementConfig)
+        com.google.storage.v2.Bucket.CustomPlacementConfigOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
         return com.google.storage.v2.StorageProto
-            .internal_static_google_storage_v2_Bucket_Autoclass_descriptor;
+            .internal_static_google_storage_v2_Bucket_CustomPlacementConfig_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
           internalGetFieldAccessorTable() {
         return com.google.storage.v2.StorageProto
-            .internal_static_google_storage_v2_Bucket_Autoclass_fieldAccessorTable
+            .internal_static_google_storage_v2_Bucket_CustomPlacementConfig_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                com.google.storage.v2.Bucket.Autoclass.class,
-                com.google.storage.v2.Bucket.Autoclass.Builder.class);
+                com.google.storage.v2.Bucket.CustomPlacementConfig.class,
+                com.google.storage.v2.Bucket.CustomPlacementConfig.Builder.class);
       }
 
-      // Construct using com.google.storage.v2.Bucket.Autoclass.newBuilder()
+      // Construct using com.google.storage.v2.Bucket.CustomPlacementConfig.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -15387,31 +15385,25 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       @java.lang.Override
       public Builder clear() {
         super.clear();
-        enabled_ = false;
-
-        if (toggleTimeBuilder_ == null) {
-          toggleTime_ = null;
-        } else {
-          toggleTime_ = null;
-          toggleTimeBuilder_ = null;
-        }
+        dataLocations_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000001);
         return this;
       }
 
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
         return com.google.storage.v2.StorageProto
-            .internal_static_google_storage_v2_Bucket_Autoclass_descriptor;
+            .internal_static_google_storage_v2_Bucket_CustomPlacementConfig_descriptor;
       }
 
       @java.lang.Override
-      public com.google.storage.v2.Bucket.Autoclass getDefaultInstanceForType() {
-        return com.google.storage.v2.Bucket.Autoclass.getDefaultInstance();
+      public com.google.storage.v2.Bucket.CustomPlacementConfig getDefaultInstanceForType() {
+        return com.google.storage.v2.Bucket.CustomPlacementConfig.getDefaultInstance();
       }
 
       @java.lang.Override
-      public com.google.storage.v2.Bucket.Autoclass build() {
-        com.google.storage.v2.Bucket.Autoclass result = buildPartial();
+      public com.google.storage.v2.Bucket.CustomPlacementConfig build() {
+        com.google.storage.v2.Bucket.CustomPlacementConfig result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -15419,15 +15411,15 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       }
 
       @java.lang.Override
-      public com.google.storage.v2.Bucket.Autoclass buildPartial() {
-        com.google.storage.v2.Bucket.Autoclass result =
-            new com.google.storage.v2.Bucket.Autoclass(this);
-        result.enabled_ = enabled_;
-        if (toggleTimeBuilder_ == null) {
-          result.toggleTime_ = toggleTime_;
-        } else {
-          result.toggleTime_ = toggleTimeBuilder_.build();
+      public com.google.storage.v2.Bucket.CustomPlacementConfig buildPartial() {
+        com.google.storage.v2.Bucket.CustomPlacementConfig result =
+            new com.google.storage.v2.Bucket.CustomPlacementConfig(this);
+        int from_bitField0_ = bitField0_;
+        if (((bitField0_ & 0x00000001) != 0)) {
+          dataLocations_ = dataLocations_.getUnmodifiableView();
+          bitField0_ = (bitField0_ & ~0x00000001);
         }
+        result.dataLocations_ = dataLocations_;
         onBuilt();
         return result;
       }
@@ -15469,21 +15461,26 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
 
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof com.google.storage.v2.Bucket.Autoclass) {
-          return mergeFrom((com.google.storage.v2.Bucket.Autoclass) other);
+        if (other instanceof com.google.storage.v2.Bucket.CustomPlacementConfig) {
+          return mergeFrom((com.google.storage.v2.Bucket.CustomPlacementConfig) other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(com.google.storage.v2.Bucket.Autoclass other) {
-        if (other == com.google.storage.v2.Bucket.Autoclass.getDefaultInstance()) return this;
-        if (other.getEnabled() != false) {
-          setEnabled(other.getEnabled());
-        }
-        if (other.hasToggleTime()) {
-          mergeToggleTime(other.getToggleTime());
+      public Builder mergeFrom(com.google.storage.v2.Bucket.CustomPlacementConfig other) {
+        if (other == com.google.storage.v2.Bucket.CustomPlacementConfig.getDefaultInstance())
+          return this;
+        if (!other.dataLocations_.isEmpty()) {
+          if (dataLocations_.isEmpty()) {
+            dataLocations_ = other.dataLocations_;
+            bitField0_ = (bitField0_ & ~0x00000001);
+          } else {
+            ensureDataLocationsIsMutable();
+            dataLocations_.addAll(other.dataLocations_);
+          }
+          onChanged();
         }
         this.mergeUnknownFields(other.unknownFields);
         onChanged();
@@ -15500,11 +15497,12 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        com.google.storage.v2.Bucket.Autoclass parsedMessage = null;
+        com.google.storage.v2.Bucket.CustomPlacementConfig parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (com.google.storage.v2.Bucket.Autoclass) e.getUnfinishedMessage();
+          parsedMessage =
+              (com.google.storage.v2.Bucket.CustomPlacementConfig) e.getUnfinishedMessage();
           throw e.unwrapIOException();
         } finally {
           if (parsedMessage != null) {
@@ -15514,54 +15512,875 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
         return this;
       }
 
-      private boolean enabled_;
+      private int bitField0_;
+
+      private com.google.protobuf.LazyStringList dataLocations_ =
+          com.google.protobuf.LazyStringArrayList.EMPTY;
+
+      private void ensureDataLocationsIsMutable() {
+        if (!((bitField0_ & 0x00000001) != 0)) {
+          dataLocations_ = new com.google.protobuf.LazyStringArrayList(dataLocations_);
+          bitField0_ |= 0x00000001;
+        }
+      }
       /**
        *
        *
        * <pre>
-       * Enables Autoclass.
+       * List of locations to use for data placement.
        * </pre>
        *
-       * <code>bool enabled = 1;</code>
+       * <code>repeated string data_locations = 1;</code>
        *
-       * @return The enabled.
+       * @return A list containing the dataLocations.
        */
-      @java.lang.Override
-      public boolean getEnabled() {
-        return enabled_;
+      public com.google.protobuf.ProtocolStringList getDataLocationsList() {
+        return dataLocations_.getUnmodifiableView();
       }
       /**
        *
        *
        * <pre>
-       * Enables Autoclass.
+       * List of locations to use for data placement.
        * </pre>
        *
-       * <code>bool enabled = 1;</code>
+       * <code>repeated string data_locations = 1;</code>
        *
-       * @param value The enabled to set.
-       * @return This builder for chaining.
+       * @return The count of dataLocations.
        */
-      public Builder setEnabled(boolean value) {
-
-        enabled_ = value;
-        onChanged();
-        return this;
+      public int getDataLocationsCount() {
+        return dataLocations_.size();
       }
       /**
        *
        *
        * <pre>
-       * Enables Autoclass.
+       * List of locations to use for data placement.
        * </pre>
        *
-       * <code>bool enabled = 1;</code>
+       * <code>repeated string data_locations = 1;</code>
        *
-       * @return This builder for chaining.
+       * @param index The index of the element to return.
+       * @return The dataLocations at the given index.
        */
-      public Builder clearEnabled() {
-
-        enabled_ = false;
+      public java.lang.String getDataLocations(int index) {
+        return dataLocations_.get(index);
+      }
+      /**
+       *
+       *
+       * <pre>
+       * List of locations to use for data placement.
+       * </pre>
+       *
+       * <code>repeated string data_locations = 1;</code>
+       *
+       * @param index The index of the value to return.
+       * @return The bytes of the dataLocations at the given index.
+       */
+      public com.google.protobuf.ByteString getDataLocationsBytes(int index) {
+        return dataLocations_.getByteString(index);
+      }
+      /**
+       *
+       *
+       * <pre>
+       * List of locations to use for data placement.
+       * </pre>
+       *
+       * <code>repeated string data_locations = 1;</code>
+       *
+       * @param index The index to set the value at.
+       * @param value The dataLocations to set.
+       * @return This builder for chaining.
+       */
+      public Builder setDataLocations(int index, java.lang.String value) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureDataLocationsIsMutable();
+        dataLocations_.set(index, value);
+        onChanged();
+        return this;
+      }
+      /**
+       *
+       *
+       * <pre>
+       * List of locations to use for data placement.
+       * </pre>
+       *
+       * <code>repeated string data_locations = 1;</code>
+       *
+       * @param value The dataLocations to add.
+       * @return This builder for chaining.
+       */
+      public Builder addDataLocations(java.lang.String value) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureDataLocationsIsMutable();
+        dataLocations_.add(value);
+        onChanged();
+        return this;
+      }
+      /**
+       *
+       *
+       * <pre>
+       * List of locations to use for data placement.
+       * </pre>
+       *
+       * <code>repeated string data_locations = 1;</code>
+       *
+       * @param values The dataLocations to add.
+       * @return This builder for chaining.
+       */
+      public Builder addAllDataLocations(java.lang.Iterable<java.lang.String> values) {
+        ensureDataLocationsIsMutable();
+        com.google.protobuf.AbstractMessageLite.Builder.addAll(values, dataLocations_);
+        onChanged();
+        return this;
+      }
+      /**
+       *
+       *
+       * <pre>
+       * List of locations to use for data placement.
+       * </pre>
+       *
+       * <code>repeated string data_locations = 1;</code>
+       *
+       * @return This builder for chaining.
+       */
+      public Builder clearDataLocations() {
+        dataLocations_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        onChanged();
+        return this;
+      }
+      /**
+       *
+       *
+       * <pre>
+       * List of locations to use for data placement.
+       * </pre>
+       *
+       * <code>repeated string data_locations = 1;</code>
+       *
+       * @param value The bytes of the dataLocations to add.
+       * @return This builder for chaining.
+       */
+      public Builder addDataLocationsBytes(com.google.protobuf.ByteString value) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        checkByteStringIsUtf8(value);
+        ensureDataLocationsIsMutable();
+        dataLocations_.add(value);
+        onChanged();
+        return this;
+      }
+
+      @java.lang.Override
+      public final Builder setUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return super.setUnknownFields(unknownFields);
+      }
+
+      @java.lang.Override
+      public final Builder mergeUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return super.mergeUnknownFields(unknownFields);
+      }
+
+      // @@protoc_insertion_point(builder_scope:google.storage.v2.Bucket.CustomPlacementConfig)
+    }
+
+    // @@protoc_insertion_point(class_scope:google.storage.v2.Bucket.CustomPlacementConfig)
+    private static final com.google.storage.v2.Bucket.CustomPlacementConfig DEFAULT_INSTANCE;
+
+    static {
+      DEFAULT_INSTANCE = new com.google.storage.v2.Bucket.CustomPlacementConfig();
+    }
+
+    public static com.google.storage.v2.Bucket.CustomPlacementConfig getDefaultInstance() {
+      return DEFAULT_INSTANCE;
+    }
+
+    private static final com.google.protobuf.Parser<CustomPlacementConfig> PARSER =
+        new com.google.protobuf.AbstractParser<CustomPlacementConfig>() {
+          @java.lang.Override
+          public CustomPlacementConfig parsePartialFrom(
+              com.google.protobuf.CodedInputStream input,
+              com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+              throws com.google.protobuf.InvalidProtocolBufferException {
+            return new CustomPlacementConfig(input, extensionRegistry);
+          }
+        };
+
+    public static com.google.protobuf.Parser<CustomPlacementConfig> parser() {
+      return PARSER;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<CustomPlacementConfig> getParserForType() {
+      return PARSER;
+    }
+
+    @java.lang.Override
+    public com.google.storage.v2.Bucket.CustomPlacementConfig getDefaultInstanceForType() {
+      return DEFAULT_INSTANCE;
+    }
+  }
+
+  public interface AutoclassOrBuilder
+      extends
+      // @@protoc_insertion_point(interface_extends:google.storage.v2.Bucket.Autoclass)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     *
+     *
+     * <pre>
+     * Enables Autoclass.
+     * </pre>
+     *
+     * <code>bool enabled = 1;</code>
+     *
+     * @return The enabled.
+     */
+    boolean getEnabled();
+
+    /**
+     *
+     *
+     * <pre>
+     * Output only. Latest instant at which the `enabled` field was set to true after being
+     * disabled/unconfigured or set to false after being enabled. If Autoclass
+     * is enabled when the bucket is created, the toggle_time is set to the
+     * bucket creation time.
+     * </pre>
+     *
+     * <code>
+     * .google.protobuf.Timestamp toggle_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     *
+     * @return Whether the toggleTime field is set.
+     */
+    boolean hasToggleTime();
+    /**
+     *
+     *
+     * <pre>
+     * Output only. Latest instant at which the `enabled` field was set to true after being
+     * disabled/unconfigured or set to false after being enabled. If Autoclass
+     * is enabled when the bucket is created, the toggle_time is set to the
+     * bucket creation time.
+     * </pre>
+     *
+     * <code>
+     * .google.protobuf.Timestamp toggle_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     *
+     * @return The toggleTime.
+     */
+    com.google.protobuf.Timestamp getToggleTime();
+    /**
+     *
+     *
+     * <pre>
+     * Output only. Latest instant at which the `enabled` field was set to true after being
+     * disabled/unconfigured or set to false after being enabled. If Autoclass
+     * is enabled when the bucket is created, the toggle_time is set to the
+     * bucket creation time.
+     * </pre>
+     *
+     * <code>
+     * .google.protobuf.Timestamp toggle_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    com.google.protobuf.TimestampOrBuilder getToggleTimeOrBuilder();
+  }
+  /**
+   *
+   *
+   * <pre>
+   * Configuration for a bucket's Autoclass feature.
+   * </pre>
+   *
+   * Protobuf type {@code google.storage.v2.Bucket.Autoclass}
+   */
+  public static final class Autoclass extends com.google.protobuf.GeneratedMessageV3
+      implements
+      // @@protoc_insertion_point(message_implements:google.storage.v2.Bucket.Autoclass)
+      AutoclassOrBuilder {
+    private static final long serialVersionUID = 0L;
+    // Use Autoclass.newBuilder() to construct.
+    private Autoclass(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+      super(builder);
+    }
+
+    private Autoclass() {}
+
+    @java.lang.Override
+    @SuppressWarnings({"unused"})
+    protected java.lang.Object newInstance(UnusedPrivateParameter unused) {
+      return new Autoclass();
+    }
+
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet getUnknownFields() {
+      return this.unknownFields;
+    }
+
+    private Autoclass(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      this();
+      if (extensionRegistry == null) {
+        throw new java.lang.NullPointerException();
+      }
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            case 8:
+              {
+                enabled_ = input.readBool();
+                break;
+              }
+            case 18:
+              {
+                com.google.protobuf.Timestamp.Builder subBuilder = null;
+                if (toggleTime_ != null) {
+                  subBuilder = toggleTime_.toBuilder();
+                }
+                toggleTime_ =
+                    input.readMessage(com.google.protobuf.Timestamp.parser(), extensionRegistry);
+                if (subBuilder != null) {
+                  subBuilder.mergeFrom(toggleTime_);
+                  toggleTime_ = subBuilder.buildPartial();
+                }
+
+                break;
+              }
+            default:
+              {
+                if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) {
+                  done = true;
+                }
+                break;
+              }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (com.google.protobuf.UninitializedMessageException e) {
+        throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+
+    public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+      return com.google.storage.v2.StorageProto
+          .internal_static_google_storage_v2_Bucket_Autoclass_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.google.storage.v2.StorageProto
+          .internal_static_google_storage_v2_Bucket_Autoclass_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.google.storage.v2.Bucket.Autoclass.class,
+              com.google.storage.v2.Bucket.Autoclass.Builder.class);
+    }
+
+    public static final int ENABLED_FIELD_NUMBER = 1;
+    private boolean enabled_;
+    /**
+     *
+     *
+     * <pre>
+     * Enables Autoclass.
+     * </pre>
+     *
+     * <code>bool enabled = 1;</code>
+     *
+     * @return The enabled.
+     */
+    @java.lang.Override
+    public boolean getEnabled() {
+      return enabled_;
+    }
+
+    public static final int TOGGLE_TIME_FIELD_NUMBER = 2;
+    private com.google.protobuf.Timestamp toggleTime_;
+    /**
+     *
+     *
+     * <pre>
+     * Output only. Latest instant at which the `enabled` field was set to true after being
+     * disabled/unconfigured or set to false after being enabled. If Autoclass
+     * is enabled when the bucket is created, the toggle_time is set to the
+     * bucket creation time.
+     * </pre>
+     *
+     * <code>
+     * .google.protobuf.Timestamp toggle_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     *
+     * @return Whether the toggleTime field is set.
+     */
+    @java.lang.Override
+    public boolean hasToggleTime() {
+      return toggleTime_ != null;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. Latest instant at which the `enabled` field was set to true after being
+     * disabled/unconfigured or set to false after being enabled. If Autoclass
+     * is enabled when the bucket is created, the toggle_time is set to the
+     * bucket creation time.
+     * </pre>
+     *
+     * <code>
+     * .google.protobuf.Timestamp toggle_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     *
+     * @return The toggleTime.
+     */
+    @java.lang.Override
+    public com.google.protobuf.Timestamp getToggleTime() {
+      return toggleTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : toggleTime_;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Output only. Latest instant at which the `enabled` field was set to true after being
+     * disabled/unconfigured or set to false after being enabled. If Autoclass
+     * is enabled when the bucket is created, the toggle_time is set to the
+     * bucket creation time.
+     * </pre>
+     *
+     * <code>
+     * .google.protobuf.Timestamp toggle_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];
+     * </code>
+     */
+    @java.lang.Override
+    public com.google.protobuf.TimestampOrBuilder getToggleTimeOrBuilder() {
+      return getToggleTime();
+    }
+
+    private byte memoizedIsInitialized = -1;
+
+    @java.lang.Override
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    @java.lang.Override
+    public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
+      if (enabled_ != false) {
+        output.writeBool(1, enabled_);
+      }
+      if (toggleTime_ != null) {
+        output.writeMessage(2, getToggleTime());
+      }
+      unknownFields.writeTo(output);
+    }
+
+    @java.lang.Override
+    public int getSerializedSize() {
+      int size = memoizedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (enabled_ != false) {
+        size += com.google.protobuf.CodedOutputStream.computeBoolSize(1, enabled_);
+      }
+      if (toggleTime_ != null) {
+        size += com.google.protobuf.CodedOutputStream.computeMessageSize(2, getToggleTime());
+      }
+      size += unknownFields.getSerializedSize();
+      memoizedSize = size;
+      return size;
+    }
+
+    @java.lang.Override
+    public boolean equals(final java.lang.Object obj) {
+      if (obj == this) {
+        return true;
+      }
+      if (!(obj instanceof com.google.storage.v2.Bucket.Autoclass)) {
+        return super.equals(obj);
+      }
+      com.google.storage.v2.Bucket.Autoclass other = (com.google.storage.v2.Bucket.Autoclass) obj;
+
+      if (getEnabled() != other.getEnabled()) return false;
+      if (hasToggleTime() != other.hasToggleTime()) return false;
+      if (hasToggleTime()) {
+        if (!getToggleTime().equals(other.getToggleTime())) return false;
+      }
+      if (!unknownFields.equals(other.unknownFields)) return false;
+      return true;
+    }
+
+    @java.lang.Override
+    public int hashCode() {
+      if (memoizedHashCode != 0) {
+        return memoizedHashCode;
+      }
+      int hash = 41;
+      hash = (19 * hash) + getDescriptor().hashCode();
+      hash = (37 * hash) + ENABLED_FIELD_NUMBER;
+      hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(getEnabled());
+      if (hasToggleTime()) {
+        hash = (37 * hash) + TOGGLE_TIME_FIELD_NUMBER;
+        hash = (53 * hash) + getToggleTime().hashCode();
+      }
+      hash = (29 * hash) + unknownFields.hashCode();
+      memoizedHashCode = hash;
+      return hash;
+    }
+
+    public static com.google.storage.v2.Bucket.Autoclass parseFrom(java.nio.ByteBuffer data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+
+    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+        java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+
+    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+
+    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+
+    public static com.google.storage.v2.Bucket.Autoclass parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+
+    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+        byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+
+    public static com.google.storage.v2.Bucket.Autoclass parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
+    }
+
+    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+        java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
+          PARSER, input, extensionRegistry);
+    }
+
+    public static com.google.storage.v2.Bucket.Autoclass parseDelimitedFrom(
+        java.io.InputStream input) throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input);
+    }
+
+    public static com.google.storage.v2.Bucket.Autoclass parseDelimitedFrom(
+        java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(
+          PARSER, input, extensionRegistry);
+    }
+
+    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+        com.google.protobuf.CodedInputStream input) throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
+    }
+
+    public static com.google.storage.v2.Bucket.Autoclass parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
+          PARSER, input, extensionRegistry);
+    }
+
+    @java.lang.Override
+    public Builder newBuilderForType() {
+      return newBuilder();
+    }
+
+    public static Builder newBuilder() {
+      return DEFAULT_INSTANCE.toBuilder();
+    }
+
+    public static Builder newBuilder(com.google.storage.v2.Bucket.Autoclass prototype) {
+      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+    }
+
+    @java.lang.Override
+    public Builder toBuilder() {
+      return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
+    }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Configuration for a bucket's Autoclass feature.
+     * </pre>
+     *
+     * Protobuf type {@code google.storage.v2.Bucket.Autoclass}
+     */
+    public static final class Builder
+        extends com.google.protobuf.GeneratedMessageV3.Builder<Builder>
+        implements
+        // @@protoc_insertion_point(builder_implements:google.storage.v2.Bucket.Autoclass)
+        com.google.storage.v2.Bucket.AutoclassOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+        return com.google.storage.v2.StorageProto
+            .internal_static_google_storage_v2_Bucket_Autoclass_descriptor;
+      }
+
+      @java.lang.Override
+      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return com.google.storage.v2.StorageProto
+            .internal_static_google_storage_v2_Bucket_Autoclass_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                com.google.storage.v2.Bucket.Autoclass.class,
+                com.google.storage.v2.Bucket.Autoclass.Builder.class);
+      }
+
+      // Construct using com.google.storage.v2.Bucket.Autoclass.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {}
+      }
+
+      @java.lang.Override
+      public Builder clear() {
+        super.clear();
+        enabled_ = false;
+
+        if (toggleTimeBuilder_ == null) {
+          toggleTime_ = null;
+        } else {
+          toggleTime_ = null;
+          toggleTimeBuilder_ = null;
+        }
+        return this;
+      }
+
+      @java.lang.Override
+      public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
+        return com.google.storage.v2.StorageProto
+            .internal_static_google_storage_v2_Bucket_Autoclass_descriptor;
+      }
+
+      @java.lang.Override
+      public com.google.storage.v2.Bucket.Autoclass getDefaultInstanceForType() {
+        return com.google.storage.v2.Bucket.Autoclass.getDefaultInstance();
+      }
+
+      @java.lang.Override
+      public com.google.storage.v2.Bucket.Autoclass build() {
+        com.google.storage.v2.Bucket.Autoclass result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      @java.lang.Override
+      public com.google.storage.v2.Bucket.Autoclass buildPartial() {
+        com.google.storage.v2.Bucket.Autoclass result =
+            new com.google.storage.v2.Bucket.Autoclass(this);
+        result.enabled_ = enabled_;
+        if (toggleTimeBuilder_ == null) {
+          result.toggleTime_ = toggleTime_;
+        } else {
+          result.toggleTime_ = toggleTimeBuilder_.build();
+        }
+        onBuilt();
+        return result;
+      }
+
+      @java.lang.Override
+      public Builder clone() {
+        return super.clone();
+      }
+
+      @java.lang.Override
+      public Builder setField(
+          com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
+        return super.setField(field, value);
+      }
+
+      @java.lang.Override
+      public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) {
+        return super.clearField(field);
+      }
+
+      @java.lang.Override
+      public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+        return super.clearOneof(oneof);
+      }
+
+      @java.lang.Override
+      public Builder setRepeatedField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          int index,
+          java.lang.Object value) {
+        return super.setRepeatedField(field, index, value);
+      }
+
+      @java.lang.Override
+      public Builder addRepeatedField(
+          com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
+        return super.addRepeatedField(field, value);
+      }
+
+      @java.lang.Override
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof com.google.storage.v2.Bucket.Autoclass) {
+          return mergeFrom((com.google.storage.v2.Bucket.Autoclass) other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(com.google.storage.v2.Bucket.Autoclass other) {
+        if (other == com.google.storage.v2.Bucket.Autoclass.getDefaultInstance()) return this;
+        if (other.getEnabled() != false) {
+          setEnabled(other.getEnabled());
+        }
+        if (other.hasToggleTime()) {
+          mergeToggleTime(other.getToggleTime());
+        }
+        this.mergeUnknownFields(other.unknownFields);
+        onChanged();
+        return this;
+      }
+
+      @java.lang.Override
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      @java.lang.Override
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        com.google.storage.v2.Bucket.Autoclass parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (com.google.storage.v2.Bucket.Autoclass) e.getUnfinishedMessage();
+          throw e.unwrapIOException();
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      private boolean enabled_;
+      /**
+       *
+       *
+       * <pre>
+       * Enables Autoclass.
+       * </pre>
+       *
+       * <code>bool enabled = 1;</code>
+       *
+       * @return The enabled.
+       */
+      @java.lang.Override
+      public boolean getEnabled() {
+        return enabled_;
+      }
+      /**
+       *
+       *
+       * <pre>
+       * Enables Autoclass.
+       * </pre>
+       *
+       * <code>bool enabled = 1;</code>
+       *
+       * @param value The enabled to set.
+       * @return This builder for chaining.
+       */
+      public Builder setEnabled(boolean value) {
+
+        enabled_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       *
+       *
+       * <pre>
+       * Enables Autoclass.
+       * </pre>
+       *
+       * <code>bool enabled = 1;</code>
+       *
+       * @return This builder for chaining.
+       */
+      public Builder clearEnabled() {
+
+        enabled_ = false;
         onChanged();
         return this;
       }
@@ -15890,37 +16709,90 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
     if (ref instanceof java.lang.String) {
       com.google.protobuf.ByteString b =
           com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
-      name_ = b;
+      name_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int BUCKET_ID_FIELD_NUMBER = 2;
+  private volatile java.lang.Object bucketId_;
+  /**
+   *
+   *
+   * <pre>
+   * Output only. The user-chosen part of the bucket name. The `{bucket}` portion of the
+   * `name` field. For globally unique buckets, this is equal to the "bucket
+   * name" of other Cloud Storage APIs. Example: "pub".
+   * </pre>
+   *
+   * <code>string bucket_id = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];</code>
+   *
+   * @return The bucketId.
+   */
+  @java.lang.Override
+  public java.lang.String getBucketId() {
+    java.lang.Object ref = bucketId_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      bucketId_ = s;
+      return s;
+    }
+  }
+  /**
+   *
+   *
+   * <pre>
+   * Output only. The user-chosen part of the bucket name. The `{bucket}` portion of the
+   * `name` field. For globally unique buckets, this is equal to the "bucket
+   * name" of other Cloud Storage APIs. Example: "pub".
+   * </pre>
+   *
+   * <code>string bucket_id = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];</code>
+   *
+   * @return The bytes for bucketId.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString getBucketIdBytes() {
+    java.lang.Object ref = bucketId_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b =
+          com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+      bucketId_ = b;
       return b;
     } else {
       return (com.google.protobuf.ByteString) ref;
     }
   }
 
-  public static final int BUCKET_ID_FIELD_NUMBER = 2;
-  private volatile java.lang.Object bucketId_;
+  public static final int ETAG_FIELD_NUMBER = 29;
+  private volatile java.lang.Object etag_;
   /**
    *
    *
    * <pre>
-   * Output only. The user-chosen part of the bucket name. The `{bucket}` portion of the
-   * `name` field. For globally unique buckets, this is equal to the "bucket
-   * name" of other Cloud Storage APIs. Example: "pub".
+   * The etag of the bucket.
+   * If included in the metadata of an UpdateBucketRequest, the operation will
+   * only be performed if the etag matches that of the bucket.
    * </pre>
    *
-   * <code>string bucket_id = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];</code>
+   * <code>string etag = 29;</code>
    *
-   * @return The bucketId.
+   * @return The etag.
    */
   @java.lang.Override
-  public java.lang.String getBucketId() {
-    java.lang.Object ref = bucketId_;
+  public java.lang.String getEtag() {
+    java.lang.Object ref = etag_;
     if (ref instanceof java.lang.String) {
       return (java.lang.String) ref;
     } else {
       com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
       java.lang.String s = bs.toStringUtf8();
-      bucketId_ = s;
+      etag_ = s;
       return s;
     }
   }
@@ -15928,22 +16800,22 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
    *
    *
    * <pre>
-   * Output only. The user-chosen part of the bucket name. The `{bucket}` portion of the
-   * `name` field. For globally unique buckets, this is equal to the "bucket
-   * name" of other Cloud Storage APIs. Example: "pub".
+   * The etag of the bucket.
+   * If included in the metadata of an UpdateBucketRequest, the operation will
+   * only be performed if the etag matches that of the bucket.
    * </pre>
    *
-   * <code>string bucket_id = 2 [(.google.api.field_behavior) = OUTPUT_ONLY];</code>
+   * <code>string etag = 29;</code>
    *
-   * @return The bytes for bucketId.
+   * @return The bytes for etag.
    */
   @java.lang.Override
-  public com.google.protobuf.ByteString getBucketIdBytes() {
-    java.lang.Object ref = bucketId_;
+  public com.google.protobuf.ByteString getEtagBytes() {
+    java.lang.Object ref = etag_;
     if (ref instanceof java.lang.String) {
       com.google.protobuf.ByteString b =
           com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
-      bucketId_ = b;
+      etag_ = b;
       return b;
     } else {
       return (com.google.protobuf.ByteString) ref;
@@ -17202,6 +18074,58 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
     return satisfiesPzs_;
   }
 
+  public static final int CUSTOM_PLACEMENT_CONFIG_FIELD_NUMBER = 26;
+  private com.google.storage.v2.Bucket.CustomPlacementConfig customPlacementConfig_;
+  /**
+   *
+   *
+   * <pre>
+   * Configuration that, if present, specifies the data placement for a Custom
+   * Dual Region.
+   * </pre>
+   *
+   * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+   *
+   * @return Whether the customPlacementConfig field is set.
+   */
+  @java.lang.Override
+  public boolean hasCustomPlacementConfig() {
+    return customPlacementConfig_ != null;
+  }
+  /**
+   *
+   *
+   * <pre>
+   * Configuration that, if present, specifies the data placement for a Custom
+   * Dual Region.
+   * </pre>
+   *
+   * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+   *
+   * @return The customPlacementConfig.
+   */
+  @java.lang.Override
+  public com.google.storage.v2.Bucket.CustomPlacementConfig getCustomPlacementConfig() {
+    return customPlacementConfig_ == null
+        ? com.google.storage.v2.Bucket.CustomPlacementConfig.getDefaultInstance()
+        : customPlacementConfig_;
+  }
+  /**
+   *
+   *
+   * <pre>
+   * Configuration that, if present, specifies the data placement for a Custom
+   * Dual Region.
+   * </pre>
+   *
+   * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+   */
+  @java.lang.Override
+  public com.google.storage.v2.Bucket.CustomPlacementConfigOrBuilder
+      getCustomPlacementConfigOrBuilder() {
+    return getCustomPlacementConfig();
+  }
+
   public static final int AUTOCLASS_FIELD_NUMBER = 28;
   private com.google.storage.v2.Bucket.Autoclass autoclass_;
   /**
@@ -17338,12 +18262,18 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
     if (satisfiesPzs_ != false) {
       output.writeBool(25, satisfiesPzs_);
     }
+    if (customPlacementConfig_ != null) {
+      output.writeMessage(26, getCustomPlacementConfig());
+    }
     if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(rpo_)) {
       com.google.protobuf.GeneratedMessageV3.writeString(output, 27, rpo_);
     }
     if (autoclass_ != null) {
       output.writeMessage(28, getAutoclass());
     }
+    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 29, etag_);
+    }
     unknownFields.writeTo(output);
   }
 
@@ -17432,12 +18362,19 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
     if (satisfiesPzs_ != false) {
       size += com.google.protobuf.CodedOutputStream.computeBoolSize(25, satisfiesPzs_);
     }
+    if (customPlacementConfig_ != null) {
+      size +=
+          com.google.protobuf.CodedOutputStream.computeMessageSize(26, getCustomPlacementConfig());
+    }
     if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(rpo_)) {
       size += com.google.protobuf.GeneratedMessageV3.computeStringSize(27, rpo_);
     }
     if (autoclass_ != null) {
       size += com.google.protobuf.CodedOutputStream.computeMessageSize(28, getAutoclass());
     }
+    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(29, etag_);
+    }
     size += unknownFields.getSerializedSize();
     memoizedSize = size;
     return size;
@@ -17455,6 +18392,7 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
 
     if (!getName().equals(other.getName())) return false;
     if (!getBucketId().equals(other.getBucketId())) return false;
+    if (!getEtag().equals(other.getEtag())) return false;
     if (!getProject().equals(other.getProject())) return false;
     if (getMetageneration() != other.getMetageneration()) return false;
     if (!getLocation().equals(other.getLocation())) return false;
@@ -17511,6 +18449,10 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       if (!getIamConfig().equals(other.getIamConfig())) return false;
     }
     if (getSatisfiesPzs() != other.getSatisfiesPzs()) return false;
+    if (hasCustomPlacementConfig() != other.hasCustomPlacementConfig()) return false;
+    if (hasCustomPlacementConfig()) {
+      if (!getCustomPlacementConfig().equals(other.getCustomPlacementConfig())) return false;
+    }
     if (hasAutoclass() != other.hasAutoclass()) return false;
     if (hasAutoclass()) {
       if (!getAutoclass().equals(other.getAutoclass())) return false;
@@ -17530,6 +18472,8 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
     hash = (53 * hash) + getName().hashCode();
     hash = (37 * hash) + BUCKET_ID_FIELD_NUMBER;
     hash = (53 * hash) + getBucketId().hashCode();
+    hash = (37 * hash) + ETAG_FIELD_NUMBER;
+    hash = (53 * hash) + getEtag().hashCode();
     hash = (37 * hash) + PROJECT_FIELD_NUMBER;
     hash = (53 * hash) + getProject().hashCode();
     hash = (37 * hash) + METAGENERATION_FIELD_NUMBER;
@@ -17606,6 +18550,10 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
     }
     hash = (37 * hash) + SATISFIES_PZS_FIELD_NUMBER;
     hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(getSatisfiesPzs());
+    if (hasCustomPlacementConfig()) {
+      hash = (37 * hash) + CUSTOM_PLACEMENT_CONFIG_FIELD_NUMBER;
+      hash = (53 * hash) + getCustomPlacementConfig().hashCode();
+    }
     if (hasAutoclass()) {
       hash = (37 * hash) + AUTOCLASS_FIELD_NUMBER;
       hash = (53 * hash) + getAutoclass().hashCode();
@@ -17780,6 +18728,8 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
 
       bucketId_ = "";
 
+      etag_ = "";
+
       project_ = "";
 
       metageneration_ = 0L;
@@ -17881,6 +18831,12 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       }
       satisfiesPzs_ = false;
 
+      if (customPlacementConfigBuilder_ == null) {
+        customPlacementConfig_ = null;
+      } else {
+        customPlacementConfig_ = null;
+        customPlacementConfigBuilder_ = null;
+      }
       if (autoclassBuilder_ == null) {
         autoclass_ = null;
       } else {
@@ -17915,6 +18871,7 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       int from_bitField0_ = bitField0_;
       result.name_ = name_;
       result.bucketId_ = bucketId_;
+      result.etag_ = etag_;
       result.project_ = project_;
       result.metageneration_ = metageneration_;
       result.location_ = location_;
@@ -18007,6 +18964,11 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
         result.iamConfig_ = iamConfigBuilder_.build();
       }
       result.satisfiesPzs_ = satisfiesPzs_;
+      if (customPlacementConfigBuilder_ == null) {
+        result.customPlacementConfig_ = customPlacementConfig_;
+      } else {
+        result.customPlacementConfig_ = customPlacementConfigBuilder_.build();
+      }
       if (autoclassBuilder_ == null) {
         result.autoclass_ = autoclass_;
       } else {
@@ -18069,6 +19031,10 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
         bucketId_ = other.bucketId_;
         onChanged();
       }
+      if (!other.getEtag().isEmpty()) {
+        etag_ = other.etag_;
+        onChanged();
+      }
       if (!other.getProject().isEmpty()) {
         project_ = other.project_;
         onChanged();
@@ -18213,6 +19179,9 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       if (other.getSatisfiesPzs() != false) {
         setSatisfiesPzs(other.getSatisfiesPzs());
       }
+      if (other.hasCustomPlacementConfig()) {
+        mergeCustomPlacementConfig(other.getCustomPlacementConfig());
+      }
       if (other.hasAutoclass()) {
         mergeAutoclass(other.getAutoclass());
       }
@@ -18469,6 +19438,122 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       return this;
     }
 
+    private java.lang.Object etag_ = "";
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the bucket.
+     * If included in the metadata of an UpdateBucketRequest, the operation will
+     * only be performed if the etag matches that of the bucket.
+     * </pre>
+     *
+     * <code>string etag = 29;</code>
+     *
+     * @return The etag.
+     */
+    public java.lang.String getEtag() {
+      java.lang.Object ref = etag_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        etag_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the bucket.
+     * If included in the metadata of an UpdateBucketRequest, the operation will
+     * only be performed if the etag matches that of the bucket.
+     * </pre>
+     *
+     * <code>string etag = 29;</code>
+     *
+     * @return The bytes for etag.
+     */
+    public com.google.protobuf.ByteString getEtagBytes() {
+      java.lang.Object ref = etag_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+        etag_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the bucket.
+     * If included in the metadata of an UpdateBucketRequest, the operation will
+     * only be performed if the etag matches that of the bucket.
+     * </pre>
+     *
+     * <code>string etag = 29;</code>
+     *
+     * @param value The etag to set.
+     * @return This builder for chaining.
+     */
+    public Builder setEtag(java.lang.String value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+
+      etag_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the bucket.
+     * If included in the metadata of an UpdateBucketRequest, the operation will
+     * only be performed if the etag matches that of the bucket.
+     * </pre>
+     *
+     * <code>string etag = 29;</code>
+     *
+     * @return This builder for chaining.
+     */
+    public Builder clearEtag() {
+
+      etag_ = getDefaultInstance().getEtag();
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the bucket.
+     * If included in the metadata of an UpdateBucketRequest, the operation will
+     * only be performed if the etag matches that of the bucket.
+     * </pre>
+     *
+     * <code>string etag = 29;</code>
+     *
+     * @param value The bytes for etag to set.
+     * @return This builder for chaining.
+     */
+    public Builder setEtagBytes(com.google.protobuf.ByteString value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+      checkByteStringIsUtf8(value);
+
+      etag_ = value;
+      onChanged();
+      return this;
+    }
+
     private java.lang.Object project_ = "";
     /**
      *
@@ -22806,6 +23891,205 @@ public final class Bucket extends com.google.protobuf.GeneratedMessageV3
       return this;
     }
 
+    private com.google.storage.v2.Bucket.CustomPlacementConfig customPlacementConfig_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+            com.google.storage.v2.Bucket.CustomPlacementConfig,
+            com.google.storage.v2.Bucket.CustomPlacementConfig.Builder,
+            com.google.storage.v2.Bucket.CustomPlacementConfigOrBuilder>
+        customPlacementConfigBuilder_;
+    /**
+     *
+     *
+     * <pre>
+     * Configuration that, if present, specifies the data placement for a Custom
+     * Dual Region.
+     * </pre>
+     *
+     * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+     *
+     * @return Whether the customPlacementConfig field is set.
+     */
+    public boolean hasCustomPlacementConfig() {
+      return customPlacementConfigBuilder_ != null || customPlacementConfig_ != null;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Configuration that, if present, specifies the data placement for a Custom
+     * Dual Region.
+     * </pre>
+     *
+     * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+     *
+     * @return The customPlacementConfig.
+     */
+    public com.google.storage.v2.Bucket.CustomPlacementConfig getCustomPlacementConfig() {
+      if (customPlacementConfigBuilder_ == null) {
+        return customPlacementConfig_ == null
+            ? com.google.storage.v2.Bucket.CustomPlacementConfig.getDefaultInstance()
+            : customPlacementConfig_;
+      } else {
+        return customPlacementConfigBuilder_.getMessage();
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Configuration that, if present, specifies the data placement for a Custom
+     * Dual Region.
+     * </pre>
+     *
+     * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+     */
+    public Builder setCustomPlacementConfig(
+        com.google.storage.v2.Bucket.CustomPlacementConfig value) {
+      if (customPlacementConfigBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        customPlacementConfig_ = value;
+        onChanged();
+      } else {
+        customPlacementConfigBuilder_.setMessage(value);
+      }
+
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Configuration that, if present, specifies the data placement for a Custom
+     * Dual Region.
+     * </pre>
+     *
+     * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+     */
+    public Builder setCustomPlacementConfig(
+        com.google.storage.v2.Bucket.CustomPlacementConfig.Builder builderForValue) {
+      if (customPlacementConfigBuilder_ == null) {
+        customPlacementConfig_ = builderForValue.build();
+        onChanged();
+      } else {
+        customPlacementConfigBuilder_.setMessage(builderForValue.build());
+      }
+
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Configuration that, if present, specifies the data placement for a Custom
+     * Dual Region.
+     * </pre>
+     *
+     * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+     */
+    public Builder mergeCustomPlacementConfig(
+        com.google.storage.v2.Bucket.CustomPlacementConfig value) {
+      if (customPlacementConfigBuilder_ == null) {
+        if (customPlacementConfig_ != null) {
+          customPlacementConfig_ =
+              com.google.storage.v2.Bucket.CustomPlacementConfig.newBuilder(customPlacementConfig_)
+                  .mergeFrom(value)
+                  .buildPartial();
+        } else {
+          customPlacementConfig_ = value;
+        }
+        onChanged();
+      } else {
+        customPlacementConfigBuilder_.mergeFrom(value);
+      }
+
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Configuration that, if present, specifies the data placement for a Custom
+     * Dual Region.
+     * </pre>
+     *
+     * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+     */
+    public Builder clearCustomPlacementConfig() {
+      if (customPlacementConfigBuilder_ == null) {
+        customPlacementConfig_ = null;
+        onChanged();
+      } else {
+        customPlacementConfig_ = null;
+        customPlacementConfigBuilder_ = null;
+      }
+
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Configuration that, if present, specifies the data placement for a Custom
+     * Dual Region.
+     * </pre>
+     *
+     * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+     */
+    public com.google.storage.v2.Bucket.CustomPlacementConfig.Builder
+        getCustomPlacementConfigBuilder() {
+
+      onChanged();
+      return getCustomPlacementConfigFieldBuilder().getBuilder();
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Configuration that, if present, specifies the data placement for a Custom
+     * Dual Region.
+     * </pre>
+     *
+     * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+     */
+    public com.google.storage.v2.Bucket.CustomPlacementConfigOrBuilder
+        getCustomPlacementConfigOrBuilder() {
+      if (customPlacementConfigBuilder_ != null) {
+        return customPlacementConfigBuilder_.getMessageOrBuilder();
+      } else {
+        return customPlacementConfig_ == null
+            ? com.google.storage.v2.Bucket.CustomPlacementConfig.getDefaultInstance()
+            : customPlacementConfig_;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * Configuration that, if present, specifies the data placement for a Custom
+     * Dual Region.
+     * </pre>
+     *
+     * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+            com.google.storage.v2.Bucket.CustomPlacementConfig,
+            com.google.storage.v2.Bucket.CustomPlacementConfig.Builder,
+            com.google.storage.v2.Bucket.CustomPlacementConfigOrBuilder>
+        getCustomPlacementConfigFieldBuilder() {
+      if (customPlacementConfigBuilder_ == null) {
+        customPlacementConfigBuilder_ =
+            new com.google.protobuf.SingleFieldBuilderV3<
+                com.google.storage.v2.Bucket.CustomPlacementConfig,
+                com.google.storage.v2.Bucket.CustomPlacementConfig.Builder,
+                com.google.storage.v2.Bucket.CustomPlacementConfigOrBuilder>(
+                getCustomPlacementConfig(), getParentForChildren(), isClean());
+        customPlacementConfig_ = null;
+      }
+      return customPlacementConfigBuilder_;
+    }
+
     private com.google.storage.v2.Bucket.Autoclass autoclass_;
     private com.google.protobuf.SingleFieldBuilderV3<
             com.google.storage.v2.Bucket.Autoclass,
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketAccessControl.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketAccessControl.java
index 7b638464..53dda1ff 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketAccessControl.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketAccessControl.java
@@ -42,6 +42,7 @@ public final class BucketAccessControl extends com.google.protobuf.GeneratedMess
     id_ = "";
     entity_ = "";
     entityId_ = "";
+    etag_ = "";
     email_ = "";
     domain_ = "";
   }
@@ -130,6 +131,13 @@ public final class BucketAccessControl extends com.google.protobuf.GeneratedMess
                 projectTeam_ = subBuilder.buildPartial();
               }
 
+              break;
+            }
+          case 66:
+            {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              etag_ = s;
               break;
             }
           default:
@@ -392,6 +400,61 @@ public final class BucketAccessControl extends com.google.protobuf.GeneratedMess
     }
   }
 
+  public static final int ETAG_FIELD_NUMBER = 8;
+  private volatile java.lang.Object etag_;
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the BucketAccessControl.
+   * If included in the metadata of an update or delete request message, the
+   * operation operation will only be performed if the etag matches that of the
+   * bucket's BucketAccessControl.
+   * </pre>
+   *
+   * <code>string etag = 8;</code>
+   *
+   * @return The etag.
+   */
+  @java.lang.Override
+  public java.lang.String getEtag() {
+    java.lang.Object ref = etag_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      etag_ = s;
+      return s;
+    }
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the BucketAccessControl.
+   * If included in the metadata of an update or delete request message, the
+   * operation operation will only be performed if the etag matches that of the
+   * bucket's BucketAccessControl.
+   * </pre>
+   *
+   * <code>string etag = 8;</code>
+   *
+   * @return The bytes for etag.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString getEtagBytes() {
+    java.lang.Object ref = etag_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b =
+          com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+      etag_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
   public static final int EMAIL_FIELD_NUMBER = 5;
   private volatile java.lang.Object email_;
   /**
@@ -573,6 +636,9 @@ public final class BucketAccessControl extends com.google.protobuf.GeneratedMess
     if (projectTeam_ != null) {
       output.writeMessage(7, getProjectTeam());
     }
+    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 8, etag_);
+    }
     unknownFields.writeTo(output);
   }
 
@@ -603,6 +669,9 @@ public final class BucketAccessControl extends com.google.protobuf.GeneratedMess
     if (projectTeam_ != null) {
       size += com.google.protobuf.CodedOutputStream.computeMessageSize(7, getProjectTeam());
     }
+    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(8, etag_);
+    }
     size += unknownFields.getSerializedSize();
     memoizedSize = size;
     return size;
@@ -623,6 +692,7 @@ public final class BucketAccessControl extends com.google.protobuf.GeneratedMess
     if (!getId().equals(other.getId())) return false;
     if (!getEntity().equals(other.getEntity())) return false;
     if (!getEntityId().equals(other.getEntityId())) return false;
+    if (!getEtag().equals(other.getEtag())) return false;
     if (!getEmail().equals(other.getEmail())) return false;
     if (!getDomain().equals(other.getDomain())) return false;
     if (hasProjectTeam() != other.hasProjectTeam()) return false;
@@ -648,6 +718,8 @@ public final class BucketAccessControl extends com.google.protobuf.GeneratedMess
     hash = (53 * hash) + getEntity().hashCode();
     hash = (37 * hash) + ENTITY_ID_FIELD_NUMBER;
     hash = (53 * hash) + getEntityId().hashCode();
+    hash = (37 * hash) + ETAG_FIELD_NUMBER;
+    hash = (53 * hash) + getEtag().hashCode();
     hash = (37 * hash) + EMAIL_FIELD_NUMBER;
     hash = (53 * hash) + getEmail().hashCode();
     hash = (37 * hash) + DOMAIN_FIELD_NUMBER;
@@ -809,6 +881,8 @@ public final class BucketAccessControl extends com.google.protobuf.GeneratedMess
 
       entityId_ = "";
 
+      etag_ = "";
+
       email_ = "";
 
       domain_ = "";
@@ -850,6 +924,7 @@ public final class BucketAccessControl extends com.google.protobuf.GeneratedMess
       result.id_ = id_;
       result.entity_ = entity_;
       result.entityId_ = entityId_;
+      result.etag_ = etag_;
       result.email_ = email_;
       result.domain_ = domain_;
       if (projectTeamBuilder_ == null) {
@@ -922,6 +997,10 @@ public final class BucketAccessControl extends com.google.protobuf.GeneratedMess
         entityId_ = other.entityId_;
         onChanged();
       }
+      if (!other.getEtag().isEmpty()) {
+        etag_ = other.etag_;
+        onChanged();
+      }
       if (!other.getEmail().isEmpty()) {
         email_ = other.email_;
         onChanged();
@@ -1456,6 +1535,127 @@ public final class BucketAccessControl extends com.google.protobuf.GeneratedMess
       return this;
     }
 
+    private java.lang.Object etag_ = "";
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the BucketAccessControl.
+     * If included in the metadata of an update or delete request message, the
+     * operation operation will only be performed if the etag matches that of the
+     * bucket's BucketAccessControl.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @return The etag.
+     */
+    public java.lang.String getEtag() {
+      java.lang.Object ref = etag_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        etag_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the BucketAccessControl.
+     * If included in the metadata of an update or delete request message, the
+     * operation operation will only be performed if the etag matches that of the
+     * bucket's BucketAccessControl.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @return The bytes for etag.
+     */
+    public com.google.protobuf.ByteString getEtagBytes() {
+      java.lang.Object ref = etag_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+        etag_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the BucketAccessControl.
+     * If included in the metadata of an update or delete request message, the
+     * operation operation will only be performed if the etag matches that of the
+     * bucket's BucketAccessControl.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @param value The etag to set.
+     * @return This builder for chaining.
+     */
+    public Builder setEtag(java.lang.String value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+
+      etag_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the BucketAccessControl.
+     * If included in the metadata of an update or delete request message, the
+     * operation operation will only be performed if the etag matches that of the
+     * bucket's BucketAccessControl.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @return This builder for chaining.
+     */
+    public Builder clearEtag() {
+
+      etag_ = getDefaultInstance().getEtag();
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the BucketAccessControl.
+     * If included in the metadata of an update or delete request message, the
+     * operation operation will only be performed if the etag matches that of the
+     * bucket's BucketAccessControl.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @param value The bytes for etag to set.
+     * @return This builder for chaining.
+     */
+    public Builder setEtagBytes(com.google.protobuf.ByteString value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+      checkByteStringIsUtf8(value);
+
+      etag_ = value;
+      onChanged();
+      return this;
+    }
+
     private java.lang.Object email_ = "";
     /**
      *
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketAccessControlOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketAccessControlOrBuilder.java
index 073daa3b..04451af6 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketAccessControlOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketAccessControlOrBuilder.java
@@ -151,6 +151,37 @@ public interface BucketAccessControlOrBuilder
    */
   com.google.protobuf.ByteString getEntityIdBytes();
 
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the BucketAccessControl.
+   * If included in the metadata of an update or delete request message, the
+   * operation operation will only be performed if the etag matches that of the
+   * bucket's BucketAccessControl.
+   * </pre>
+   *
+   * <code>string etag = 8;</code>
+   *
+   * @return The etag.
+   */
+  java.lang.String getEtag();
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the BucketAccessControl.
+   * If included in the metadata of an update or delete request message, the
+   * operation operation will only be performed if the etag matches that of the
+   * bucket's BucketAccessControl.
+   * </pre>
+   *
+   * <code>string etag = 8;</code>
+   *
+   * @return The bytes for etag.
+   */
+  com.google.protobuf.ByteString getEtagBytes();
+
   /**
    *
    *
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketOrBuilder.java
index a30ce772..50ec1b91 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketOrBuilder.java
@@ -77,6 +77,35 @@ public interface BucketOrBuilder
    */
   com.google.protobuf.ByteString getBucketIdBytes();
 
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the bucket.
+   * If included in the metadata of an UpdateBucketRequest, the operation will
+   * only be performed if the etag matches that of the bucket.
+   * </pre>
+   *
+   * <code>string etag = 29;</code>
+   *
+   * @return The etag.
+   */
+  java.lang.String getEtag();
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the bucket.
+   * If included in the metadata of an UpdateBucketRequest, the operation will
+   * only be performed if the etag matches that of the bucket.
+   * </pre>
+   *
+   * <code>string etag = 29;</code>
+   *
+   * @return The bytes for etag.
+   */
+  com.google.protobuf.ByteString getEtagBytes();
+
   /**
    *
    *
@@ -971,6 +1000,44 @@ public interface BucketOrBuilder
    */
   boolean getSatisfiesPzs();
 
+  /**
+   *
+   *
+   * <pre>
+   * Configuration that, if present, specifies the data placement for a Custom
+   * Dual Region.
+   * </pre>
+   *
+   * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+   *
+   * @return Whether the customPlacementConfig field is set.
+   */
+  boolean hasCustomPlacementConfig();
+  /**
+   *
+   *
+   * <pre>
+   * Configuration that, if present, specifies the data placement for a Custom
+   * Dual Region.
+   * </pre>
+   *
+   * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+   *
+   * @return The customPlacementConfig.
+   */
+  com.google.storage.v2.Bucket.CustomPlacementConfig getCustomPlacementConfig();
+  /**
+   *
+   *
+   * <pre>
+   * Configuration that, if present, specifies the data placement for a Custom
+   * Dual Region.
+   * </pre>
+   *
+   * <code>.google.storage.v2.Bucket.CustomPlacementConfig custom_placement_config = 26;</code>
+   */
+  com.google.storage.v2.Bucket.CustomPlacementConfigOrBuilder getCustomPlacementConfigOrBuilder();
+
   /**
    *
    *
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/DeleteObjectRequest.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/DeleteObjectRequest.java
index 5cd7c37d..38dfd204 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/DeleteObjectRequest.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/DeleteObjectRequest.java
@@ -390,7 +390,7 @@ public final class DeleteObjectRequest extends com.google.protobuf.GeneratedMess
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -408,7 +408,7 @@ public final class DeleteObjectRequest extends com.google.protobuf.GeneratedMess
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -1497,7 +1497,7 @@ public final class DeleteObjectRequest extends com.google.protobuf.GeneratedMess
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -1515,7 +1515,7 @@ public final class DeleteObjectRequest extends com.google.protobuf.GeneratedMess
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -1533,7 +1533,7 @@ public final class DeleteObjectRequest extends com.google.protobuf.GeneratedMess
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -1554,7 +1554,7 @@ public final class DeleteObjectRequest extends com.google.protobuf.GeneratedMess
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/DeleteObjectRequestOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/DeleteObjectRequestOrBuilder.java
index 11cf2596..dfd8e1f8 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/DeleteObjectRequestOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/DeleteObjectRequestOrBuilder.java
@@ -149,7 +149,7 @@ public interface DeleteObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -164,7 +164,7 @@ public interface DeleteObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/GetObjectRequest.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/GetObjectRequest.java
index 22cfb435..a3a09a3c 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/GetObjectRequest.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/GetObjectRequest.java
@@ -343,7 +343,7 @@ public final class GetObjectRequest extends com.google.protobuf.GeneratedMessage
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -361,7 +361,7 @@ public final class GetObjectRequest extends com.google.protobuf.GeneratedMessage
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -1404,7 +1404,7 @@ public final class GetObjectRequest extends com.google.protobuf.GeneratedMessage
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -1422,7 +1422,7 @@ public final class GetObjectRequest extends com.google.protobuf.GeneratedMessage
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -1440,7 +1440,7 @@ public final class GetObjectRequest extends com.google.protobuf.GeneratedMessage
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -1461,7 +1461,7 @@ public final class GetObjectRequest extends com.google.protobuf.GeneratedMessage
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/GetObjectRequestOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/GetObjectRequestOrBuilder.java
index 9abed62f..8730f04d 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/GetObjectRequestOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/GetObjectRequestOrBuilder.java
@@ -120,7 +120,7 @@ public interface GetObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -135,7 +135,7 @@ public interface GetObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/HmacKeyMetadata.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/HmacKeyMetadata.java
index 1c6bd3d5..dc54e590 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/HmacKeyMetadata.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/HmacKeyMetadata.java
@@ -43,6 +43,7 @@ public final class HmacKeyMetadata extends com.google.protobuf.GeneratedMessageV
     project_ = "";
     serviceAccountEmail_ = "";
     state_ = "";
+    etag_ = "";
   }
 
   @java.lang.Override
@@ -137,6 +138,13 @@ public final class HmacKeyMetadata extends com.google.protobuf.GeneratedMessageV
                 updateTime_ = subBuilder.buildPartial();
               }
 
+              break;
+            }
+          case 66:
+            {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              etag_ = s;
               break;
             }
           default:
@@ -512,6 +520,55 @@ public final class HmacKeyMetadata extends com.google.protobuf.GeneratedMessageV
     return getUpdateTime();
   }
 
+  public static final int ETAG_FIELD_NUMBER = 8;
+  private volatile java.lang.Object etag_;
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the HMAC key.
+   * </pre>
+   *
+   * <code>string etag = 8;</code>
+   *
+   * @return The etag.
+   */
+  @java.lang.Override
+  public java.lang.String getEtag() {
+    java.lang.Object ref = etag_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      etag_ = s;
+      return s;
+    }
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the HMAC key.
+   * </pre>
+   *
+   * <code>string etag = 8;</code>
+   *
+   * @return The bytes for etag.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString getEtagBytes() {
+    java.lang.Object ref = etag_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b =
+          com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+      etag_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
   private byte memoizedIsInitialized = -1;
 
   @java.lang.Override
@@ -547,6 +604,9 @@ public final class HmacKeyMetadata extends com.google.protobuf.GeneratedMessageV
     if (updateTime_ != null) {
       output.writeMessage(7, getUpdateTime());
     }
+    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 8, etag_);
+    }
     unknownFields.writeTo(output);
   }
 
@@ -577,6 +637,9 @@ public final class HmacKeyMetadata extends com.google.protobuf.GeneratedMessageV
     if (updateTime_ != null) {
       size += com.google.protobuf.CodedOutputStream.computeMessageSize(7, getUpdateTime());
     }
+    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(8, etag_);
+    }
     size += unknownFields.getSerializedSize();
     memoizedSize = size;
     return size;
@@ -605,6 +668,7 @@ public final class HmacKeyMetadata extends com.google.protobuf.GeneratedMessageV
     if (hasUpdateTime()) {
       if (!getUpdateTime().equals(other.getUpdateTime())) return false;
     }
+    if (!getEtag().equals(other.getEtag())) return false;
     if (!unknownFields.equals(other.unknownFields)) return false;
     return true;
   }
@@ -634,6 +698,8 @@ public final class HmacKeyMetadata extends com.google.protobuf.GeneratedMessageV
       hash = (37 * hash) + UPDATE_TIME_FIELD_NUMBER;
       hash = (53 * hash) + getUpdateTime().hashCode();
     }
+    hash = (37 * hash) + ETAG_FIELD_NUMBER;
+    hash = (53 * hash) + getEtag().hashCode();
     hash = (29 * hash) + unknownFields.hashCode();
     memoizedHashCode = hash;
     return hash;
@@ -800,6 +866,8 @@ public final class HmacKeyMetadata extends com.google.protobuf.GeneratedMessageV
         updateTime_ = null;
         updateTimeBuilder_ = null;
       }
+      etag_ = "";
+
       return this;
     }
 
@@ -842,6 +910,7 @@ public final class HmacKeyMetadata extends com.google.protobuf.GeneratedMessageV
       } else {
         result.updateTime_ = updateTimeBuilder_.build();
       }
+      result.etag_ = etag_;
       onBuilt();
       return result;
     }
@@ -917,6 +986,10 @@ public final class HmacKeyMetadata extends com.google.protobuf.GeneratedMessageV
       if (other.hasUpdateTime()) {
         mergeUpdateTime(other.getUpdateTime());
       }
+      if (!other.getEtag().isEmpty()) {
+        etag_ = other.etag_;
+        onChanged();
+      }
       this.mergeUnknownFields(other.unknownFields);
       onChanged();
       return this;
@@ -1842,6 +1915,112 @@ public final class HmacKeyMetadata extends com.google.protobuf.GeneratedMessageV
       return updateTimeBuilder_;
     }
 
+    private java.lang.Object etag_ = "";
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the HMAC key.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @return The etag.
+     */
+    public java.lang.String getEtag() {
+      java.lang.Object ref = etag_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        etag_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the HMAC key.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @return The bytes for etag.
+     */
+    public com.google.protobuf.ByteString getEtagBytes() {
+      java.lang.Object ref = etag_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+        etag_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the HMAC key.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @param value The etag to set.
+     * @return This builder for chaining.
+     */
+    public Builder setEtag(java.lang.String value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+
+      etag_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the HMAC key.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @return This builder for chaining.
+     */
+    public Builder clearEtag() {
+
+      etag_ = getDefaultInstance().getEtag();
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the HMAC key.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @param value The bytes for etag to set.
+     * @return This builder for chaining.
+     */
+    public Builder setEtagBytes(com.google.protobuf.ByteString value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+      checkByteStringIsUtf8(value);
+
+      etag_ = value;
+      onChanged();
+      return this;
+    }
+
     @java.lang.Override
     public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
       return super.setUnknownFields(unknownFields);
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/HmacKeyMetadataOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/HmacKeyMetadataOrBuilder.java
index 489b9189..3e7bc4e8 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/HmacKeyMetadataOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/HmacKeyMetadataOrBuilder.java
@@ -217,4 +217,29 @@ public interface HmacKeyMetadataOrBuilder
    * <code>.google.protobuf.Timestamp update_time = 7;</code>
    */
   com.google.protobuf.TimestampOrBuilder getUpdateTimeOrBuilder();
+
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the HMAC key.
+   * </pre>
+   *
+   * <code>string etag = 8;</code>
+   *
+   * @return The etag.
+   */
+  java.lang.String getEtag();
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the HMAC key.
+   * </pre>
+   *
+   * <code>string etag = 8;</code>
+   *
+   * @return The bytes for etag.
+   */
+  com.google.protobuf.ByteString getEtagBytes();
 }
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListNotificationsRequest.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListNotificationsRequest.java
index 773bda1b..74d9859d 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListNotificationsRequest.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListNotificationsRequest.java
@@ -187,7 +187,8 @@ public final class ListNotificationsRequest extends com.google.protobuf.Generate
    * <pre>
    * The maximum number of notifications to return. The service may return fewer
    * than this value.
-   * The maximum value is 100; values above 100 will be coerced to 100.
+   * The default value is 100. Specifying a value above 100 will result in a
+   * page_size of 100.
    * </pre>
    *
    * <code>int32 page_size = 2;</code>
@@ -724,7 +725,8 @@ public final class ListNotificationsRequest extends com.google.protobuf.Generate
      * <pre>
      * The maximum number of notifications to return. The service may return fewer
      * than this value.
-     * The maximum value is 100; values above 100 will be coerced to 100.
+     * The default value is 100. Specifying a value above 100 will result in a
+     * page_size of 100.
      * </pre>
      *
      * <code>int32 page_size = 2;</code>
@@ -741,7 +743,8 @@ public final class ListNotificationsRequest extends com.google.protobuf.Generate
      * <pre>
      * The maximum number of notifications to return. The service may return fewer
      * than this value.
-     * The maximum value is 100; values above 100 will be coerced to 100.
+     * The default value is 100. Specifying a value above 100 will result in a
+     * page_size of 100.
      * </pre>
      *
      * <code>int32 page_size = 2;</code>
@@ -761,7 +764,8 @@ public final class ListNotificationsRequest extends com.google.protobuf.Generate
      * <pre>
      * The maximum number of notifications to return. The service may return fewer
      * than this value.
-     * The maximum value is 100; values above 100 will be coerced to 100.
+     * The default value is 100. Specifying a value above 100 will result in a
+     * page_size of 100.
      * </pre>
      *
      * <code>int32 page_size = 2;</code>
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListNotificationsRequestOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListNotificationsRequestOrBuilder.java
index a078cac3..af80ec76 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListNotificationsRequestOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListNotificationsRequestOrBuilder.java
@@ -58,7 +58,8 @@ public interface ListNotificationsRequestOrBuilder
    * <pre>
    * The maximum number of notifications to return. The service may return fewer
    * than this value.
-   * The maximum value is 100; values above 100 will be coerced to 100.
+   * The default value is 100. Specifying a value above 100 will result in a
+   * page_size of 100.
    * </pre>
    *
    * <code>int32 page_size = 2;</code>
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Notification.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Notification.java
index 506e55da..00632e30 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Notification.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Notification.java
@@ -40,6 +40,7 @@ public final class Notification extends com.google.protobuf.GeneratedMessageV3
   private Notification() {
     name_ = "";
     topic_ = "";
+    etag_ = "";
     eventTypes_ = com.google.protobuf.LazyStringArrayList.EMPTY;
     objectNamePrefix_ = "";
     payloadFormat_ = "";
@@ -130,6 +131,13 @@ public final class Notification extends com.google.protobuf.GeneratedMessageV3
               payloadFormat_ = s;
               break;
             }
+          case 58:
+            {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              etag_ = s;
+              break;
+            }
           default:
             {
               if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) {
@@ -286,6 +294,59 @@ public final class Notification extends com.google.protobuf.GeneratedMessageV3
     }
   }
 
+  public static final int ETAG_FIELD_NUMBER = 7;
+  private volatile java.lang.Object etag_;
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the Notification.
+   * If included in the metadata of GetNotificationRequest, the operation will
+   * only be performed if the etag matches that of the Notification.
+   * </pre>
+   *
+   * <code>string etag = 7;</code>
+   *
+   * @return The etag.
+   */
+  @java.lang.Override
+  public java.lang.String getEtag() {
+    java.lang.Object ref = etag_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      etag_ = s;
+      return s;
+    }
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the Notification.
+   * If included in the metadata of GetNotificationRequest, the operation will
+   * only be performed if the etag matches that of the Notification.
+   * </pre>
+   *
+   * <code>string etag = 7;</code>
+   *
+   * @return The bytes for etag.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString getEtagBytes() {
+    java.lang.Object ref = etag_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b =
+          com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+      etag_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
   public static final int EVENT_TYPES_FIELD_NUMBER = 3;
   private com.google.protobuf.LazyStringList eventTypes_;
   /**
@@ -595,6 +656,9 @@ public final class Notification extends com.google.protobuf.GeneratedMessageV3
     if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(payloadFormat_)) {
       com.google.protobuf.GeneratedMessageV3.writeString(output, 6, payloadFormat_);
     }
+    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 7, etag_);
+    }
     unknownFields.writeTo(output);
   }
 
@@ -634,6 +698,9 @@ public final class Notification extends com.google.protobuf.GeneratedMessageV3
     if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(payloadFormat_)) {
       size += com.google.protobuf.GeneratedMessageV3.computeStringSize(6, payloadFormat_);
     }
+    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(7, etag_);
+    }
     size += unknownFields.getSerializedSize();
     memoizedSize = size;
     return size;
@@ -651,6 +718,7 @@ public final class Notification extends com.google.protobuf.GeneratedMessageV3
 
     if (!getName().equals(other.getName())) return false;
     if (!getTopic().equals(other.getTopic())) return false;
+    if (!getEtag().equals(other.getEtag())) return false;
     if (!getEventTypesList().equals(other.getEventTypesList())) return false;
     if (!internalGetCustomAttributes().equals(other.internalGetCustomAttributes())) return false;
     if (!getObjectNamePrefix().equals(other.getObjectNamePrefix())) return false;
@@ -670,6 +738,8 @@ public final class Notification extends com.google.protobuf.GeneratedMessageV3
     hash = (53 * hash) + getName().hashCode();
     hash = (37 * hash) + TOPIC_FIELD_NUMBER;
     hash = (53 * hash) + getTopic().hashCode();
+    hash = (37 * hash) + ETAG_FIELD_NUMBER;
+    hash = (53 * hash) + getEtag().hashCode();
     if (getEventTypesCount() > 0) {
       hash = (37 * hash) + EVENT_TYPES_FIELD_NUMBER;
       hash = (53 * hash) + getEventTypesList().hashCode();
@@ -850,6 +920,8 @@ public final class Notification extends com.google.protobuf.GeneratedMessageV3
 
       topic_ = "";
 
+      etag_ = "";
+
       eventTypes_ = com.google.protobuf.LazyStringArrayList.EMPTY;
       bitField0_ = (bitField0_ & ~0x00000001);
       internalGetMutableCustomAttributes().clear();
@@ -886,6 +958,7 @@ public final class Notification extends com.google.protobuf.GeneratedMessageV3
       int from_bitField0_ = bitField0_;
       result.name_ = name_;
       result.topic_ = topic_;
+      result.etag_ = etag_;
       if (((bitField0_ & 0x00000001) != 0)) {
         eventTypes_ = eventTypes_.getUnmodifiableView();
         bitField0_ = (bitField0_ & ~0x00000001);
@@ -952,6 +1025,10 @@ public final class Notification extends com.google.protobuf.GeneratedMessageV3
         topic_ = other.topic_;
         onChanged();
       }
+      if (!other.getEtag().isEmpty()) {
+        etag_ = other.etag_;
+        onChanged();
+      }
       if (!other.eventTypes_.isEmpty()) {
         if (eventTypes_.isEmpty()) {
           eventTypes_ = other.eventTypes_;
@@ -1234,6 +1311,122 @@ public final class Notification extends com.google.protobuf.GeneratedMessageV3
       return this;
     }
 
+    private java.lang.Object etag_ = "";
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the Notification.
+     * If included in the metadata of GetNotificationRequest, the operation will
+     * only be performed if the etag matches that of the Notification.
+     * </pre>
+     *
+     * <code>string etag = 7;</code>
+     *
+     * @return The etag.
+     */
+    public java.lang.String getEtag() {
+      java.lang.Object ref = etag_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        etag_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the Notification.
+     * If included in the metadata of GetNotificationRequest, the operation will
+     * only be performed if the etag matches that of the Notification.
+     * </pre>
+     *
+     * <code>string etag = 7;</code>
+     *
+     * @return The bytes for etag.
+     */
+    public com.google.protobuf.ByteString getEtagBytes() {
+      java.lang.Object ref = etag_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+        etag_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the Notification.
+     * If included in the metadata of GetNotificationRequest, the operation will
+     * only be performed if the etag matches that of the Notification.
+     * </pre>
+     *
+     * <code>string etag = 7;</code>
+     *
+     * @param value The etag to set.
+     * @return This builder for chaining.
+     */
+    public Builder setEtag(java.lang.String value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+
+      etag_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the Notification.
+     * If included in the metadata of GetNotificationRequest, the operation will
+     * only be performed if the etag matches that of the Notification.
+     * </pre>
+     *
+     * <code>string etag = 7;</code>
+     *
+     * @return This builder for chaining.
+     */
+    public Builder clearEtag() {
+
+      etag_ = getDefaultInstance().getEtag();
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the Notification.
+     * If included in the metadata of GetNotificationRequest, the operation will
+     * only be performed if the etag matches that of the Notification.
+     * </pre>
+     *
+     * <code>string etag = 7;</code>
+     *
+     * @param value The bytes for etag to set.
+     * @return This builder for chaining.
+     */
+    public Builder setEtagBytes(com.google.protobuf.ByteString value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+      checkByteStringIsUtf8(value);
+
+      etag_ = value;
+      onChanged();
+      return this;
+    }
+
     private com.google.protobuf.LazyStringList eventTypes_ =
         com.google.protobuf.LazyStringArrayList.EMPTY;
 
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/NotificationOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/NotificationOrBuilder.java
index f16926fe..5031676f 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/NotificationOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/NotificationOrBuilder.java
@@ -81,6 +81,35 @@ public interface NotificationOrBuilder
    */
   com.google.protobuf.ByteString getTopicBytes();
 
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the Notification.
+   * If included in the metadata of GetNotificationRequest, the operation will
+   * only be performed if the etag matches that of the Notification.
+   * </pre>
+   *
+   * <code>string etag = 7;</code>
+   *
+   * @return The etag.
+   */
+  java.lang.String getEtag();
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the Notification.
+   * If included in the metadata of GetNotificationRequest, the operation will
+   * only be performed if the etag matches that of the Notification.
+   * </pre>
+   *
+   * <code>string etag = 7;</code>
+   *
+   * @return The bytes for etag.
+   */
+  com.google.protobuf.ByteString getEtagBytes();
+
   /**
    *
    *
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Object.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Object.java
index 8b90884c..6b4d9c5b 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Object.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Object.java
@@ -40,6 +40,7 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
   private Object() {
     name_ = "";
     bucket_ = "";
+    etag_ = "";
     storageClass_ = "";
     contentEncoding_ = "";
     contentDisposition_ = "";
@@ -334,6 +335,13 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
                 customTime_ = subBuilder.buildPartial();
               }
 
+              break;
+            }
+          case 218:
+            {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              etag_ = s;
               break;
             }
           default:
@@ -499,6 +507,61 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
     }
   }
 
+  public static final int ETAG_FIELD_NUMBER = 27;
+  private volatile java.lang.Object etag_;
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the object.
+   * If included in the metadata of an update or delete request message, the
+   * operation will only be performed if the etag matches that of the live
+   * object.
+   * </pre>
+   *
+   * <code>string etag = 27;</code>
+   *
+   * @return The etag.
+   */
+  @java.lang.Override
+  public java.lang.String getEtag() {
+    java.lang.Object ref = etag_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      etag_ = s;
+      return s;
+    }
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the object.
+   * If included in the metadata of an update or delete request message, the
+   * operation will only be performed if the etag matches that of the live
+   * object.
+   * </pre>
+   *
+   * <code>string etag = 27;</code>
+   *
+   * @return The bytes for etag.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString getEtagBytes() {
+    java.lang.Object ref = etag_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b =
+          com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+      etag_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
   public static final int GENERATION_FIELD_NUMBER = 3;
   private long generation_;
   /**
@@ -1789,6 +1852,9 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
     if (customTime_ != null) {
       output.writeMessage(26, getCustomTime());
     }
+    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 27, etag_);
+    }
     unknownFields.writeTo(output);
   }
 
@@ -1885,6 +1951,9 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
     if (customTime_ != null) {
       size += com.google.protobuf.CodedOutputStream.computeMessageSize(26, getCustomTime());
     }
+    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(27, etag_);
+    }
     size += unknownFields.getSerializedSize();
     memoizedSize = size;
     return size;
@@ -1902,6 +1971,7 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
 
     if (!getName().equals(other.getName())) return false;
     if (!getBucket().equals(other.getBucket())) return false;
+    if (!getEtag().equals(other.getEtag())) return false;
     if (getGeneration() != other.getGeneration()) return false;
     if (getMetageneration() != other.getMetageneration()) return false;
     if (!getStorageClass().equals(other.getStorageClass())) return false;
@@ -1971,6 +2041,8 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
     hash = (53 * hash) + getName().hashCode();
     hash = (37 * hash) + BUCKET_FIELD_NUMBER;
     hash = (53 * hash) + getBucket().hashCode();
+    hash = (37 * hash) + ETAG_FIELD_NUMBER;
+    hash = (53 * hash) + getEtag().hashCode();
     hash = (37 * hash) + GENERATION_FIELD_NUMBER;
     hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getGeneration());
     hash = (37 * hash) + METAGENERATION_FIELD_NUMBER;
@@ -2211,6 +2283,8 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
 
       bucket_ = "";
 
+      etag_ = "";
+
       generation_ = 0L;
 
       metageneration_ = 0L;
@@ -2327,6 +2401,7 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
       int to_bitField0_ = 0;
       result.name_ = name_;
       result.bucket_ = bucket_;
+      result.etag_ = etag_;
       result.generation_ = generation_;
       result.metageneration_ = metageneration_;
       result.storageClass_ = storageClass_;
@@ -2457,6 +2532,10 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
         bucket_ = other.bucket_;
         onChanged();
       }
+      if (!other.getEtag().isEmpty()) {
+        etag_ = other.etag_;
+        onChanged();
+      }
       if (other.getGeneration() != 0L) {
         setGeneration(other.getGeneration());
       }
@@ -2841,6 +2920,127 @@ public final class Object extends com.google.protobuf.GeneratedMessageV3
       return this;
     }
 
+    private java.lang.Object etag_ = "";
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the object.
+     * If included in the metadata of an update or delete request message, the
+     * operation will only be performed if the etag matches that of the live
+     * object.
+     * </pre>
+     *
+     * <code>string etag = 27;</code>
+     *
+     * @return The etag.
+     */
+    public java.lang.String getEtag() {
+      java.lang.Object ref = etag_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        etag_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the object.
+     * If included in the metadata of an update or delete request message, the
+     * operation will only be performed if the etag matches that of the live
+     * object.
+     * </pre>
+     *
+     * <code>string etag = 27;</code>
+     *
+     * @return The bytes for etag.
+     */
+    public com.google.protobuf.ByteString getEtagBytes() {
+      java.lang.Object ref = etag_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+        etag_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the object.
+     * If included in the metadata of an update or delete request message, the
+     * operation will only be performed if the etag matches that of the live
+     * object.
+     * </pre>
+     *
+     * <code>string etag = 27;</code>
+     *
+     * @param value The etag to set.
+     * @return This builder for chaining.
+     */
+    public Builder setEtag(java.lang.String value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+
+      etag_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the object.
+     * If included in the metadata of an update or delete request message, the
+     * operation will only be performed if the etag matches that of the live
+     * object.
+     * </pre>
+     *
+     * <code>string etag = 27;</code>
+     *
+     * @return This builder for chaining.
+     */
+    public Builder clearEtag() {
+
+      etag_ = getDefaultInstance().getEtag();
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the object.
+     * If included in the metadata of an update or delete request message, the
+     * operation will only be performed if the etag matches that of the live
+     * object.
+     * </pre>
+     *
+     * <code>string etag = 27;</code>
+     *
+     * @param value The bytes for etag to set.
+     * @return This builder for chaining.
+     */
+    public Builder setEtagBytes(com.google.protobuf.ByteString value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+      checkByteStringIsUtf8(value);
+
+      etag_ = value;
+      onChanged();
+      return this;
+    }
+
     private long generation_;
     /**
      *
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectAccessControl.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectAccessControl.java
index 1fbaadae..33f3d9b9 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectAccessControl.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectAccessControl.java
@@ -42,6 +42,7 @@ public final class ObjectAccessControl extends com.google.protobuf.GeneratedMess
     id_ = "";
     entity_ = "";
     entityId_ = "";
+    etag_ = "";
     email_ = "";
     domain_ = "";
   }
@@ -130,6 +131,13 @@ public final class ObjectAccessControl extends com.google.protobuf.GeneratedMess
                 projectTeam_ = subBuilder.buildPartial();
               }
 
+              break;
+            }
+          case 66:
+            {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              etag_ = s;
               break;
             }
           default:
@@ -392,6 +400,61 @@ public final class ObjectAccessControl extends com.google.protobuf.GeneratedMess
     }
   }
 
+  public static final int ETAG_FIELD_NUMBER = 8;
+  private volatile java.lang.Object etag_;
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the ObjectAccessControl.
+   * If included in the metadata of an update or delete request message, the
+   * operation will only be performed if the etag matches that of the live
+   * object's ObjectAccessControl.
+   * </pre>
+   *
+   * <code>string etag = 8;</code>
+   *
+   * @return The etag.
+   */
+  @java.lang.Override
+  public java.lang.String getEtag() {
+    java.lang.Object ref = etag_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      etag_ = s;
+      return s;
+    }
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the ObjectAccessControl.
+   * If included in the metadata of an update or delete request message, the
+   * operation will only be performed if the etag matches that of the live
+   * object's ObjectAccessControl.
+   * </pre>
+   *
+   * <code>string etag = 8;</code>
+   *
+   * @return The bytes for etag.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString getEtagBytes() {
+    java.lang.Object ref = etag_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b =
+          com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+      etag_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
   public static final int EMAIL_FIELD_NUMBER = 5;
   private volatile java.lang.Object email_;
   /**
@@ -573,6 +636,9 @@ public final class ObjectAccessControl extends com.google.protobuf.GeneratedMess
     if (projectTeam_ != null) {
       output.writeMessage(7, getProjectTeam());
     }
+    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 8, etag_);
+    }
     unknownFields.writeTo(output);
   }
 
@@ -603,6 +669,9 @@ public final class ObjectAccessControl extends com.google.protobuf.GeneratedMess
     if (projectTeam_ != null) {
       size += com.google.protobuf.CodedOutputStream.computeMessageSize(7, getProjectTeam());
     }
+    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(8, etag_);
+    }
     size += unknownFields.getSerializedSize();
     memoizedSize = size;
     return size;
@@ -623,6 +692,7 @@ public final class ObjectAccessControl extends com.google.protobuf.GeneratedMess
     if (!getId().equals(other.getId())) return false;
     if (!getEntity().equals(other.getEntity())) return false;
     if (!getEntityId().equals(other.getEntityId())) return false;
+    if (!getEtag().equals(other.getEtag())) return false;
     if (!getEmail().equals(other.getEmail())) return false;
     if (!getDomain().equals(other.getDomain())) return false;
     if (hasProjectTeam() != other.hasProjectTeam()) return false;
@@ -648,6 +718,8 @@ public final class ObjectAccessControl extends com.google.protobuf.GeneratedMess
     hash = (53 * hash) + getEntity().hashCode();
     hash = (37 * hash) + ENTITY_ID_FIELD_NUMBER;
     hash = (53 * hash) + getEntityId().hashCode();
+    hash = (37 * hash) + ETAG_FIELD_NUMBER;
+    hash = (53 * hash) + getEtag().hashCode();
     hash = (37 * hash) + EMAIL_FIELD_NUMBER;
     hash = (53 * hash) + getEmail().hashCode();
     hash = (37 * hash) + DOMAIN_FIELD_NUMBER;
@@ -809,6 +881,8 @@ public final class ObjectAccessControl extends com.google.protobuf.GeneratedMess
 
       entityId_ = "";
 
+      etag_ = "";
+
       email_ = "";
 
       domain_ = "";
@@ -850,6 +924,7 @@ public final class ObjectAccessControl extends com.google.protobuf.GeneratedMess
       result.id_ = id_;
       result.entity_ = entity_;
       result.entityId_ = entityId_;
+      result.etag_ = etag_;
       result.email_ = email_;
       result.domain_ = domain_;
       if (projectTeamBuilder_ == null) {
@@ -922,6 +997,10 @@ public final class ObjectAccessControl extends com.google.protobuf.GeneratedMess
         entityId_ = other.entityId_;
         onChanged();
       }
+      if (!other.getEtag().isEmpty()) {
+        etag_ = other.etag_;
+        onChanged();
+      }
       if (!other.getEmail().isEmpty()) {
         email_ = other.email_;
         onChanged();
@@ -1456,6 +1535,127 @@ public final class ObjectAccessControl extends com.google.protobuf.GeneratedMess
       return this;
     }
 
+    private java.lang.Object etag_ = "";
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the ObjectAccessControl.
+     * If included in the metadata of an update or delete request message, the
+     * operation will only be performed if the etag matches that of the live
+     * object's ObjectAccessControl.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @return The etag.
+     */
+    public java.lang.String getEtag() {
+      java.lang.Object ref = etag_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        etag_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the ObjectAccessControl.
+     * If included in the metadata of an update or delete request message, the
+     * operation will only be performed if the etag matches that of the live
+     * object's ObjectAccessControl.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @return The bytes for etag.
+     */
+    public com.google.protobuf.ByteString getEtagBytes() {
+      java.lang.Object ref = etag_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b =
+            com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+        etag_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the ObjectAccessControl.
+     * If included in the metadata of an update or delete request message, the
+     * operation will only be performed if the etag matches that of the live
+     * object's ObjectAccessControl.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @param value The etag to set.
+     * @return This builder for chaining.
+     */
+    public Builder setEtag(java.lang.String value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+
+      etag_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the ObjectAccessControl.
+     * If included in the metadata of an update or delete request message, the
+     * operation will only be performed if the etag matches that of the live
+     * object's ObjectAccessControl.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @return This builder for chaining.
+     */
+    public Builder clearEtag() {
+
+      etag_ = getDefaultInstance().getEtag();
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The etag of the ObjectAccessControl.
+     * If included in the metadata of an update or delete request message, the
+     * operation will only be performed if the etag matches that of the live
+     * object's ObjectAccessControl.
+     * </pre>
+     *
+     * <code>string etag = 8;</code>
+     *
+     * @param value The bytes for etag to set.
+     * @return This builder for chaining.
+     */
+    public Builder setEtagBytes(com.google.protobuf.ByteString value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+      checkByteStringIsUtf8(value);
+
+      etag_ = value;
+      onChanged();
+      return this;
+    }
+
     private java.lang.Object email_ = "";
     /**
      *
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectAccessControlOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectAccessControlOrBuilder.java
index a6a45c09..21e493d7 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectAccessControlOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectAccessControlOrBuilder.java
@@ -151,6 +151,37 @@ public interface ObjectAccessControlOrBuilder
    */
   com.google.protobuf.ByteString getEntityIdBytes();
 
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the ObjectAccessControl.
+   * If included in the metadata of an update or delete request message, the
+   * operation will only be performed if the etag matches that of the live
+   * object's ObjectAccessControl.
+   * </pre>
+   *
+   * <code>string etag = 8;</code>
+   *
+   * @return The etag.
+   */
+  java.lang.String getEtag();
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the ObjectAccessControl.
+   * If included in the metadata of an update or delete request message, the
+   * operation will only be performed if the etag matches that of the live
+   * object's ObjectAccessControl.
+   * </pre>
+   *
+   * <code>string etag = 8;</code>
+   *
+   * @return The bytes for etag.
+   */
+  com.google.protobuf.ByteString getEtagBytes();
+
   /**
    *
    *
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectOrBuilder.java
index 3f0622ed..bd6aa32c 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectOrBuilder.java
@@ -89,6 +89,37 @@ public interface ObjectOrBuilder
    */
   com.google.protobuf.ByteString getBucketBytes();
 
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the object.
+   * If included in the metadata of an update or delete request message, the
+   * operation will only be performed if the etag matches that of the live
+   * object.
+   * </pre>
+   *
+   * <code>string etag = 27;</code>
+   *
+   * @return The etag.
+   */
+  java.lang.String getEtag();
+  /**
+   *
+   *
+   * <pre>
+   * The etag of the object.
+   * If included in the metadata of an update or delete request message, the
+   * operation will only be performed if the etag matches that of the live
+   * object.
+   * </pre>
+   *
+   * <code>string etag = 27;</code>
+   *
+   * @return The bytes for etag.
+   */
+  com.google.protobuf.ByteString getEtagBytes();
+
   /**
    *
    *
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ReadObjectRequest.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ReadObjectRequest.java
index e5591243..13c5b08a 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ReadObjectRequest.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ReadObjectRequest.java
@@ -322,8 +322,8 @@ public final class ReadObjectRequest extends com.google.protobuf.GeneratedMessag
    * back from the end of the object to be returned. For example, if an object's
    * length is 15 bytes, a ReadObjectRequest with `read_offset` = -5 and
    * `read_limit` = 3 would return bytes 10 through 12 of the object. Requesting
-   * a negative offset whose magnitude is larger than the size of the object
-   * will result in an error.
+   * a negative offset with magnitude larger than the size of the object will
+   * return the entire object.
    * </pre>
    *
    * <code>int64 read_offset = 4;</code>
@@ -401,7 +401,7 @@ public final class ReadObjectRequest extends com.google.protobuf.GeneratedMessag
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -419,7 +419,7 @@ public final class ReadObjectRequest extends com.google.protobuf.GeneratedMessag
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -1426,8 +1426,8 @@ public final class ReadObjectRequest extends com.google.protobuf.GeneratedMessag
      * back from the end of the object to be returned. For example, if an object's
      * length is 15 bytes, a ReadObjectRequest with `read_offset` = -5 and
      * `read_limit` = 3 would return bytes 10 through 12 of the object. Requesting
-     * a negative offset whose magnitude is larger than the size of the object
-     * will result in an error.
+     * a negative offset with magnitude larger than the size of the object will
+     * return the entire object.
      * </pre>
      *
      * <code>int64 read_offset = 4;</code>
@@ -1448,8 +1448,8 @@ public final class ReadObjectRequest extends com.google.protobuf.GeneratedMessag
      * back from the end of the object to be returned. For example, if an object's
      * length is 15 bytes, a ReadObjectRequest with `read_offset` = -5 and
      * `read_limit` = 3 would return bytes 10 through 12 of the object. Requesting
-     * a negative offset whose magnitude is larger than the size of the object
-     * will result in an error.
+     * a negative offset with magnitude larger than the size of the object will
+     * return the entire object.
      * </pre>
      *
      * <code>int64 read_offset = 4;</code>
@@ -1473,8 +1473,8 @@ public final class ReadObjectRequest extends com.google.protobuf.GeneratedMessag
      * back from the end of the object to be returned. For example, if an object's
      * length is 15 bytes, a ReadObjectRequest with `read_offset` = -5 and
      * `read_limit` = 3 would return bytes 10 through 12 of the object. Requesting
-     * a negative offset whose magnitude is larger than the size of the object
-     * will result in an error.
+     * a negative offset with magnitude larger than the size of the object will
+     * return the entire object.
      * </pre>
      *
      * <code>int64 read_offset = 4;</code>
@@ -1635,7 +1635,7 @@ public final class ReadObjectRequest extends com.google.protobuf.GeneratedMessag
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -1653,7 +1653,7 @@ public final class ReadObjectRequest extends com.google.protobuf.GeneratedMessag
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -1671,7 +1671,7 @@ public final class ReadObjectRequest extends com.google.protobuf.GeneratedMessag
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -1692,7 +1692,7 @@ public final class ReadObjectRequest extends com.google.protobuf.GeneratedMessag
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ReadObjectRequestOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ReadObjectRequestOrBuilder.java
index 20cd5315..5a1661cd 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ReadObjectRequestOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ReadObjectRequestOrBuilder.java
@@ -97,8 +97,8 @@ public interface ReadObjectRequestOrBuilder
    * back from the end of the object to be returned. For example, if an object's
    * length is 15 bytes, a ReadObjectRequest with `read_offset` = -5 and
    * `read_limit` = 3 would return bytes 10 through 12 of the object. Requesting
-   * a negative offset whose magnitude is larger than the size of the object
-   * will result in an error.
+   * a negative offset with magnitude larger than the size of the object will
+   * return the entire object.
    * </pre>
    *
    * <code>int64 read_offset = 4;</code>
@@ -158,7 +158,7 @@ public interface ReadObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -173,7 +173,7 @@ public interface ReadObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/RewriteObjectRequest.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/RewriteObjectRequest.java
index b792c74e..3bf7f794 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/RewriteObjectRequest.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/RewriteObjectRequest.java
@@ -784,7 +784,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -802,7 +802,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -893,7 +893,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the source object's current
+   * Makes the operation conditional on whether the source object's live
    * generation matches the given value.
    * </pre>
    *
@@ -909,7 +909,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the source object's current
+   * Makes the operation conditional on whether the source object's live
    * generation matches the given value.
    * </pre>
    *
@@ -928,7 +928,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the source object's current
+   * Makes the operation conditional on whether the source object's live
    * generation does not match the given value.
    * </pre>
    *
@@ -944,7 +944,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the source object's current
+   * Makes the operation conditional on whether the source object's live
    * generation does not match the given value.
    * </pre>
    *
@@ -3156,7 +3156,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -3174,7 +3174,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -3192,7 +3192,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -3213,7 +3213,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -3377,7 +3377,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the source object's current
+     * Makes the operation conditional on whether the source object's live
      * generation matches the given value.
      * </pre>
      *
@@ -3393,7 +3393,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the source object's current
+     * Makes the operation conditional on whether the source object's live
      * generation matches the given value.
      * </pre>
      *
@@ -3409,7 +3409,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the source object's current
+     * Makes the operation conditional on whether the source object's live
      * generation matches the given value.
      * </pre>
      *
@@ -3428,7 +3428,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the source object's current
+     * Makes the operation conditional on whether the source object's live
      * generation matches the given value.
      * </pre>
      *
@@ -3448,7 +3448,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the source object's current
+     * Makes the operation conditional on whether the source object's live
      * generation does not match the given value.
      * </pre>
      *
@@ -3464,7 +3464,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the source object's current
+     * Makes the operation conditional on whether the source object's live
      * generation does not match the given value.
      * </pre>
      *
@@ -3480,7 +3480,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the source object's current
+     * Makes the operation conditional on whether the source object's live
      * generation does not match the given value.
      * </pre>
      *
@@ -3499,7 +3499,7 @@ public final class RewriteObjectRequest extends com.google.protobuf.GeneratedMes
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the source object's current
+     * Makes the operation conditional on whether the source object's live
      * generation does not match the given value.
      * </pre>
      *
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/RewriteObjectRequestOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/RewriteObjectRequestOrBuilder.java
index 89315b9c..41ffda22 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/RewriteObjectRequestOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/RewriteObjectRequestOrBuilder.java
@@ -334,7 +334,7 @@ public interface RewriteObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -349,7 +349,7 @@ public interface RewriteObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -419,7 +419,7 @@ public interface RewriteObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the source object's current
+   * Makes the operation conditional on whether the source object's live
    * generation matches the given value.
    * </pre>
    *
@@ -432,7 +432,7 @@ public interface RewriteObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the source object's current
+   * Makes the operation conditional on whether the source object's live
    * generation matches the given value.
    * </pre>
    *
@@ -446,7 +446,7 @@ public interface RewriteObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the source object's current
+   * Makes the operation conditional on whether the source object's live
    * generation does not match the given value.
    * </pre>
    *
@@ -459,7 +459,7 @@ public interface RewriteObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the source object's current
+   * Makes the operation conditional on whether the source object's live
    * generation does not match the given value.
    * </pre>
    *
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageProto.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageProto.java
index 19cf33cb..5c95c7fc 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageProto.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageProto.java
@@ -243,6 +243,10 @@ public final class StorageProto {
       internal_static_google_storage_v2_Bucket_Website_descriptor;
   static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
       internal_static_google_storage_v2_Bucket_Website_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+      internal_static_google_storage_v2_Bucket_CustomPlacementConfig_descriptor;
+  static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_google_storage_v2_Bucket_CustomPlacementConfig_fieldAccessorTable;
   static final com.google.protobuf.Descriptors.Descriptor
       internal_static_google_storage_v2_Bucket_Autoclass_descriptor;
   static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
@@ -573,239 +577,244 @@ public final class StorageProto {
           + "\033MAX_LABELS_KEY_VALUE_LENGTH\020?\022\037\n\032MAX_LA"
           + "BELS_KEY_VALUE_BYTES\020\200\001\022.\n)MAX_OBJECT_ID"
           + "S_PER_DELETE_OBJECTS_REQUEST\020\350\007\022\036\n\032SPLIT"
-          + "_TOKEN_MAX_VALID_DAYS\020\016\032\002\020\001\"\243\026\n\006Bucket\022\021"
+          + "_TOKEN_MAX_VALID_DAYS\020\016\032\002\020\001\"\264\027\n\006Bucket\022\021"
           + "\n\004name\030\001 \001(\tB\003\340A\005\022\026\n\tbucket_id\030\002 \001(\tB\003\340A"
-          + "\003\022D\n\007project\030\003 \001(\tB3\340A\005\372A-\n+cloudresourc"
-          + "emanager.googleapis.com/Project\022\033\n\016metag"
-          + "eneration\030\004 \001(\003B\003\340A\003\022\025\n\010location\030\005 \001(\tB\003"
-          + "\340A\005\022\032\n\rlocation_type\030\006 \001(\tB\003\340A\003\022\025\n\rstora"
-          + "ge_class\030\007 \001(\t\022\013\n\003rpo\030\033 \001(\t\0223\n\003acl\030\010 \003(\013"
-          + "2&.google.storage.v2.BucketAccessControl"
-          + "\022B\n\022default_object_acl\030\t \003(\0132&.google.st"
-          + "orage.v2.ObjectAccessControl\0226\n\tlifecycl"
-          + "e\030\n \001(\0132#.google.storage.v2.Bucket.Lifec"
-          + "ycle\0224\n\013create_time\030\013 \001(\0132\032.google.proto"
-          + "buf.TimestampB\003\340A\003\022,\n\004cors\030\014 \003(\0132\036.googl"
-          + "e.storage.v2.Bucket.Cors\0224\n\013update_time\030"
-          + "\r \001(\0132\032.google.protobuf.TimestampB\003\340A\003\022 "
-          + "\n\030default_event_based_hold\030\016 \001(\010\0225\n\006labe"
-          + "ls\030\017 \003(\0132%.google.storage.v2.Bucket.Labe"
-          + "lsEntry\0222\n\007website\030\020 \001(\0132!.google.storag"
-          + "e.v2.Bucket.Website\0228\n\nversioning\030\021 \001(\0132"
-          + "$.google.storage.v2.Bucket.Versioning\0222\n"
-          + "\007logging\030\022 \001(\0132!.google.storage.v2.Bucke"
-          + "t.Logging\022,\n\005owner\030\023 \001(\0132\030.google.storag"
-          + "e.v2.OwnerB\003\340A\003\0228\n\nencryption\030\024 \001(\0132$.go"
-          + "ogle.storage.v2.Bucket.Encryption\0222\n\007bil"
-          + "ling\030\025 \001(\0132!.google.storage.v2.Bucket.Bi"
-          + "lling\022C\n\020retention_policy\030\026 \001(\0132).google"
-          + ".storage.v2.Bucket.RetentionPolicy\0227\n\nia"
-          + "m_config\030\027 \001(\0132#.google.storage.v2.Bucke"
-          + "t.IamConfig\022\025\n\rsatisfies_pzs\030\031 \001(\010\0226\n\tau"
-          + "toclass\030\034 \001(\0132#.google.storage.v2.Bucket"
-          + ".Autoclass\032!\n\007Billing\022\026\n\016requester_pays\030"
-          + "\001 \001(\010\032X\n\004Cors\022\016\n\006origin\030\001 \003(\t\022\016\n\006method\030"
-          + "\002 \003(\t\022\027\n\017response_header\030\003 \003(\t\022\027\n\017max_ag"
-          + "e_seconds\030\004 \001(\005\032M\n\nEncryption\022?\n\017default"
-          + "_kms_key\030\001 \001(\tB&\372A#\n!cloudkms.googleapis"
-          + ".com/CryptoKey\032\354\001\n\tIamConfig\022a\n\033uniform_"
-          + "bucket_level_access\030\001 \001(\0132<.google.stora"
-          + "ge.v2.Bucket.IamConfig.UniformBucketLeve"
-          + "lAccess\022 \n\030public_access_prevention\030\003 \001("
-          + "\t\032Z\n\030UniformBucketLevelAccess\022\017\n\007enabled"
-          + "\030\001 \001(\010\022-\n\tlock_time\030\002 \001(\0132\032.google.proto"
-          + "buf.Timestamp\032\363\005\n\tLifecycle\0226\n\004rule\030\001 \003("
-          + "\0132(.google.storage.v2.Bucket.Lifecycle.R"
-          + "ule\032\255\005\n\004Rule\022?\n\006action\030\001 \001(\0132/.google.st"
-          + "orage.v2.Bucket.Lifecycle.Rule.Action\022E\n"
-          + "\tcondition\030\002 \001(\01322.google.storage.v2.Buc"
-          + "ket.Lifecycle.Rule.Condition\032-\n\006Action\022\014"
-          + "\n\004type\030\001 \001(\t\022\025\n\rstorage_class\030\002 \001(\t\032\355\003\n\t"
-          + "Condition\022\025\n\010age_days\030\001 \001(\005H\000\210\001\001\022)\n\016crea"
-          + "ted_before\030\002 \001(\0132\021.google.type.Date\022\024\n\007i"
-          + "s_live\030\003 \001(\010H\001\210\001\001\022\037\n\022num_newer_versions\030"
-          + "\004 \001(\005H\002\210\001\001\022\035\n\025matches_storage_class\030\005 \003("
-          + "\t\022#\n\026days_since_custom_time\030\007 \001(\005H\003\210\001\001\022-"
-          + "\n\022custom_time_before\030\010 \001(\0132\021.google.type"
-          + ".Date\022\'\n\032days_since_noncurrent_time\030\t \001("
-          + "\005H\004\210\001\001\0221\n\026noncurrent_time_before\030\n \001(\0132\021"
-          + ".google.type.Date\022\026\n\016matches_prefix\030\013 \003("
-          + "\t\022\026\n\016matches_suffix\030\014 \003(\tB\013\n\t_age_daysB\n"
-          + "\n\010_is_liveB\025\n\023_num_newer_versionsB\031\n\027_da"
-          + "ys_since_custom_timeB\035\n\033_days_since_nonc"
-          + "urrent_time\0328\n\007Logging\022\022\n\nlog_bucket\030\001 \001"
-          + "(\t\022\031\n\021log_object_prefix\030\002 \001(\t\032r\n\017Retenti"
-          + "onPolicy\0222\n\016effective_time\030\001 \001(\0132\032.googl"
-          + "e.protobuf.Timestamp\022\021\n\tis_locked\030\002 \001(\010\022"
-          + "\030\n\020retention_period\030\003 \001(\003\032\035\n\nVersioning\022"
-          + "\017\n\007enabled\030\001 \001(\010\032;\n\007Website\022\030\n\020main_page"
-          + "_suffix\030\001 \001(\t\022\026\n\016not_found_page\030\002 \001(\t\032R\n"
-          + "\tAutoclass\022\017\n\007enabled\030\001 \001(\010\0224\n\013toggle_ti"
-          + "me\030\002 \001(\0132\032.google.protobuf.TimestampB\003\340A"
-          + "\003\032-\n\013LabelsEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002"
-          + " \001(\t:\0028\001:G\352AD\n\035storage.googleapis.com/Bu"
-          + "cket\022#projects/{project}/buckets/{bucket"
-          + "}\"\247\001\n\023BucketAccessControl\022\014\n\004role\030\001 \001(\t\022"
-          + "\n\n\002id\030\002 \001(\t\022\016\n\006entity\030\003 \001(\t\022\021\n\tentity_id"
-          + "\030\004 \001(\t\022\r\n\005email\030\005 \001(\t\022\016\n\006domain\030\006 \001(\t\0224\n"
-          + "\014project_team\030\007 \001(\0132\036.google.storage.v2."
-          + "ProjectTeam\"B\n\017ChecksummedData\022\017\n\007conten"
-          + "t\030\001 \001(\014\022\023\n\006crc32c\030\002 \001(\007H\000\210\001\001B\t\n\007_crc32c\""
-          + "C\n\017ObjectChecksums\022\023\n\006crc32c\030\001 \001(\007H\000\210\001\001\022"
-          + "\020\n\010md5_hash\030\002 \001(\014B\t\n\007_crc32c\"\203\002\n\017HmacKey"
-          + "Metadata\022\n\n\002id\030\001 \001(\t\022\021\n\taccess_id\030\002 \001(\t\022"
-          + "A\n\007project\030\003 \001(\tB0\372A-\n+cloudresourcemana"
-          + "ger.googleapis.com/Project\022\035\n\025service_ac"
-          + "count_email\030\004 \001(\t\022\r\n\005state\030\005 \001(\t\022/\n\013crea"
-          + "te_time\030\006 \001(\0132\032.google.protobuf.Timestam"
-          + "p\022/\n\013update_time\030\007 \001(\0132\032.google.protobuf"
-          + ".Timestamp\"\217\003\n\014Notification\022\021\n\004name\030\001 \001("
-          + "\tB\003\340A\002\022\022\n\005topic\030\002 \001(\tB\003\340A\002\022\030\n\013event_type"
-          + "s\030\003 \003(\tB\003\340A\001\022U\n\021custom_attributes\030\004 \003(\0132"
-          + "5.google.storage.v2.Notification.CustomA"
-          + "ttributesEntryB\003\340A\001\022\037\n\022object_name_prefi"
-          + "x\030\005 \001(\tB\003\340A\001\022\033\n\016payload_format\030\006 \001(\tB\003\340A"
-          + "\002\0327\n\025CustomAttributesEntry\022\013\n\003key\030\001 \001(\t\022"
-          + "\r\n\005value\030\002 \001(\t:\0028\001:p\352Am\n#storage.googlea"
-          + "pis.com/Notification\022Fprojects/{project}"
-          + "/buckets/{bucket}/notificationConfigs/{n"
-          + "otification}\"L\n\022CustomerEncryption\022\034\n\024en"
-          + "cryption_algorithm\030\001 \001(\t\022\030\n\020key_sha256_b"
-          + "ytes\030\003 \001(\014\"\364\010\n\006Object\022\021\n\004name\030\001 \001(\tB\003\340A\005"
-          + "\0225\n\006bucket\030\002 \001(\tB%\340A\005\372A\037\n\035storage.google"
-          + "apis.com/Bucket\022\027\n\ngeneration\030\003 \001(\003B\003\340A\005"
-          + "\022\033\n\016metageneration\030\004 \001(\003B\003\340A\003\022\025\n\rstorage"
-          + "_class\030\005 \001(\t\022\021\n\004size\030\006 \001(\003B\003\340A\003\022\030\n\020conte"
-          + "nt_encoding\030\007 \001(\t\022\033\n\023content_disposition"
-          + "\030\010 \001(\t\022\025\n\rcache_control\030\t \001(\t\0223\n\003acl\030\n \003"
+          + "\003\022\014\n\004etag\030\035 \001(\t\022D\n\007project\030\003 \001(\tB3\340A\005\372A-"
+          + "\n+cloudresourcemanager.googleapis.com/Pr"
+          + "oject\022\033\n\016metageneration\030\004 \001(\003B\003\340A\003\022\025\n\010lo"
+          + "cation\030\005 \001(\tB\003\340A\005\022\032\n\rlocation_type\030\006 \001(\t"
+          + "B\003\340A\003\022\025\n\rstorage_class\030\007 \001(\t\022\013\n\003rpo\030\033 \001("
+          + "\t\0223\n\003acl\030\010 \003(\0132&.google.storage.v2.Bucke"
+          + "tAccessControl\022B\n\022default_object_acl\030\t \003"
           + "(\0132&.google.storage.v2.ObjectAccessContr"
-          + "ol\022\030\n\020content_language\030\013 \001(\t\0224\n\013delete_t"
-          + "ime\030\014 \001(\0132\032.google.protobuf.TimestampB\003\340"
-          + "A\003\022\024\n\014content_type\030\r \001(\t\0224\n\013create_time\030"
-          + "\016 \001(\0132\032.google.protobuf.TimestampB\003\340A\003\022\034"
-          + "\n\017component_count\030\017 \001(\005B\003\340A\003\022:\n\tchecksum"
-          + "s\030\020 \001(\0132\".google.storage.v2.ObjectChecks"
-          + "umsB\003\340A\003\0224\n\013update_time\030\021 \001(\0132\032.google.p"
-          + "rotobuf.TimestampB\003\340A\003\0227\n\007kms_key\030\022 \001(\tB"
-          + "&\372A#\n!cloudkms.googleapis.com/CryptoKey\022"
-          + "B\n\031update_storage_class_time\030\023 \001(\0132\032.goo"
-          + "gle.protobuf.TimestampB\003\340A\003\022\026\n\016temporary"
-          + "_hold\030\024 \001(\010\0229\n\025retention_expire_time\030\025 \001"
-          + "(\0132\032.google.protobuf.Timestamp\0229\n\010metada"
-          + "ta\030\026 \003(\0132\'.google.storage.v2.Object.Meta"
-          + "dataEntry\022\035\n\020event_based_hold\030\027 \001(\010H\000\210\001\001"
-          + "\022,\n\005owner\030\030 \001(\0132\030.google.storage.v2.Owne"
-          + "rB\003\340A\003\022B\n\023customer_encryption\030\031 \001(\0132%.go"
-          + "ogle.storage.v2.CustomerEncryption\022/\n\013cu"
-          + "stom_time\030\032 \001(\0132\032.google.protobuf.Timest"
-          + "amp\032/\n\rMetadataEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005val"
-          + "ue\030\002 \001(\t:\0028\001B\023\n\021_event_based_hold\"\247\001\n\023Ob"
-          + "jectAccessControl\022\014\n\004role\030\001 \001(\t\022\n\n\002id\030\002 "
-          + "\001(\t\022\016\n\006entity\030\003 \001(\t\022\021\n\tentity_id\030\004 \001(\t\022\r"
-          + "\n\005email\030\005 \001(\t\022\016\n\006domain\030\006 \001(\t\0224\n\014project"
-          + "_team\030\007 \001(\0132\036.google.storage.v2.ProjectT"
-          + "eam\"l\n\023ListObjectsResponse\022*\n\007objects\030\001 "
-          + "\003(\0132\031.google.storage.v2.Object\022\020\n\010prefix"
-          + "es\030\002 \003(\t\022\027\n\017next_page_token\030\003 \001(\t\"3\n\013Pro"
-          + "jectTeam\022\026\n\016project_number\030\001 \001(\t\022\014\n\004team"
-          + "\030\002 \001(\t\"\'\n\016ServiceAccount\022\025\n\remail_addres"
-          + "s\030\001 \001(\t\"*\n\005Owner\022\016\n\006entity\030\001 \001(\t\022\021\n\tenti"
-          + "ty_id\030\002 \001(\t\"C\n\014ContentRange\022\r\n\005start\030\001 \001"
-          + "(\003\022\013\n\003end\030\002 \001(\003\022\027\n\017complete_length\030\003 \001(\003"
-          + "2\260\033\n\007Storage\022W\n\014DeleteBucket\022&.google.st"
-          + "orage.v2.DeleteBucketRequest\032\026.google.pr"
-          + "otobuf.Empty\"\007\332A\004name\022T\n\tGetBucket\022#.goo"
-          + "gle.storage.v2.GetBucketRequest\032\031.google"
-          + ".storage.v2.Bucket\"\007\332A\004name\022m\n\014CreateBuc"
-          + "ket\022&.google.storage.v2.CreateBucketRequ"
-          + "est\032\031.google.storage.v2.Bucket\"\032\332A\027paren"
-          + "t,bucket,bucket_id\022g\n\013ListBuckets\022%.goog",
-      "le.storage.v2.ListBucketsRequest\032&.googl"
-          + "e.storage.v2.ListBucketsResponse\"\t\332A\006par"
-          + "ent\022v\n\031LockBucketRetentionPolicy\0223.googl"
-          + "e.storage.v2.LockBucketRetentionPolicyRe"
-          + "quest\032\031.google.storage.v2.Bucket\"\t\332A\006buc"
-          + "ket\022V\n\014GetIamPolicy\022\".google.iam.v1.GetI"
-          + "amPolicyRequest\032\025.google.iam.v1.Policy\"\013"
-          + "\332A\010resource\022]\n\014SetIamPolicy\022\".google.iam"
-          + ".v1.SetIamPolicyRequest\032\025.google.iam.v1."
-          + "Policy\"\022\332A\017resource,policy\022\202\001\n\022TestIamPe"
-          + "rmissions\022(.google.iam.v1.TestIamPermiss"
-          + "ionsRequest\032).google.iam.v1.TestIamPermi"
-          + "ssionsResponse\"\027\332A\024resource,permissions\022"
-          + "h\n\014UpdateBucket\022&.google.storage.v2.Upda"
-          + "teBucketRequest\032\031.google.storage.v2.Buck"
-          + "et\"\025\332A\022bucket,update_mask\022c\n\022DeleteNotif"
-          + "ication\022,.google.storage.v2.DeleteNotifi"
-          + "cationRequest\032\026.google.protobuf.Empty\"\007\332"
-          + "A\004name\022f\n\017GetNotification\022).google.stora"
-          + "ge.v2.GetNotificationRequest\032\037.google.st"
-          + "orage.v2.Notification\"\007\332A\004name\022{\n\022Create"
-          + "Notification\022,.google.storage.v2.CreateN"
-          + "otificationRequest\032\037.google.storage.v2.N"
-          + "otification\"\026\332A\023parent,notification\022y\n\021L"
-          + "istNotifications\022+.google.storage.v2.Lis"
-          + "tNotificationsRequest\032,.google.storage.v"
-          + "2.ListNotificationsResponse\"\t\332A\006parent\022U"
-          + "\n\rComposeObject\022\'.google.storage.v2.Comp"
-          + "oseObjectRequest\032\031.google.storage.v2.Obj"
-          + "ect\"\000\022{\n\014DeleteObject\022&.google.storage.v"
-          + "2.DeleteObjectRequest\032\026.google.protobuf."
-          + "Empty\"+\332A\rbucket,object\332A\030bucket,object,"
-          + "generation\022x\n\tGetObject\022#.google.storage"
-          + ".v2.GetObjectRequest\032\031.google.storage.v2"
-          + ".Object\"+\332A\rbucket,object\332A\030bucket,objec"
-          + "t,generation\022\210\001\n\nReadObject\022$.google.sto"
-          + "rage.v2.ReadObjectRequest\032%.google.stora"
-          + "ge.v2.ReadObjectResponse\"+\332A\rbucket,obje"
-          + "ct\332A\030bucket,object,generation0\001\022h\n\014Updat"
-          + "eObject\022&.google.storage.v2.UpdateObject"
-          + "Request\032\031.google.storage.v2.Object\"\025\332A\022o"
-          + "bject,update_mask\022`\n\013WriteObject\022%.googl"
-          + "e.storage.v2.WriteObjectRequest\032&.google"
-          + ".storage.v2.WriteObjectResponse\"\000(\001\022g\n\013L"
-          + "istObjects\022%.google.storage.v2.ListObjec"
-          + "tsRequest\032&.google.storage.v2.ListObject"
-          + "sResponse\"\t\332A\006parent\022^\n\rRewriteObject\022\'."
-          + "google.storage.v2.RewriteObjectRequest\032\""
-          + ".google.storage.v2.RewriteResponse\"\000\022v\n\023"
-          + "StartResumableWrite\022-.google.storage.v2."
-          + "StartResumableWriteRequest\032..google.stor"
-          + "age.v2.StartResumableWriteResponse\"\000\022y\n\020"
-          + "QueryWriteStatus\022*.google.storage.v2.Que"
-          + "ryWriteStatusRequest\032+.google.storage.v2"
-          + ".QueryWriteStatusResponse\"\014\332A\tupload_id\022"
-          + "o\n\021GetServiceAccount\022+.google.storage.v2"
-          + ".GetServiceAccountRequest\032!.google.stora"
-          + "ge.v2.ServiceAccount\"\n\332A\007project\022\204\001\n\rCre"
-          + "ateHmacKey\022\'.google.storage.v2.CreateHma"
-          + "cKeyRequest\032(.google.storage.v2.CreateHm"
-          + "acKeyResponse\" \332A\035project,service_accoun"
-          + "t_email\022f\n\rDeleteHmacKey\022\'.google.storag"
-          + "e.v2.DeleteHmacKeyRequest\032\026.google.proto"
-          + "buf.Empty\"\024\332A\021access_id,project\022l\n\nGetHm"
-          + "acKey\022$.google.storage.v2.GetHmacKeyRequ"
+          + "ol\0226\n\tlifecycle\030\n \001(\0132#.google.storage.v"
+          + "2.Bucket.Lifecycle\0224\n\013create_time\030\013 \001(\0132"
+          + "\032.google.protobuf.TimestampB\003\340A\003\022,\n\004cors"
+          + "\030\014 \003(\0132\036.google.storage.v2.Bucket.Cors\0224"
+          + "\n\013update_time\030\r \001(\0132\032.google.protobuf.Ti"
+          + "mestampB\003\340A\003\022 \n\030default_event_based_hold"
+          + "\030\016 \001(\010\0225\n\006labels\030\017 \003(\0132%.google.storage."
+          + "v2.Bucket.LabelsEntry\0222\n\007website\030\020 \001(\0132!"
+          + ".google.storage.v2.Bucket.Website\0228\n\nver"
+          + "sioning\030\021 \001(\0132$.google.storage.v2.Bucket"
+          + ".Versioning\0222\n\007logging\030\022 \001(\0132!.google.st"
+          + "orage.v2.Bucket.Logging\022,\n\005owner\030\023 \001(\0132\030"
+          + ".google.storage.v2.OwnerB\003\340A\003\0228\n\nencrypt"
+          + "ion\030\024 \001(\0132$.google.storage.v2.Bucket.Enc"
+          + "ryption\0222\n\007billing\030\025 \001(\0132!.google.storag"
+          + "e.v2.Bucket.Billing\022C\n\020retention_policy\030"
+          + "\026 \001(\0132).google.storage.v2.Bucket.Retenti"
+          + "onPolicy\0227\n\niam_config\030\027 \001(\0132#.google.st"
+          + "orage.v2.Bucket.IamConfig\022\025\n\rsatisfies_p"
+          + "zs\030\031 \001(\010\022P\n\027custom_placement_config\030\032 \001("
+          + "\0132/.google.storage.v2.Bucket.CustomPlace"
+          + "mentConfig\0226\n\tautoclass\030\034 \001(\0132#.google.s"
+          + "torage.v2.Bucket.Autoclass\032!\n\007Billing\022\026\n"
+          + "\016requester_pays\030\001 \001(\010\032X\n\004Cors\022\016\n\006origin\030"
+          + "\001 \003(\t\022\016\n\006method\030\002 \003(\t\022\027\n\017response_header"
+          + "\030\003 \003(\t\022\027\n\017max_age_seconds\030\004 \001(\005\032M\n\nEncry"
+          + "ption\022?\n\017default_kms_key\030\001 \001(\tB&\372A#\n!clo"
+          + "udkms.googleapis.com/CryptoKey\032\354\001\n\tIamCo"
+          + "nfig\022a\n\033uniform_bucket_level_access\030\001 \001("
+          + "\0132<.google.storage.v2.Bucket.IamConfig.U"
+          + "niformBucketLevelAccess\022 \n\030public_access"
+          + "_prevention\030\003 \001(\t\032Z\n\030UniformBucketLevelA"
+          + "ccess\022\017\n\007enabled\030\001 \001(\010\022-\n\tlock_time\030\002 \001("
+          + "\0132\032.google.protobuf.Timestamp\032\363\005\n\tLifecy"
+          + "cle\0226\n\004rule\030\001 \003(\0132(.google.storage.v2.Bu"
+          + "cket.Lifecycle.Rule\032\255\005\n\004Rule\022?\n\006action\030\001"
+          + " \001(\0132/.google.storage.v2.Bucket.Lifecycl"
+          + "e.Rule.Action\022E\n\tcondition\030\002 \001(\01322.googl"
+          + "e.storage.v2.Bucket.Lifecycle.Rule.Condi"
+          + "tion\032-\n\006Action\022\014\n\004type\030\001 \001(\t\022\025\n\rstorage_"
+          + "class\030\002 \001(\t\032\355\003\n\tCondition\022\025\n\010age_days\030\001 "
+          + "\001(\005H\000\210\001\001\022)\n\016created_before\030\002 \001(\0132\021.googl"
+          + "e.type.Date\022\024\n\007is_live\030\003 \001(\010H\001\210\001\001\022\037\n\022num"
+          + "_newer_versions\030\004 \001(\005H\002\210\001\001\022\035\n\025matches_st"
+          + "orage_class\030\005 \003(\t\022#\n\026days_since_custom_t"
+          + "ime\030\007 \001(\005H\003\210\001\001\022-\n\022custom_time_before\030\010 \001"
+          + "(\0132\021.google.type.Date\022\'\n\032days_since_nonc"
+          + "urrent_time\030\t \001(\005H\004\210\001\001\0221\n\026noncurrent_tim"
+          + "e_before\030\n \001(\0132\021.google.type.Date\022\026\n\016mat"
+          + "ches_prefix\030\013 \003(\t\022\026\n\016matches_suffix\030\014 \003("
+          + "\tB\013\n\t_age_daysB\n\n\010_is_liveB\025\n\023_num_newer"
+          + "_versionsB\031\n\027_days_since_custom_timeB\035\n\033"
+          + "_days_since_noncurrent_time\0328\n\007Logging\022\022"
+          + "\n\nlog_bucket\030\001 \001(\t\022\031\n\021log_object_prefix\030"
+          + "\002 \001(\t\032r\n\017RetentionPolicy\0222\n\016effective_ti"
+          + "me\030\001 \001(\0132\032.google.protobuf.Timestamp\022\021\n\t"
+          + "is_locked\030\002 \001(\010\022\030\n\020retention_period\030\003 \001("
+          + "\003\032\035\n\nVersioning\022\017\n\007enabled\030\001 \001(\010\032;\n\007Webs"
+          + "ite\022\030\n\020main_page_suffix\030\001 \001(\t\022\026\n\016not_fou"
+          + "nd_page\030\002 \001(\t\032/\n\025CustomPlacementConfig\022\026"
+          + "\n\016data_locations\030\001 \003(\t\032R\n\tAutoclass\022\017\n\007e"
+          + "nabled\030\001 \001(\010\0224\n\013toggle_time\030\002 \001(\0132\032.goog"
+          + "le.protobuf.TimestampB\003\340A\003\032-\n\013LabelsEntr"
+          + "y\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001:G\352AD\n\035"
+          + "storage.googleapis.com/Bucket\022#projects/"
+          + "{project}/buckets/{bucket}\"\265\001\n\023BucketAcc"
+          + "essControl\022\014\n\004role\030\001 \001(\t\022\n\n\002id\030\002 \001(\t\022\016\n\006"
+          + "entity\030\003 \001(\t\022\021\n\tentity_id\030\004 \001(\t\022\014\n\004etag\030"
+          + "\010 \001(\t\022\r\n\005email\030\005 \001(\t\022\016\n\006domain\030\006 \001(\t\0224\n\014"
+          + "project_team\030\007 \001(\0132\036.google.storage.v2.P"
+          + "rojectTeam\"B\n\017ChecksummedData\022\017\n\007content"
+          + "\030\001 \001(\014\022\023\n\006crc32c\030\002 \001(\007H\000\210\001\001B\t\n\007_crc32c\"C"
+          + "\n\017ObjectChecksums\022\023\n\006crc32c\030\001 \001(\007H\000\210\001\001\022\020"
+          + "\n\010md5_hash\030\002 \001(\014B\t\n\007_crc32c\"\221\002\n\017HmacKeyM"
+          + "etadata\022\n\n\002id\030\001 \001(\t\022\021\n\taccess_id\030\002 \001(\t\022A"
+          + "\n\007project\030\003 \001(\tB0\372A-\n+cloudresourcemanag"
+          + "er.googleapis.com/Project\022\035\n\025service_acc"
+          + "ount_email\030\004 \001(\t\022\r\n\005state\030\005 \001(\t\022/\n\013creat"
+          + "e_time\030\006 \001(\0132\032.google.protobuf.Timestamp"
+          + "\022/\n\013update_time\030\007 \001(\0132\032.google.protobuf."
+          + "Timestamp\022\014\n\004etag\030\010 \001(\t\"\235\003\n\014Notification"
+          + "\022\021\n\004name\030\001 \001(\tB\003\340A\002\022\022\n\005topic\030\002 \001(\tB\003\340A\002\022"
+          + "\014\n\004etag\030\007 \001(\t\022\030\n\013event_types\030\003 \003(\tB\003\340A\001\022"
+          + "U\n\021custom_attributes\030\004 \003(\01325.google.stor"
+          + "age.v2.Notification.CustomAttributesEntr"
+          + "yB\003\340A\001\022\037\n\022object_name_prefix\030\005 \001(\tB\003\340A\001\022"
+          + "\033\n\016payload_format\030\006 \001(\tB\003\340A\002\0327\n\025CustomAt"
+          + "tributesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001("
+          + "\t:\0028\001:p\352Am\n#storage.googleapis.com/Notif"
+          + "ication\022Fprojects/{project}/buckets/{buc"
+          + "ket}/notificationConfigs/{notification}\""
+          + "L\n\022CustomerEncryption\022\034\n\024encryption_algo"
+          + "rithm\030\001 \001(\t\022\030\n\020key_sha256_bytes\030\003 \001(\014\"\202\t"
+          + "\n\006Object\022\021\n\004name\030\001 \001(\tB\003\340A\005\0225\n\006bucket\030\002 "
+          + "\001(\tB%\340A\005\372A\037\n\035storage.googleapis.com/Buck"
+          + "et\022\014\n\004etag\030\033 \001(\t\022\027\n\ngeneration\030\003 \001(\003B\003\340A"
+          + "\005\022\033\n\016metageneration\030\004 \001(\003B\003\340A\003\022\025\n\rstorag"
+          + "e_class\030\005 \001(\t\022\021\n\004size\030\006 \001(\003B\003\340A\003\022\030\n\020cont"
+          + "ent_encoding\030\007 \001(\t\022\033\n\023content_dispositio"
+          + "n\030\010 \001(\t\022\025\n\rcache_control\030\t \001(\t\0223\n\003acl\030\n "
+          + "\003(\0132&.google.storage.v2.ObjectAccessCont"
+          + "rol\022\030\n\020content_language\030\013 \001(\t\0224\n\013delete_"
+          + "time\030\014 \001(\0132\032.google.protobuf.TimestampB\003"
+          + "\340A\003\022\024\n\014content_type\030\r \001(\t\0224\n\013create_time"
+          + "\030\016 \001(\0132\032.google.protobuf.TimestampB\003\340A\003\022"
+          + "\034\n\017component_count\030\017 \001(\005B\003\340A\003\022:\n\tchecksu"
+          + "ms\030\020 \001(\0132\".google.storage.v2.ObjectCheck"
+          + "sumsB\003\340A\003\0224\n\013update_time\030\021 \001(\0132\032.google."
+          + "protobuf.TimestampB\003\340A\003\0227\n\007kms_key\030\022 \001(\t"
+          + "B&\372A#\n!cloudkms.googleapis.com/CryptoKey"
+          + "\022B\n\031update_storage_class_time\030\023 \001(\0132\032.go"
+          + "ogle.protobuf.TimestampB\003\340A\003\022\026\n\016temporar"
+          + "y_hold\030\024 \001(\010\0229\n\025retention_expire_time\030\025 "
+          + "\001(\0132\032.google.protobuf.Timestamp\0229\n\010metad"
+          + "ata\030\026 \003(\0132\'.google.storage.v2.Object.Met"
+          + "adataEntry\022\035\n\020event_based_hold\030\027 \001(\010H\000\210\001"
+          + "\001\022,\n\005owner\030\030 \001(\0132\030.google.storage.v2.Own"
+          + "erB\003\340A\003\022B\n\023customer_encryption\030\031 \001(\0132%.g"
+          + "oogle.storage.v2.CustomerEncryption\022/\n\013c"
+          + "ustom_time\030\032 \001(\0132\032.google.protobuf.Times"
+          + "tamp\032/\n\rMetadataEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005va"
+          + "lue\030\002 \001(\t:\0028\001B\023\n\021_event_based_hold\"\265\001\n\023O"
+          + "bjectAccessControl\022\014\n\004role\030\001 \001(\t\022\n\n\002id\030\002"
+          + " \001(\t\022\016\n\006entity\030\003 \001(\t\022\021\n\tentity_id\030\004 \001(\t\022"
+          + "\014\n\004etag\030\010 \001(\t\022\r\n\005email\030\005 \001(\t\022\016\n\006domain\030\006"
+          + " \001(\t\0224\n\014project_team\030\007 \001(\0132\036.google.stor"
+          + "age.v2.ProjectTeam\"l\n\023ListObjectsRespons"
+          + "e\022*\n\007objects\030\001 \003(\0132\031.google.storage.v2.O"
+          + "bject\022\020\n\010prefixes\030\002 \003(\t\022\027\n\017next_page_tok"
+          + "en\030\003 \001(\t\"3\n\013ProjectTeam\022\026\n\016project_numbe"
+          + "r\030\001 \001(\t\022\014\n\004team\030\002 \001(\t\"\'\n\016ServiceAccount\022"
+          + "\025\n\remail_address\030\001 \001(\t\"*\n\005Owner\022\016\n\006entit"
+          + "y\030\001 \001(\t\022\021\n\tentity_id\030\002 \001(\t\"C\n\014ContentRan"
+          + "ge\022\r\n\005start\030\001 \001(\003\022\013\n\003end\030\002 \001(\003\022\027\n\017comple"
+          + "te_length\030\003 \001(\0032\260\033\n\007Storage\022W\n\014DeleteBuc"
+          + "ket\022&.google.storage.v2.DeleteBucketRequ"
+          + "est\032\026.google.protobuf.Empty\"\007\332A\004name\022T\n\t",
+      "GetBucket\022#.google.storage.v2.GetBucketR"
+          + "equest\032\031.google.storage.v2.Bucket\"\007\332A\004na"
+          + "me\022m\n\014CreateBucket\022&.google.storage.v2.C"
+          + "reateBucketRequest\032\031.google.storage.v2.B"
+          + "ucket\"\032\332A\027parent,bucket,bucket_id\022g\n\013Lis"
+          + "tBuckets\022%.google.storage.v2.ListBuckets"
+          + "Request\032&.google.storage.v2.ListBucketsR"
+          + "esponse\"\t\332A\006parent\022v\n\031LockBucketRetentio"
+          + "nPolicy\0223.google.storage.v2.LockBucketRe"
+          + "tentionPolicyRequest\032\031.google.storage.v2"
+          + ".Bucket\"\t\332A\006bucket\022V\n\014GetIamPolicy\022\".goo"
+          + "gle.iam.v1.GetIamPolicyRequest\032\025.google."
+          + "iam.v1.Policy\"\013\332A\010resource\022]\n\014SetIamPoli"
+          + "cy\022\".google.iam.v1.SetIamPolicyRequest\032\025"
+          + ".google.iam.v1.Policy\"\022\332A\017resource,polic"
+          + "y\022\202\001\n\022TestIamPermissions\022(.google.iam.v1"
+          + ".TestIamPermissionsRequest\032).google.iam."
+          + "v1.TestIamPermissionsResponse\"\027\332A\024resour"
+          + "ce,permissions\022h\n\014UpdateBucket\022&.google."
+          + "storage.v2.UpdateBucketRequest\032\031.google."
+          + "storage.v2.Bucket\"\025\332A\022bucket,update_mask"
+          + "\022c\n\022DeleteNotification\022,.google.storage."
+          + "v2.DeleteNotificationRequest\032\026.google.pr"
+          + "otobuf.Empty\"\007\332A\004name\022f\n\017GetNotification"
+          + "\022).google.storage.v2.GetNotificationRequ"
+          + "est\032\037.google.storage.v2.Notification\"\007\332A"
+          + "\004name\022{\n\022CreateNotification\022,.google.sto"
+          + "rage.v2.CreateNotificationRequest\032\037.goog"
+          + "le.storage.v2.Notification\"\026\332A\023parent,no"
+          + "tification\022y\n\021ListNotifications\022+.google"
+          + ".storage.v2.ListNotificationsRequest\032,.g"
+          + "oogle.storage.v2.ListNotificationsRespon"
+          + "se\"\t\332A\006parent\022U\n\rComposeObject\022\'.google."
+          + "storage.v2.ComposeObjectRequest\032\031.google"
+          + ".storage.v2.Object\"\000\022{\n\014DeleteObject\022&.g"
+          + "oogle.storage.v2.DeleteObjectRequest\032\026.g"
+          + "oogle.protobuf.Empty\"+\332A\rbucket,object\332A"
+          + "\030bucket,object,generation\022x\n\tGetObject\022#"
+          + ".google.storage.v2.GetObjectRequest\032\031.go"
+          + "ogle.storage.v2.Object\"+\332A\rbucket,object"
+          + "\332A\030bucket,object,generation\022\210\001\n\nReadObje"
+          + "ct\022$.google.storage.v2.ReadObjectRequest"
+          + "\032%.google.storage.v2.ReadObjectResponse\""
+          + "+\332A\rbucket,object\332A\030bucket,object,genera"
+          + "tion0\001\022h\n\014UpdateObject\022&.google.storage."
+          + "v2.UpdateObjectRequest\032\031.google.storage."
+          + "v2.Object\"\025\332A\022object,update_mask\022`\n\013Writ"
+          + "eObject\022%.google.storage.v2.WriteObjectR"
+          + "equest\032&.google.storage.v2.WriteObjectRe"
+          + "sponse\"\000(\001\022g\n\013ListObjects\022%.google.stora"
+          + "ge.v2.ListObjectsRequest\032&.google.storag"
+          + "e.v2.ListObjectsResponse\"\t\332A\006parent\022^\n\rR"
+          + "ewriteObject\022\'.google.storage.v2.Rewrite"
+          + "ObjectRequest\032\".google.storage.v2.Rewrit"
+          + "eResponse\"\000\022v\n\023StartResumableWrite\022-.goo"
+          + "gle.storage.v2.StartResumableWriteReques"
+          + "t\032..google.storage.v2.StartResumableWrit"
+          + "eResponse\"\000\022y\n\020QueryWriteStatus\022*.google"
+          + ".storage.v2.QueryWriteStatusRequest\032+.go"
+          + "ogle.storage.v2.QueryWriteStatusResponse"
+          + "\"\014\332A\tupload_id\022o\n\021GetServiceAccount\022+.go"
+          + "ogle.storage.v2.GetServiceAccountRequest"
+          + "\032!.google.storage.v2.ServiceAccount\"\n\332A\007"
+          + "project\022\204\001\n\rCreateHmacKey\022\'.google.stora"
+          + "ge.v2.CreateHmacKeyRequest\032(.google.stor"
+          + "age.v2.CreateHmacKeyResponse\" \332A\035project"
+          + ",service_account_email\022f\n\rDeleteHmacKey\022"
+          + "\'.google.storage.v2.DeleteHmacKeyRequest"
+          + "\032\026.google.protobuf.Empty\"\024\332A\021access_id,p"
+          + "roject\022l\n\nGetHmacKey\022$.google.storage.v2"
+          + ".GetHmacKeyRequest\032\".google.storage.v2.H"
+          + "macKeyMetadata\"\024\332A\021access_id,project\022k\n\014"
+          + "ListHmacKeys\022&.google.storage.v2.ListHma"
+          + "cKeysRequest\032\'.google.storage.v2.ListHma"
+          + "cKeysResponse\"\n\332A\007project\022u\n\rUpdateHmacK"
+          + "ey\022\'.google.storage.v2.UpdateHmacKeyRequ"
           + "est\032\".google.storage.v2.HmacKeyMetadata\""
-          + "\024\332A\021access_id,project\022k\n\014ListHmacKeys\022&."
-          + "google.storage.v2.ListHmacKeysRequest\032\'."
-          + "google.storage.v2.ListHmacKeysResponse\"\n"
-          + "\332A\007project\022u\n\rUpdateHmacKey\022\'.google.sto"
-          + "rage.v2.UpdateHmacKeyRequest\032\".google.st"
-          + "orage.v2.HmacKeyMetadata\"\027\332A\024hmac_key,up"
-          + "date_mask\032\247\002\312A\026storage.googleapis.com\322A\212"
-          + "\002https://www.googleapis.com/auth/cloud-p"
-          + "latform,https://www.googleapis.com/auth/"
-          + "cloud-platform.read-only,https://www.goo"
-          + "gleapis.com/auth/devstorage.full_control"
-          + ",https://www.googleapis.com/auth/devstor"
-          + "age.read_only,https://www.googleapis.com"
-          + "/auth/devstorage.read_writeB\334\001\n\025com.goog"
-          + "le.storage.v2B\014StorageProtoP\001Z8google.go"
-          + "lang.org/genproto/googleapis/storage/v2;"
-          + "storage\352Ax\n!cloudkms.googleapis.com/Cryp"
-          + "toKey\022Sprojects/{project}/locations/{loc"
-          + "ation}/keyRings/{key_ring}/cryptoKeys/{c"
-          + "rypto_key}b\006proto3"
+          + "\027\332A\024hmac_key,update_mask\032\247\002\312A\026storage.go"
+          + "ogleapis.com\322A\212\002https://www.googleapis.c"
+          + "om/auth/cloud-platform,https://www.googl"
+          + "eapis.com/auth/cloud-platform.read-only,"
+          + "https://www.googleapis.com/auth/devstora"
+          + "ge.full_control,https://www.googleapis.c"
+          + "om/auth/devstorage.read_only,https://www"
+          + ".googleapis.com/auth/devstorage.read_wri"
+          + "teB\334\001\n\025com.google.storage.v2B\014StoragePro"
+          + "toP\001Z8google.golang.org/genproto/googlea"
+          + "pis/storage/v2;storage\352Ax\n!cloudkms.goog"
+          + "leapis.com/CryptoKey\022Sprojects/{project}"
+          + "/locations/{location}/keyRings/{key_ring"
+          + "}/cryptoKeys/{crypto_key}b\006proto3"
     };
     descriptor =
         com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(
@@ -1280,6 +1289,7 @@ public final class StorageProto {
             new java.lang.String[] {
               "Name",
               "BucketId",
+              "Etag",
               "Project",
               "Metageneration",
               "Location",
@@ -1303,6 +1313,7 @@ public final class StorageProto {
               "RetentionPolicy",
               "IamConfig",
               "SatisfiesPzs",
+              "CustomPlacementConfig",
               "Autoclass",
             });
     internal_static_google_storage_v2_Bucket_Billing_descriptor =
@@ -1424,8 +1435,16 @@ public final class StorageProto {
             new java.lang.String[] {
               "MainPageSuffix", "NotFoundPage",
             });
-    internal_static_google_storage_v2_Bucket_Autoclass_descriptor =
+    internal_static_google_storage_v2_Bucket_CustomPlacementConfig_descriptor =
         internal_static_google_storage_v2_Bucket_descriptor.getNestedTypes().get(9);
+    internal_static_google_storage_v2_Bucket_CustomPlacementConfig_fieldAccessorTable =
+        new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+            internal_static_google_storage_v2_Bucket_CustomPlacementConfig_descriptor,
+            new java.lang.String[] {
+              "DataLocations",
+            });
+    internal_static_google_storage_v2_Bucket_Autoclass_descriptor =
+        internal_static_google_storage_v2_Bucket_descriptor.getNestedTypes().get(10);
     internal_static_google_storage_v2_Bucket_Autoclass_fieldAccessorTable =
         new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
             internal_static_google_storage_v2_Bucket_Autoclass_descriptor,
@@ -1433,7 +1452,7 @@ public final class StorageProto {
               "Enabled", "ToggleTime",
             });
     internal_static_google_storage_v2_Bucket_LabelsEntry_descriptor =
-        internal_static_google_storage_v2_Bucket_descriptor.getNestedTypes().get(10);
+        internal_static_google_storage_v2_Bucket_descriptor.getNestedTypes().get(11);
     internal_static_google_storage_v2_Bucket_LabelsEntry_fieldAccessorTable =
         new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
             internal_static_google_storage_v2_Bucket_LabelsEntry_descriptor,
@@ -1446,7 +1465,7 @@ public final class StorageProto {
         new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
             internal_static_google_storage_v2_BucketAccessControl_descriptor,
             new java.lang.String[] {
-              "Role", "Id", "Entity", "EntityId", "Email", "Domain", "ProjectTeam",
+              "Role", "Id", "Entity", "EntityId", "Etag", "Email", "Domain", "ProjectTeam",
             });
     internal_static_google_storage_v2_ChecksummedData_descriptor =
         getDescriptor().getMessageTypes().get(40);
@@ -1477,6 +1496,7 @@ public final class StorageProto {
               "State",
               "CreateTime",
               "UpdateTime",
+              "Etag",
             });
     internal_static_google_storage_v2_Notification_descriptor =
         getDescriptor().getMessageTypes().get(43);
@@ -1486,6 +1506,7 @@ public final class StorageProto {
             new java.lang.String[] {
               "Name",
               "Topic",
+              "Etag",
               "EventTypes",
               "CustomAttributes",
               "ObjectNamePrefix",
@@ -1514,6 +1535,7 @@ public final class StorageProto {
             new java.lang.String[] {
               "Name",
               "Bucket",
+              "Etag",
               "Generation",
               "Metageneration",
               "StorageClass",
@@ -1554,7 +1576,7 @@ public final class StorageProto {
         new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
             internal_static_google_storage_v2_ObjectAccessControl_descriptor,
             new java.lang.String[] {
-              "Role", "Id", "Entity", "EntityId", "Email", "Domain", "ProjectTeam",
+              "Role", "Id", "Entity", "EntityId", "Etag", "Email", "Domain", "ProjectTeam",
             });
     internal_static_google_storage_v2_ListObjectsResponse_descriptor =
         getDescriptor().getMessageTypes().get(47);
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/UpdateObjectRequest.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/UpdateObjectRequest.java
index 379c7f2c..2c9b05ce 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/UpdateObjectRequest.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/UpdateObjectRequest.java
@@ -194,7 +194,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
    * The object's bucket and name fields are used to identify the object to
    * update. If present, the object's generation field selects a specific
    * revision of this object whose metadata should be updated. Otherwise,
-   * assumes the current, live version of the object.
+   * assumes the live version of the object.
    * </pre>
    *
    * <code>.google.storage.v2.Object object = 1;</code>
@@ -213,7 +213,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
    * The object's bucket and name fields are used to identify the object to
    * update. If present, the object's generation field selects a specific
    * revision of this object whose metadata should be updated. Otherwise,
-   * assumes the current, live version of the object.
+   * assumes the live version of the object.
    * </pre>
    *
    * <code>.google.storage.v2.Object object = 1;</code>
@@ -232,7 +232,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
    * The object's bucket and name fields are used to identify the object to
    * update. If present, the object's generation field selects a specific
    * revision of this object whose metadata should be updated. Otherwise,
-   * assumes the current, live version of the object.
+   * assumes the live version of the object.
    * </pre>
    *
    * <code>.google.storage.v2.Object object = 1;</code>
@@ -285,7 +285,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -303,7 +303,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -1071,7 +1071,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      * The object's bucket and name fields are used to identify the object to
      * update. If present, the object's generation field selects a specific
      * revision of this object whose metadata should be updated. Otherwise,
-     * assumes the current, live version of the object.
+     * assumes the live version of the object.
      * </pre>
      *
      * <code>.google.storage.v2.Object object = 1;</code>
@@ -1089,7 +1089,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      * The object's bucket and name fields are used to identify the object to
      * update. If present, the object's generation field selects a specific
      * revision of this object whose metadata should be updated. Otherwise,
-     * assumes the current, live version of the object.
+     * assumes the live version of the object.
      * </pre>
      *
      * <code>.google.storage.v2.Object object = 1;</code>
@@ -1111,7 +1111,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      * The object's bucket and name fields are used to identify the object to
      * update. If present, the object's generation field selects a specific
      * revision of this object whose metadata should be updated. Otherwise,
-     * assumes the current, live version of the object.
+     * assumes the live version of the object.
      * </pre>
      *
      * <code>.google.storage.v2.Object object = 1;</code>
@@ -1137,7 +1137,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      * The object's bucket and name fields are used to identify the object to
      * update. If present, the object's generation field selects a specific
      * revision of this object whose metadata should be updated. Otherwise,
-     * assumes the current, live version of the object.
+     * assumes the live version of the object.
      * </pre>
      *
      * <code>.google.storage.v2.Object object = 1;</code>
@@ -1160,7 +1160,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      * The object's bucket and name fields are used to identify the object to
      * update. If present, the object's generation field selects a specific
      * revision of this object whose metadata should be updated. Otherwise,
-     * assumes the current, live version of the object.
+     * assumes the live version of the object.
      * </pre>
      *
      * <code>.google.storage.v2.Object object = 1;</code>
@@ -1188,7 +1188,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      * The object's bucket and name fields are used to identify the object to
      * update. If present, the object's generation field selects a specific
      * revision of this object whose metadata should be updated. Otherwise,
-     * assumes the current, live version of the object.
+     * assumes the live version of the object.
      * </pre>
      *
      * <code>.google.storage.v2.Object object = 1;</code>
@@ -1212,7 +1212,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      * The object's bucket and name fields are used to identify the object to
      * update. If present, the object's generation field selects a specific
      * revision of this object whose metadata should be updated. Otherwise,
-     * assumes the current, live version of the object.
+     * assumes the live version of the object.
      * </pre>
      *
      * <code>.google.storage.v2.Object object = 1;</code>
@@ -1230,7 +1230,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      * The object's bucket and name fields are used to identify the object to
      * update. If present, the object's generation field selects a specific
      * revision of this object whose metadata should be updated. Otherwise,
-     * assumes the current, live version of the object.
+     * assumes the live version of the object.
      * </pre>
      *
      * <code>.google.storage.v2.Object object = 1;</code>
@@ -1250,7 +1250,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      * The object's bucket and name fields are used to identify the object to
      * update. If present, the object's generation field selects a specific
      * revision of this object whose metadata should be updated. Otherwise,
-     * assumes the current, live version of the object.
+     * assumes the live version of the object.
      * </pre>
      *
      * <code>.google.storage.v2.Object object = 1;</code>
@@ -1352,7 +1352,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -1370,7 +1370,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -1388,7 +1388,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
@@ -1409,7 +1409,7 @@ public final class UpdateObjectRequest extends com.google.protobuf.GeneratedMess
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current generation
+     * Makes the operation conditional on whether the object's live generation
      * does not match the given value. If no live object exists, the precondition
      * fails. Setting to 0 makes the operation succeed only if there is a live
      * version of the object.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/UpdateObjectRequestOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/UpdateObjectRequestOrBuilder.java
index b3ddf395..2c599632 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/UpdateObjectRequestOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/UpdateObjectRequestOrBuilder.java
@@ -31,7 +31,7 @@ public interface UpdateObjectRequestOrBuilder
    * The object's bucket and name fields are used to identify the object to
    * update. If present, the object's generation field selects a specific
    * revision of this object whose metadata should be updated. Otherwise,
-   * assumes the current, live version of the object.
+   * assumes the live version of the object.
    * </pre>
    *
    * <code>.google.storage.v2.Object object = 1;</code>
@@ -47,7 +47,7 @@ public interface UpdateObjectRequestOrBuilder
    * The object's bucket and name fields are used to identify the object to
    * update. If present, the object's generation field selects a specific
    * revision of this object whose metadata should be updated. Otherwise,
-   * assumes the current, live version of the object.
+   * assumes the live version of the object.
    * </pre>
    *
    * <code>.google.storage.v2.Object object = 1;</code>
@@ -63,7 +63,7 @@ public interface UpdateObjectRequestOrBuilder
    * The object's bucket and name fields are used to identify the object to
    * update. If present, the object's generation field selects a specific
    * revision of this object whose metadata should be updated. Otherwise,
-   * assumes the current, live version of the object.
+   * assumes the live version of the object.
    * </pre>
    *
    * <code>.google.storage.v2.Object object = 1;</code>
@@ -103,7 +103,7 @@ public interface UpdateObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
@@ -118,7 +118,7 @@ public interface UpdateObjectRequestOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current generation
+   * Makes the operation conditional on whether the object's live generation
    * does not match the given value. If no live object exists, the precondition
    * fails. Setting to 0 makes the operation succeed only if there is a live
    * version of the object.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/WriteObjectSpec.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/WriteObjectSpec.java
index 39dcad33..0081affc 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/WriteObjectSpec.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/WriteObjectSpec.java
@@ -296,7 +296,7 @@ public final class WriteObjectSpec extends com.google.protobuf.GeneratedMessageV
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current
+   * Makes the operation conditional on whether the object's live
    * generation does not match the given value. If no live object exists, the
    * precondition fails. Setting to 0 makes the operation succeed only if
    * there is a live version of the object.
@@ -314,7 +314,7 @@ public final class WriteObjectSpec extends com.google.protobuf.GeneratedMessageV
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current
+   * Makes the operation conditional on whether the object's live
    * generation does not match the given value. If no live object exists, the
    * precondition fails. Setting to 0 makes the operation succeed only if
    * there is a live version of the object.
@@ -1213,7 +1213,7 @@ public final class WriteObjectSpec extends com.google.protobuf.GeneratedMessageV
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current
+     * Makes the operation conditional on whether the object's live
      * generation does not match the given value. If no live object exists, the
      * precondition fails. Setting to 0 makes the operation succeed only if
      * there is a live version of the object.
@@ -1231,7 +1231,7 @@ public final class WriteObjectSpec extends com.google.protobuf.GeneratedMessageV
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current
+     * Makes the operation conditional on whether the object's live
      * generation does not match the given value. If no live object exists, the
      * precondition fails. Setting to 0 makes the operation succeed only if
      * there is a live version of the object.
@@ -1249,7 +1249,7 @@ public final class WriteObjectSpec extends com.google.protobuf.GeneratedMessageV
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current
+     * Makes the operation conditional on whether the object's live
      * generation does not match the given value. If no live object exists, the
      * precondition fails. Setting to 0 makes the operation succeed only if
      * there is a live version of the object.
@@ -1270,7 +1270,7 @@ public final class WriteObjectSpec extends com.google.protobuf.GeneratedMessageV
      *
      *
      * <pre>
-     * Makes the operation conditional on whether the object's current
+     * Makes the operation conditional on whether the object's live
      * generation does not match the given value. If no live object exists, the
      * precondition fails. Setting to 0 makes the operation succeed only if
      * there is a live version of the object.
diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/WriteObjectSpecOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/WriteObjectSpecOrBuilder.java
index 9683cca9..1b455397 100644
--- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/WriteObjectSpecOrBuilder.java
+++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/WriteObjectSpecOrBuilder.java
@@ -120,7 +120,7 @@ public interface WriteObjectSpecOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current
+   * Makes the operation conditional on whether the object's live
    * generation does not match the given value. If no live object exists, the
    * precondition fails. Setting to 0 makes the operation succeed only if
    * there is a live version of the object.
@@ -135,7 +135,7 @@ public interface WriteObjectSpecOrBuilder
    *
    *
    * <pre>
-   * Makes the operation conditional on whether the object's current
+   * Makes the operation conditional on whether the object's live
    * generation does not match the given value. If no live object exists, the
    * precondition fails. Setting to 0 makes the operation succeed only if
    * there is a live version of the object.
diff --git a/proto-google-cloud-storage-v2/src/main/proto/google/storage/v2/storage.proto b/proto-google-cloud-storage-v2/src/main/proto/google/storage/v2/storage.proto
index 00131376..4b0fb49a 100644
--- a/proto-google-cloud-storage-v2/src/main/proto/google/storage/v2/storage.proto
+++ b/proto-google-cloud-storage-v2/src/main/proto/google/storage/v2/storage.proto
@@ -175,13 +175,37 @@ service Storage {
   // true, or else it is an error.
   //
   // For a resumable write, the client should instead call
-  // `StartResumableWrite()` and provide that method an `WriteObjectSpec.`
+  // `StartResumableWrite()`, populating a `WriteObjectSpec` into that request.
   // They should then attach the returned `upload_id` to the first message of
-  // each following call to `Create`. If there is an error or the connection is
-  // broken during the resumable `Create()`, the client should check the status
-  // of the `Create()` by calling `QueryWriteStatus()` and continue writing from
-  // the returned `persisted_size`. This may be less than the amount of data the
-  // client previously sent.
+  // each following call to `WriteObject`. If the stream is closed before
+  // finishing the upload (either explicitly by the client or due to a network
+  // error or an error response from the server), the client should do as
+  // follows:
+  //   - Check the result Status of the stream, to determine if writing can be
+  //     resumed on this stream or must be restarted from scratch (by calling
+  //     `StartResumableWrite()`). The resumable errors are DEADLINE_EXCEEDED,
+  //     INTERNAL, and UNAVAILABLE. For each case, the client should use binary
+  //     exponential backoff before retrying.  Additionally, writes can be
+  //     resumed after RESOURCE_EXHAUSTED errors, but only after taking
+  //     appropriate measures, which may include reducing aggregate send rate
+  //     across clients and/or requesting a quota increase for your project.
+  //   - If the call to `WriteObject` returns `ABORTED`, that indicates
+  //     concurrent attempts to update the resumable write, caused either by
+  //     multiple racing clients or by a single client where the previous
+  //     request was timed out on the client side but nonetheless reached the
+  //     server. In this case the client should take steps to prevent further
+  //     concurrent writes (e.g., increase the timeouts, stop using more than
+  //     one process to perform the upload, etc.), and then should follow the
+  //     steps below for resuming the upload.
+  //   - For resumable errors, the client should call `QueryWriteStatus()` and
+  //     then continue writing from the returned `persisted_size`. This may be
+  //     less than the amount of data the client previously sent. Note also that
+  //     it is acceptable to send data starting at an offset earlier than the
+  //     returned `persisted_size`; in this case, the service will skip data at
+  //     offsets that were already persisted (without checking that it matches
+  //     the previously written data), and write only the data starting from the
+  //     persisted offset. This behavior can make client-side handling simpler
+  //     in some cases.
   //
   // The service will not view the object as complete until the client has
   // sent a `WriteObjectRequest` with `finish_write` set to `true`. Sending any
@@ -189,6 +213,10 @@ service Storage {
   // `true` will cause an error. The client **should** check the response it
   // receives to determine how much data the service was able to commit and
   // whether the service views the object as complete.
+  //
+  // Attempting to resume an already finalized object will result in an OK
+  // status, with a WriteObjectResponse containing the finalized object's
+  // metadata.
   rpc WriteObject(stream WriteObjectRequest) returns (WriteObjectResponse) {
   }
 
@@ -472,7 +500,8 @@ message ListNotificationsRequest {
 
   // The maximum number of notifications to return. The service may return fewer
   // than this value.
-  // The maximum value is 100; values above 100 will be coerced to 100.
+  // The default value is 100. Specifying a value above 100 will result in a
+  // page_size of 100.
   int32 page_size = 2;
 
   // A page token, received from a previous `ListNotifications` call.
@@ -571,7 +600,7 @@ message DeleteObjectRequest {
   // there are no live versions of the object.
   optional int64 if_generation_match = 5;
 
-  // Makes the operation conditional on whether the object's current generation
+  // Makes the operation conditional on whether the object's live generation
   // does not match the given value. If no live object exists, the precondition
   // fails. Setting to 0 makes the operation succeed only if there is a live
   // version of the object.
@@ -608,8 +637,8 @@ message ReadObjectRequest {
   // back from the end of the object to be returned. For example, if an object's
   // length is 15 bytes, a ReadObjectRequest with `read_offset` = -5 and
   // `read_limit` = 3 would return bytes 10 through 12 of the object. Requesting
-  // a negative offset whose magnitude is larger than the size of the object
-  // will result in an error.
+  // a negative offset with magnitude larger than the size of the object will
+  // return the entire object.
   int64 read_offset = 4;
 
   // The maximum number of `data` bytes the server is allowed to return in the
@@ -626,7 +655,7 @@ message ReadObjectRequest {
   // there are no live versions of the object.
   optional int64 if_generation_match = 6;
 
-  // Makes the operation conditional on whether the object's current generation
+  // Makes the operation conditional on whether the object's live generation
   // does not match the given value. If no live object exists, the precondition
   // fails. Setting to 0 makes the operation succeed only if there is a live
   // version of the object.
@@ -668,7 +697,7 @@ message GetObjectRequest {
   // there are no live versions of the object.
   optional int64 if_generation_match = 4;
 
-  // Makes the operation conditional on whether the object's current generation
+  // Makes the operation conditional on whether the object's live generation
   // does not match the given value. If no live object exists, the precondition
   // fails. Setting to 0 makes the operation succeed only if there is a live
   // version of the object.
@@ -730,7 +759,7 @@ message WriteObjectSpec {
   // succeed only if there are no live versions of the object.
   optional int64 if_generation_match = 3;
 
-  // Makes the operation conditional on whether the object's current
+  // Makes the operation conditional on whether the object's live
   // generation does not match the given value. If no live object exists, the
   // precondition fails. Setting to 0 makes the operation succeed only if
   // there is a live version of the object.
@@ -970,7 +999,7 @@ message RewriteObjectRequest {
   // there are no live versions of the object.
   optional int64 if_generation_match = 7;
 
-  // Makes the operation conditional on whether the object's current generation
+  // Makes the operation conditional on whether the object's live generation
   // does not match the given value. If no live object exists, the precondition
   // fails. Setting to 0 makes the operation succeed only if there is a live
   // version of the object.
@@ -984,11 +1013,11 @@ message RewriteObjectRequest {
   // metageneration does not match the given value.
   optional int64 if_metageneration_not_match = 10;
 
-  // Makes the operation conditional on whether the source object's current
+  // Makes the operation conditional on whether the source object's live
   // generation matches the given value.
   optional int64 if_source_generation_match = 11;
 
-  // Makes the operation conditional on whether the source object's current
+  // Makes the operation conditional on whether the source object's live
   // generation does not match the given value.
   optional int64 if_source_generation_not_match = 12;
 
@@ -1073,7 +1102,7 @@ message UpdateObjectRequest {
   // The object's bucket and name fields are used to identify the object to
   // update. If present, the object's generation field selects a specific
   // revision of this object whose metadata should be updated. Otherwise,
-  // assumes the current, live version of the object.
+  // assumes the live version of the object.
   Object object = 1;
 
   // Makes the operation conditional on whether the object's current generation
@@ -1081,7 +1110,7 @@ message UpdateObjectRequest {
   // there are no live versions of the object.
   optional int64 if_generation_match = 2;
 
-  // Makes the operation conditional on whether the object's current generation
+  // Makes the operation conditional on whether the object's live generation
   // does not match the given value. If no live object exists, the precondition
   // fails. Setting to 0 makes the operation succeed only if there is a live
   // version of the object.
@@ -1483,7 +1512,8 @@ message Bucket {
 
   // Logging-related properties of a bucket.
   message Logging {
-    // The destination bucket where the current bucket's logs should be placed.
+    // The destination bucket where the current bucket's logs should be placed,
+    // using path format (like `projects/123456/buckets/foo`).
     string log_bucket = 1;
 
     // A prefix for log object names.
@@ -1532,6 +1562,14 @@ message Bucket {
     string not_found_page = 2;
   }
 
+  // Configuration for Custom Dual Regions.  It should specify precisely two
+  // eligible regions within the same Multiregion. More information on regions
+  // may be found [https://cloud.google.com/storage/docs/locations][here].
+  message CustomPlacementConfig {
+    // List of locations to use for data placement.
+    repeated string data_locations = 1;
+  }
+
   // Configuration for a bucket's Autoclass feature.
   message Autoclass {
     // Enables Autoclass.
@@ -1552,6 +1590,11 @@ message Bucket {
   // name" of other Cloud Storage APIs. Example: "pub".
   string bucket_id = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
 
+  // The etag of the bucket.
+  // If included in the metadata of an UpdateBucketRequest, the operation will
+  // only be performed if the etag matches that of the bucket.
+  string etag = 29;
+
   // Immutable. The project which owns this bucket.
   string project = 3 [
     (google.api.field_behavior) = IMMUTABLE,
@@ -1677,6 +1720,10 @@ message Bucket {
   // Reserved for future use.
   bool satisfies_pzs = 25;
 
+  // Configuration that, if present, specifies the data placement for a Custom
+  // Dual Region.
+  CustomPlacementConfig custom_placement_config = 26;
+
   // The bucket's Autoclass configuration. If there is no configuration, the
   // Autoclass feature will be disabled and have no effect on the bucket.
   Autoclass autoclass = 28;
@@ -1710,6 +1757,12 @@ message BucketAccessControl {
   // The ID for the entity, if any.
   string entity_id = 4;
 
+  // The etag of the BucketAccessControl.
+  // If included in the metadata of an update or delete request message, the
+  // operation operation will only be performed if the etag matches that of the
+  // bucket's BucketAccessControl.
+  string etag = 8;
+
   // The email address associated with the entity, if any.
   string email = 5;
 
@@ -1772,6 +1825,9 @@ message HmacKeyMetadata {
 
   // The last modification time of the HMAC key metadata.
   google.protobuf.Timestamp update_time = 7;
+
+  // The etag of the HMAC key.
+  string etag = 8;
 }
 
 // A directive to publish Pub/Sub notifications upon changes to a bucket.
@@ -1791,6 +1847,11 @@ message Notification {
   // '//pubsub.googleapis.com/projects/{project-identifier}/topics/{my-topic}'
   string topic = 2 [(google.api.field_behavior) = REQUIRED];
 
+  // The etag of the Notification.
+  // If included in the metadata of GetNotificationRequest, the operation will
+  // only be performed if the etag matches that of the Notification.
+  string etag = 7;
+
   // Optional. If present, only send notifications about listed event types. If empty,
   // sent notifications for all event types.
   repeated string event_types = 3 [(google.api.field_behavior) = OPTIONAL];
@@ -1837,6 +1898,12 @@ message Object {
     }
   ];
 
+  // The etag of the object.
+  // If included in the metadata of an update or delete request message, the
+  // operation will only be performed if the etag matches that of the live
+  // object.
+  string etag = 27;
+
   // Immutable. The content generation of this object. Used for object versioning.
   // Attempting to set or update this field will result in a
   // [FieldViolation][google.rpc.BadRequest.FieldViolation].
@@ -1998,6 +2065,12 @@ message ObjectAccessControl {
   // The ID for the entity, if any.
   string entity_id = 4;
 
+  // The etag of the ObjectAccessControl.
+  // If included in the metadata of an update or delete request message, the
+  // operation will only be performed if the etag matches that of the live
+  // object's ObjectAccessControl.
+  string etag = 8;
+
   // The email address associated with the entity, if any.
   string email = 5;
 


Test patch:
diff --git a/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java b/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java
index 906f8827..5d8bd415 100644
--- a/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java
+++ b/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java
@@ -175,6 +175,7 @@ public class StorageClientTest {
         Bucket.newBuilder()
             .setName(BucketName.of("[PROJECT]", "[BUCKET]").toString())
             .setBucketId("bucketId-1603305307")
+            .setEtag("etag3123477")
             .setProject(ProjectName.of("[PROJECT]").toString())
             .setMetageneration(1048558813)
             .setLocation("location1901043637")
@@ -198,6 +199,7 @@ public class StorageClientTest {
             .setRetentionPolicy(Bucket.RetentionPolicy.newBuilder().build())
             .setIamConfig(Bucket.IamConfig.newBuilder().build())
             .setSatisfiesPzs(true)
+            .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build())
             .setAutoclass(Bucket.Autoclass.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
@@ -238,6 +240,7 @@ public class StorageClientTest {
         Bucket.newBuilder()
             .setName(BucketName.of("[PROJECT]", "[BUCKET]").toString())
             .setBucketId("bucketId-1603305307")
+            .setEtag("etag3123477")
             .setProject(ProjectName.of("[PROJECT]").toString())
             .setMetageneration(1048558813)
             .setLocation("location1901043637")
@@ -261,6 +264,7 @@ public class StorageClientTest {
             .setRetentionPolicy(Bucket.RetentionPolicy.newBuilder().build())
             .setIamConfig(Bucket.IamConfig.newBuilder().build())
             .setSatisfiesPzs(true)
+            .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build())
             .setAutoclass(Bucket.Autoclass.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
@@ -301,6 +305,7 @@ public class StorageClientTest {
         Bucket.newBuilder()
             .setName(BucketName.of("[PROJECT]", "[BUCKET]").toString())
             .setBucketId("bucketId-1603305307")
+            .setEtag("etag3123477")
             .setProject(ProjectName.of("[PROJECT]").toString())
             .setMetageneration(1048558813)
             .setLocation("location1901043637")
@@ -324,6 +329,7 @@ public class StorageClientTest {
             .setRetentionPolicy(Bucket.RetentionPolicy.newBuilder().build())
             .setIamConfig(Bucket.IamConfig.newBuilder().build())
             .setSatisfiesPzs(true)
+            .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build())
             .setAutoclass(Bucket.Autoclass.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
@@ -370,6 +376,7 @@ public class StorageClientTest {
         Bucket.newBuilder()
             .setName(BucketName.of("[PROJECT]", "[BUCKET]").toString())
             .setBucketId("bucketId-1603305307")
+            .setEtag("etag3123477")
             .setProject(ProjectName.of("[PROJECT]").toString())
             .setMetageneration(1048558813)
             .setLocation("location1901043637")
@@ -393,6 +400,7 @@ public class StorageClientTest {
             .setRetentionPolicy(Bucket.RetentionPolicy.newBuilder().build())
             .setIamConfig(Bucket.IamConfig.newBuilder().build())
             .setSatisfiesPzs(true)
+            .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build())
             .setAutoclass(Bucket.Autoclass.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
@@ -527,6 +535,7 @@ public class StorageClientTest {
         Bucket.newBuilder()
             .setName(BucketName.of("[PROJECT]", "[BUCKET]").toString())
             .setBucketId("bucketId-1603305307")
+            .setEtag("etag3123477")
             .setProject(ProjectName.of("[PROJECT]").toString())
             .setMetageneration(1048558813)
             .setLocation("location1901043637")
@@ -550,6 +559,7 @@ public class StorageClientTest {
             .setRetentionPolicy(Bucket.RetentionPolicy.newBuilder().build())
             .setIamConfig(Bucket.IamConfig.newBuilder().build())
             .setSatisfiesPzs(true)
+            .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build())
             .setAutoclass(Bucket.Autoclass.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
@@ -591,6 +601,7 @@ public class StorageClientTest {
         Bucket.newBuilder()
             .setName(BucketName.of("[PROJECT]", "[BUCKET]").toString())
             .setBucketId("bucketId-1603305307")
+            .setEtag("etag3123477")
             .setProject(ProjectName.of("[PROJECT]").toString())
             .setMetageneration(1048558813)
             .setLocation("location1901043637")
@@ -614,6 +625,7 @@ public class StorageClientTest {
             .setRetentionPolicy(Bucket.RetentionPolicy.newBuilder().build())
             .setIamConfig(Bucket.IamConfig.newBuilder().build())
             .setSatisfiesPzs(true)
+            .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build())
             .setAutoclass(Bucket.Autoclass.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
@@ -909,6 +921,7 @@ public class StorageClientTest {
         Bucket.newBuilder()
             .setName(BucketName.of("[PROJECT]", "[BUCKET]").toString())
             .setBucketId("bucketId-1603305307")
+            .setEtag("etag3123477")
             .setProject(ProjectName.of("[PROJECT]").toString())
             .setMetageneration(1048558813)
             .setLocation("location1901043637")
@@ -932,6 +945,7 @@ public class StorageClientTest {
             .setRetentionPolicy(Bucket.RetentionPolicy.newBuilder().build())
             .setIamConfig(Bucket.IamConfig.newBuilder().build())
             .setSatisfiesPzs(true)
+            .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build())
             .setAutoclass(Bucket.Autoclass.newBuilder().build())
             .build();
     mockStorage.addResponse(expectedResponse);
@@ -1043,6 +1057,7 @@ public class StorageClientTest {
         Notification.newBuilder()
             .setName(NotificationName.of("[PROJECT]", "[BUCKET]", "[NOTIFICATION]").toString())
             .setTopic("topic110546223")
+            .setEtag("etag3123477")
             .addAllEventTypes(new ArrayList<String>())
             .putAllCustomAttributes(new HashMap<String, String>())
             .setObjectNamePrefix("objectNamePrefix-1978236516")
@@ -1086,6 +1101,7 @@ public class StorageClientTest {
         Notification.newBuilder()
             .setName(NotificationName.of("[PROJECT]", "[BUCKET]", "[NOTIFICATION]").toString())
             .setTopic("topic110546223")
+            .setEtag("etag3123477")
             .addAllEventTypes(new ArrayList<String>())
             .putAllCustomAttributes(new HashMap<String, String>())
             .setObjectNamePrefix("objectNamePrefix-1978236516")
@@ -1129,6 +1145,7 @@ public class StorageClientTest {
         Notification.newBuilder()
             .setName(NotificationName.of("[PROJECT]", "[BUCKET]", "[NOTIFICATION]").toString())
             .setTopic("topic110546223")
+            .setEtag("etag3123477")
             .addAllEventTypes(new ArrayList<String>())
             .putAllCustomAttributes(new HashMap<String, String>())
             .setObjectNamePrefix("objectNamePrefix-1978236516")
@@ -1175,6 +1192,7 @@ public class StorageClientTest {
         Notification.newBuilder()
             .setName(NotificationName.of("[PROJECT]", "[BUCKET]", "[NOTIFICATION]").toString())
             .setTopic("topic110546223")
+            .setEtag("etag3123477")
             .addAllEventTypes(new ArrayList<String>())
             .putAllCustomAttributes(new HashMap<String, String>())
             .setObjectNamePrefix("objectNamePrefix-1978236516")
@@ -1309,6 +1327,7 @@ public class StorageClientTest {
         Object.newBuilder()
             .setName("name3373707")
             .setBucket(BucketName.of("[PROJECT]", "[BUCKET]").toString())
+            .setEtag("etag3123477")
             .setGeneration(305703192)
             .setMetageneration(1048558813)
             .setStorageClass("storageClass871353277")
@@ -1482,6 +1501,7 @@ public class StorageClientTest {
         Object.newBuilder()
             .setName("name3373707")
             .setBucket(BucketName.of("[PROJECT]", "[BUCKET]").toString())
+            .setEtag("etag3123477")
             .setGeneration(305703192)
             .setMetageneration(1048558813)
             .setStorageClass("storageClass871353277")
@@ -1550,6 +1570,7 @@ public class StorageClientTest {
         Object.newBuilder()
             .setName("name3373707")
             .setBucket(BucketName.of("[PROJECT]", "[BUCKET]").toString())
+            .setEtag("etag3123477")
             .setGeneration(305703192)
             .setMetageneration(1048558813)
             .setStorageClass("storageClass871353277")
@@ -1692,6 +1713,7 @@ public class StorageClientTest {
         Object.newBuilder()
             .setName("name3373707")
             .setBucket(BucketName.of("[PROJECT]", "[BUCKET]").toString())
+            .setEtag("etag3123477")
             .setGeneration(305703192)
             .setMetageneration(1048558813)
             .setStorageClass("storageClass871353277")
@@ -2352,6 +2374,7 @@ public class StorageClientTest {
             .setState("state109757585")
             .setCreateTime(Timestamp.newBuilder().build())
             .setUpdateTime(Timestamp.newBuilder().build())
+            .setEtag("etag3123477")
             .build();
     mockStorage.addResponse(expectedResponse);
 
@@ -2399,6 +2422,7 @@ public class StorageClientTest {
             .setState("state109757585")
             .setCreateTime(Timestamp.newBuilder().build())
             .setUpdateTime(Timestamp.newBuilder().build())
+            .setEtag("etag3123477")
             .build();
     mockStorage.addResponse(expectedResponse);
 
@@ -2534,6 +2558,7 @@ public class StorageClientTest {
             .setState("state109757585")
             .setCreateTime(Timestamp.newBuilder().build())
             .setUpdateTime(Timestamp.newBuilder().build())
+            .setEtag("etag3123477")
             .build();
     mockStorage.addResponse(expectedResponse);