You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by sa...@apache.org on 2020/09/04 08:31:39 UTC

[hadoop-ozone] branch master updated: HDDS-3725. Ozone sh volume client support quota option. (#1233)

This is an automated email from the ASF dual-hosted git repository.

sammichen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hadoop-ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new f254183  HDDS-3725. Ozone sh volume client support quota option. (#1233)
f254183 is described below

commit f25418329cfc5d7194c632b72a9617f5bb7a4bb6
Author: micah zhao <mi...@tencent.com>
AuthorDate: Fri Sep 4 16:31:26 2020 +0800

    HDDS-3725. Ozone sh volume client support quota option. (#1233)
---
 .../org/apache/hadoop/hdds/client/OzoneQuota.java  | 240 +++++++++++++--------
 .../java/org/apache/hadoop/ozone/OzoneConsts.java  |  11 +
 .../apache/hadoop/hdds/server/TestJsonUtils.java   |   5 +-
 .../apache/hadoop/ozone/client/OzoneVolume.java    |  60 ++++--
 .../org/apache/hadoop/ozone/client/VolumeArgs.java |  45 ++--
 .../ozone/client/protocol/ClientProtocol.java      |   6 +-
 .../apache/hadoop/ozone/client/rpc/RpcClient.java  |  37 ++--
 .../hadoop/ozone/om/helpers/OmVolumeArgs.java      |  42 +++-
 .../ozone/om/protocol/OzoneManagerProtocol.java    |   6 +-
 ...OzoneManagerProtocolClientSideTranslatorPB.java |  10 +-
 .../src/main/smoketest/basic/ozone-shell-lib.robot |   6 +-
 .../dist/src/main/smoketest/createbucketenv.robot  |   2 +-
 .../dist/src/main/smoketest/createmrenv.robot      |   2 +-
 .../src/main/smoketest/debug/ozone-debug.robot     |   2 +-
 .../dist/src/main/smoketest/gdpr/gdpr.robot        |   2 +-
 .../dist/src/main/smoketest/ozonefs/setup.robot    |   8 +-
 .../src/main/smoketest/topology/loaddata.robot     |   2 +-
 .../hadoop/fs/ozone/TestRootedOzoneFileSystem.java |   7 +-
 .../client/rpc/TestOzoneRpcClientAbstract.java     |  47 +++-
 .../src/main/proto/OmClientProtocol.proto          |   2 +
 .../org/apache/hadoop/ozone/om/OzoneManager.java   |  28 +--
 .../org/apache/hadoop/ozone/om/VolumeManager.java  |   9 -
 .../apache/hadoop/ozone/om/VolumeManagerImpl.java  |  39 ----
 .../om/request/volume/OMVolumeSetQuotaRequest.java |   2 +
 .../ozone/om/request/TestOMRequestUtils.java       |   9 +-
 .../volume/TestOMVolumeSetOwnerRequest.java        |   2 +-
 .../volume/TestOMVolumeSetQuotaRequest.java        |  36 ++--
 .../hadoop/ozone/client/ObjectStoreStub.java       |   5 +-
 .../hadoop/ozone/client/OzoneVolumeStub.java       |   6 +-
 .../hadoop/ozone/freon/RandomKeyGenerator.java     |  13 +-
 .../ozone/shell/volume/CreateVolumeHandler.java    |  19 +-
 .../ozone/shell/volume/UpdateVolumeHandler.java    |  28 ++-
 32 files changed, 457 insertions(+), 281 deletions(-)

diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/OzoneQuota.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/OzoneQuota.java
index 2c9473c..b778e03 100644
--- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/OzoneQuota.java
+++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/client/OzoneQuota.java
@@ -18,33 +18,94 @@
 
 package org.apache.hadoop.hdds.client;
 
-import org.apache.hadoop.ozone.OzoneConsts;
+import com.google.common.base.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.hadoop.ozone.OzoneConsts.GB;
+import static org.apache.hadoop.ozone.OzoneConsts.KB;
+import static org.apache.hadoop.ozone.OzoneConsts.MB;
+import static org.apache.hadoop.ozone.OzoneConsts.TB;
 
 
 /**
  * represents an OzoneQuota Object that can be applied to
  * a storage volume.
  */
-public class OzoneQuota {
+public final class OzoneQuota {
+  public static final Logger LOG =
+      LoggerFactory.getLogger(OzoneQuota.class);
 
   public static final String OZONE_QUOTA_BYTES = "BYTES";
+  public static final String OZONE_QUOTA_KB = "KB";
   public static final String OZONE_QUOTA_MB = "MB";
   public static final String OZONE_QUOTA_GB = "GB";
   public static final String OZONE_QUOTA_TB = "TB";
 
-  private Units unit;
-  private long size;
-
   /** Quota Units.*/
   public enum Units {UNDEFINED, BYTES, KB, MB, GB, TB}
 
+  // Quota to decide how many buckets can be created.
+  private long quotaInCounts;
+  // Quota to decide how many storage space will be used in bytes.
+  private long quotaInBytes;
+  private RawQuotaInBytes rawQuotaInBytes;
+
+  /**
+   * Used to convert user input values into bytes such as: 1MB-> 1048576.
+   */
+  private static class RawQuotaInBytes {
+    private Units unit;
+    private long size;
+
+    RawQuotaInBytes(Units unit, long size) {
+      this.unit = unit;
+      this.size = size;
+    }
+
+    public Units getUnit() {
+      return unit;
+    }
+
+    public long getSize() {
+      return size;
+    }
+
+    /**
+     * Returns size in Bytes or -1 if there is no Quota.
+     */
+    public long sizeInBytes() {
+      switch (this.unit) {
+      case BYTES:
+        return this.getSize();
+      case KB:
+        return this.getSize() * KB;
+      case MB:
+        return this.getSize() * MB;
+      case GB:
+        return this.getSize() * GB;
+      case TB:
+        return this.getSize() * TB;
+      case UNDEFINED:
+      default:
+        return -1;
+      }
+    }
+
+    @Override
+    public String toString() {
+      return size + " " + unit;
+    }
+
+  }
+
   /**
    * Returns size.
    *
    * @return long
    */
-  public long getSize() {
-    return size;
+  public long getRawSize() {
+    return this.rawQuotaInBytes.getSize();
   }
 
   /**
@@ -53,26 +114,19 @@ public class OzoneQuota {
    * @return Unit in MB, GB or TB
    */
   public Units getUnit() {
-    return unit;
-  }
-
-  /**
-   * Constructs a default Quota object.
-   */
-  public OzoneQuota() {
-    this.size = 0;
-    this.unit = Units.UNDEFINED;
+    return this.rawQuotaInBytes.getUnit();
   }
 
   /**
    * Constructor for Ozone Quota.
    *
-   * @param size Long Size
-   * @param unit MB, GB  or TB
+   * @param quotaInCounts Volume quota in counts
+   * @param rawQuotaInBytes RawQuotaInBytes value
    */
-  public OzoneQuota(long size, Units unit) {
-    this.size = size;
-    this.unit = unit;
+  private OzoneQuota(long quotaInCounts, RawQuotaInBytes rawQuotaInBytes) {
+    this.quotaInCounts = quotaInCounts;
+    this.rawQuotaInBytes = rawQuotaInBytes;
+    this.quotaInBytes = rawQuotaInBytes.sizeInBytes();
   }
 
   /**
@@ -82,118 +136,130 @@ public class OzoneQuota {
    * @return string representation of quota
    */
   public static String formatQuota(OzoneQuota quota) {
-    return String.valueOf(quota.size) + quota.unit;
+    return String.valueOf(quota.getRawSize()) + quota.getUnit();
   }
 
   /**
    * Parses a user provided string and returns the
    * Quota Object.
    *
-   * @param quotaString Quota String
+   * @param quotaInBytes Volume quota in bytes
+   * @param quotaInCounts Volume quota in counts
    *
    * @return OzoneQuota object
    */
-  public static OzoneQuota parseQuota(String quotaString) {
+  public static OzoneQuota parseQuota(String quotaInBytes,
+      long quotaInCounts) {
 
-    if ((quotaString == null) || (quotaString.isEmpty())) {
+    if (Strings.isNullOrEmpty(quotaInBytes)) {
       throw new IllegalArgumentException(
           "Quota string cannot be null or empty.");
     }
 
-    String uppercase = quotaString.toUpperCase().replaceAll("\\s+", "");
+    String uppercase = quotaInBytes.toUpperCase()
+        .replaceAll("\\s+", "");
     String size = "";
-    int nSize;
+    long nSize = 0;
     Units currUnit = Units.MB;
-    boolean found = false;
-    if (uppercase.endsWith(OZONE_QUOTA_MB)) {
-      size = uppercase
-          .substring(0, uppercase.length() - OZONE_QUOTA_MB.length());
-      currUnit = Units.MB;
-      found = true;
-    }
+    long quotaMultiplyExact = 0;
 
-    if (uppercase.endsWith(OZONE_QUOTA_GB)) {
-      size = uppercase
-          .substring(0, uppercase.length() - OZONE_QUOTA_GB.length());
-      currUnit = Units.GB;
-      found = true;
-    }
+    try {
+      if (uppercase.endsWith(OZONE_QUOTA_KB)) {
+        size = uppercase
+            .substring(0, uppercase.length() - OZONE_QUOTA_KB.length());
+        currUnit = Units.KB;
+        quotaMultiplyExact = Math.multiplyExact(Long.parseLong(size), KB);
+      }
 
-    if (uppercase.endsWith(OZONE_QUOTA_TB)) {
-      size = uppercase
-          .substring(0, uppercase.length() - OZONE_QUOTA_TB.length());
-      currUnit = Units.TB;
-      found = true;
-    }
+      if (uppercase.endsWith(OZONE_QUOTA_MB)) {
+        size = uppercase
+            .substring(0, uppercase.length() - OZONE_QUOTA_MB.length());
+        currUnit = Units.MB;
+        quotaMultiplyExact = Math.multiplyExact(Long.parseLong(size), MB);
+      }
 
-    if (uppercase.endsWith(OZONE_QUOTA_BYTES)) {
-      size = uppercase
-          .substring(0, uppercase.length() - OZONE_QUOTA_BYTES.length());
-      currUnit = Units.BYTES;
-      found = true;
-    }
+      if (uppercase.endsWith(OZONE_QUOTA_GB)) {
+        size = uppercase
+            .substring(0, uppercase.length() - OZONE_QUOTA_GB.length());
+        currUnit = Units.GB;
+        quotaMultiplyExact = Math.multiplyExact(Long.parseLong(size), GB);
+      }
+
+      if (uppercase.endsWith(OZONE_QUOTA_TB)) {
+        size = uppercase
+            .substring(0, uppercase.length() - OZONE_QUOTA_TB.length());
+        currUnit = Units.TB;
+        quotaMultiplyExact = Math.multiplyExact(Long.parseLong(size), TB);
+      }
 
-    if (!found) {
-      throw new IllegalArgumentException("Quota unit not recognized. " +
-          "Supported values are BYTES, MB, GB and TB.");
+      if (uppercase.endsWith(OZONE_QUOTA_BYTES)) {
+        size = uppercase
+            .substring(0, uppercase.length() - OZONE_QUOTA_BYTES.length());
+        currUnit = Units.BYTES;
+        quotaMultiplyExact = Math.multiplyExact(Long.parseLong(size), 1L);
+      }
+      nSize = Long.parseLong(size);
+    } catch (NumberFormatException e) {
+      throw new IllegalArgumentException("Invalid values for quota, to ensure" +
+          " that the Quota format is legal(supported values are BYTES, KB, " +
+          "MB, GB and TB).");
+    } catch  (ArithmeticException e) {
+      LOG.debug("long overflow:\n{}", quotaMultiplyExact);
+      throw new IllegalArgumentException("Invalid values for quota, the quota" +
+          " value cannot be greater than Long.MAX_VALUE BYTES");
     }
 
-    nSize = Integer.parseInt(size);
     if (nSize < 0) {
       throw new IllegalArgumentException("Quota cannot be negative.");
     }
 
-    return new OzoneQuota(nSize, currUnit);
+    return new OzoneQuota(quotaInCounts,
+        new RawQuotaInBytes(currUnit, nSize));
   }
 
 
   /**
-   * Returns size in Bytes or -1 if there is no Quota.
-   */
-  public long sizeInBytes() {
-    switch (this.unit) {
-    case BYTES:
-      return this.getSize();
-    case MB:
-      return this.getSize() * OzoneConsts.MB;
-    case GB:
-      return this.getSize() * OzoneConsts.GB;
-    case TB:
-      return this.getSize() * OzoneConsts.TB;
-    case UNDEFINED:
-    default:
-      return -1;
-    }
-  }
-
-  /**
    * Returns OzoneQuota corresponding to size in bytes.
    *
-   * @param sizeInBytes size in bytes to be converted
+   * @param quotaInBytes in bytes to be converted
+   * @param quotaInCounts in counts to be converted
    *
    * @return OzoneQuota object
    */
-  public static OzoneQuota getOzoneQuota(long sizeInBytes) {
+  public static OzoneQuota getOzoneQuota(long quotaInBytes,
+      long quotaInCounts) {
     long size;
     Units unit;
-    if (sizeInBytes % OzoneConsts.TB == 0) {
-      size = sizeInBytes / OzoneConsts.TB;
+    if (quotaInBytes % TB == 0) {
+      size = quotaInBytes / TB;
       unit = Units.TB;
-    } else if (sizeInBytes % OzoneConsts.GB == 0) {
-      size = sizeInBytes / OzoneConsts.GB;
+    } else if (quotaInBytes % GB == 0) {
+      size = quotaInBytes / GB;
       unit = Units.GB;
-    } else if (sizeInBytes % OzoneConsts.MB == 0) {
-      size = sizeInBytes / OzoneConsts.MB;
+    } else if (quotaInBytes % MB == 0) {
+      size = quotaInBytes / MB;
       unit = Units.MB;
+    } else if (quotaInBytes % KB == 0) {
+      size = quotaInBytes / KB;
+      unit = Units.KB;
     } else {
-      size = sizeInBytes;
+      size = quotaInBytes;
       unit = Units.BYTES;
     }
-    return new OzoneQuota((int)size, unit);
+    return new OzoneQuota(quotaInCounts, new RawQuotaInBytes(unit, size));
+  }
+
+  public long getQuotaInCounts() {
+    return quotaInCounts;
+  }
+
+  public long getQuotaInBytes() {
+    return quotaInBytes;
   }
 
   @Override
   public String toString() {
-    return size + " " + unit;
+    return "Space Bytes Quota: " + rawQuotaInBytes.toString() + "\n" +
+        "Counts Quota: " + quotaInCounts;
   }
 }
diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java
index 9854d40..5e6fe23 100644
--- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java
+++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java
@@ -205,6 +205,16 @@ public final class OzoneConsts {
   public static final long MAX_QUOTA_IN_BYTES = 1024L * 1024 * TB;
 
   /**
+   * Quota RESET default is -1, which means quota is not set.
+   */
+  public static final long QUOTA_RESET = -1;
+
+  /**
+   * Quota Units.
+   */
+  public enum Units {TB, GB, MB, KB, BYTES}
+
+  /**
    * Max number of keys returned per list buckets operation.
    */
   public static final int MAX_LISTBUCKETS_SIZE  = 1024;
@@ -260,6 +270,7 @@ public final class OzoneConsts {
   public static final String SRC_KEY = "srcKey";
   public static final String DST_KEY = "dstKey";
   public static final String QUOTA_IN_BYTES = "quotaInBytes";
+  public static final String QUOTA_IN_COUNTS = "quotaInCounts";
   public static final String OBJECT_ID = "objectID";
   public static final String UPDATE_ID = "updateID";
   public static final String CLIENT_ID = "clientID";
diff --git a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/TestJsonUtils.java b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/TestJsonUtils.java
index a9f82ed..b5452fb 100644
--- a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/TestJsonUtils.java
+++ b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/TestJsonUtils.java
@@ -32,12 +32,13 @@ public class TestJsonUtils {
 
   @Test
   public void printObjectAsJson() throws IOException {
-    OzoneQuota quota = new OzoneQuota(123, OzoneQuota.Units.MB);
+    OzoneQuota quota = OzoneQuota.parseQuota("123MB", 1000L);
 
     String result = JsonUtils.toJsonStringWithDefaultPrettyPrinter(quota);
 
-    assertContains(result, "\"size\" : 123");
+    assertContains(result, "\"rawSize\" : 123");
     assertContains(result, "\"unit\" : \"MB\"");
+    assertContains(result, "\"quotaInCounts\" : 1000");
   }
 
   private static void assertContains(String str, String part) {
diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneVolume.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneVolume.java
index 9978cc7..fb4677d 100644
--- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneVolume.java
+++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneVolume.java
@@ -26,8 +26,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 
-import org.apache.hadoop.hdds.conf.ConfigurationSource;
 import org.apache.hadoop.hdds.client.OzoneQuota;
+import org.apache.hadoop.hdds.conf.ConfigurationSource;
 import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
 import org.apache.hadoop.ozone.OzoneAcl;
 import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
@@ -61,10 +61,14 @@ public class OzoneVolume extends WithMetadata {
    */
   private String owner;
   /**
-   * Quota allocated for the Volume.
+   * Quota of bytes allocated for the Volume.
    */
   private long quotaInBytes;
   /**
+   * Quota of bucket count allocated for the Volume.
+   */
+  private long quotaInCounts;
+  /**
    * Creation time of the volume.
    */
   private Instant creationTime;
@@ -94,13 +98,15 @@ public class OzoneVolume extends WithMetadata {
   @SuppressWarnings("parameternumber")
   public OzoneVolume(ConfigurationSource conf, ClientProtocol proxy,
       String name, String admin, String owner, long quotaInBytes,
-      long creationTime, List<OzoneAcl> acls, Map<String, String> metadata) {
+      long quotaInCounts, long creationTime, List<OzoneAcl> acls,
+      Map<String, String> metadata) {
     Preconditions.checkNotNull(proxy, "Client proxy is not set.");
     this.proxy = proxy;
     this.name = name;
     this.admin = admin;
     this.owner = owner;
     this.quotaInBytes = quotaInBytes;
+    this.quotaInCounts = quotaInCounts;
     this.creationTime = Instant.ofEpochMilli(creationTime);
     this.acls = acls;
     this.listCacheSize = HddsClientUtils.getListCacheSize(conf);
@@ -118,9 +124,9 @@ public class OzoneVolume extends WithMetadata {
   @SuppressWarnings("parameternumber")
   public OzoneVolume(ConfigurationSource conf, ClientProtocol proxy,
       String name, String admin, String owner, long quotaInBytes,
-      long creationTime, long modificationTime, List<OzoneAcl> acls,
-      Map<String, String> metadata) {
-    this(conf, proxy, name, admin, owner, quotaInBytes,
+      long quotaInCounts, long creationTime, long modificationTime,
+      List<OzoneAcl> acls, Map<String, String> metadata) {
+    this(conf, proxy, name, admin, owner, quotaInBytes, quotaInCounts,
         creationTime, acls, metadata);
     this.modificationTime = Instant.ofEpochMilli(modificationTime);
   }
@@ -128,9 +134,9 @@ public class OzoneVolume extends WithMetadata {
   @SuppressWarnings("parameternumber")
   public OzoneVolume(ConfigurationSource conf, ClientProtocol proxy,
       String name, String admin, String owner, long quotaInBytes,
-      long creationTime, List<OzoneAcl> acls) {
-    this(conf, proxy, name, admin, owner, quotaInBytes, creationTime, acls,
-        new HashMap<>());
+      long quotaInCounts, long creationTime, List<OzoneAcl> acls) {
+    this(conf, proxy, name, admin, owner, quotaInBytes, quotaInCounts,
+        creationTime, acls, new HashMap<>());
     modificationTime = Instant.now();
     if (modificationTime.isBefore(this.creationTime)) {
       modificationTime = Instant.ofEpochSecond(
@@ -141,19 +147,23 @@ public class OzoneVolume extends WithMetadata {
   @SuppressWarnings("parameternumber")
   public OzoneVolume(ConfigurationSource conf, ClientProtocol proxy,
       String name, String admin, String owner, long quotaInBytes,
-      long creationTime, long modificationTime, List<OzoneAcl> acls) {
-    this(conf, proxy, name, admin, owner, quotaInBytes, creationTime, acls);
+      long quotaInCounts, long creationTime, long modificationTime,
+      List<OzoneAcl> acls) {
+    this(conf, proxy, name, admin, owner, quotaInBytes, quotaInCounts,
+        creationTime, acls);
     this.modificationTime = Instant.ofEpochMilli(modificationTime);
   }
 
   @VisibleForTesting
   protected OzoneVolume(String name, String admin, String owner,
-      long quotaInBytes, long creationTime, List<OzoneAcl> acls) {
+      long quotaInBytes, long quotaInCounts, long creationTime,
+      List<OzoneAcl> acls) {
     this.proxy = null;
     this.name = name;
     this.admin = admin;
     this.owner = owner;
     this.quotaInBytes = quotaInBytes;
+    this.quotaInCounts = quotaInCounts;
     this.creationTime = Instant.ofEpochMilli(creationTime);
     this.acls = acls;
     this.metadata = new HashMap<>();
@@ -164,11 +174,12 @@ public class OzoneVolume extends WithMetadata {
     }
   }
 
+  @SuppressWarnings("parameternumber")
   @VisibleForTesting
   protected OzoneVolume(String name, String admin, String owner,
-      long quotaInBytes, long creationTime, long modificationTime,
-      List<OzoneAcl> acls) {
-    this(name, admin, owner, quotaInBytes, creationTime, acls);
+      long quotaInBytes, long quotaInCounts, long creationTime,
+      long modificationTime, List<OzoneAcl> acls) {
+    this(name, admin, owner, quotaInBytes, quotaInCounts, creationTime, acls);
     this.modificationTime = Instant.ofEpochMilli(modificationTime);
   }
 
@@ -204,11 +215,19 @@ public class OzoneVolume extends WithMetadata {
    *
    * @return quotaInBytes
    */
-  public long getQuota() {
+  public long getQuotaInBytes() {
     return quotaInBytes;
   }
 
   /**
+   * Returns quota of bucket counts allocated for the Volume.
+   *
+   * @return quotaInCounts
+   */
+  public long getQuotaInCounts() {
+    return quotaInCounts;
+  }
+  /**
    * Returns creation time of the volume.
    *
    * @return creation time.
@@ -248,12 +267,15 @@ public class OzoneVolume extends WithMetadata {
 
   /**
    * Sets/Changes the quota of this Volume.
-   * @param quota new quota
+   *
+   * @param quota OzoneQuota Object that can be applied to storage volume.
    * @throws IOException
    */
   public void setQuota(OzoneQuota quota) throws IOException {
-    proxy.setVolumeQuota(name, quota);
-    this.quotaInBytes = quota.sizeInBytes();
+    proxy.setVolumeQuota(name, quota.getQuotaInCounts(),
+        quota.getQuotaInBytes());
+    this.quotaInBytes = quota.getQuotaInBytes();
+    this.quotaInCounts = quota.getQuotaInCounts();
   }
 
   /**
diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/VolumeArgs.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/VolumeArgs.java
index 359e195..aa58e8c 100644
--- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/VolumeArgs.java
+++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/VolumeArgs.java
@@ -33,7 +33,8 @@ public final class VolumeArgs {
 
   private final String admin;
   private final String owner;
-  private final String quota;
+  private final String quotaInBytes;
+  private final long quotaInCounts;
   private final List<OzoneAcl> acls;
   private Map<String, String> metadata;
 
@@ -41,17 +42,21 @@ public final class VolumeArgs {
    * Private constructor, constructed via builder.
    * @param admin Administrator's name.
    * @param owner Volume owner's name
-   * @param quota Volume Quota.
+   * @param quotaInBytes Volume quota in bytes.
+   * @param quotaInCounts Volume quota in counts.
    * @param acls User to access rights map.
+   * @param metadata Metadata of volume.
    */
   private VolumeArgs(String admin,
       String owner,
-      String quota,
+      String quotaInBytes,
+      long quotaInCounts,
       List<OzoneAcl> acls,
       Map<String, String> metadata) {
     this.admin = admin;
     this.owner = owner;
-    this.quota = quota;
+    this.quotaInBytes = quotaInBytes;
+    this.quotaInCounts = quotaInCounts;
     this.acls = acls;
     this.metadata = metadata;
   }
@@ -73,11 +78,19 @@ public final class VolumeArgs {
   }
 
   /**
-   * Returns Volume Quota.
-   * @return Quota.
+   * Returns Volume Quota in bytes.
+   * @return quotaInBytes.
    */
-  public String getQuota() {
-    return quota;
+  public String getQuotaInBytes() {
+    return quotaInBytes;
+  }
+
+  /**
+   * Returns Volume Quota in bucket counts.
+   * @return quotaInCounts.
+   */
+  public long getQuotaInCounts() {
+    return quotaInCounts;
   }
 
   /**
@@ -107,7 +120,8 @@ public final class VolumeArgs {
   public static class Builder {
     private String adminName;
     private String ownerName;
-    private String volumeQuota;
+    private String quotaInBytes;
+    private long quotaInCounts;
     private List<OzoneAcl> listOfAcls;
     private Map<String, String> metadata = new HashMap<>();
 
@@ -122,8 +136,13 @@ public final class VolumeArgs {
       return this;
     }
 
-    public VolumeArgs.Builder setQuota(String quota) {
-      this.volumeQuota = quota;
+    public VolumeArgs.Builder setQuotaInBytes(String quota) {
+      this.quotaInBytes = quota;
+      return this;
+    }
+
+    public VolumeArgs.Builder setQuotaInCounts(long quota) {
+      this.quotaInCounts = quota;
       return this;
     }
 
@@ -142,8 +161,8 @@ public final class VolumeArgs {
      * @return CreateVolumeArgs.
      */
     public VolumeArgs build() {
-      return new VolumeArgs(adminName, ownerName, volumeQuota, listOfAcls,
-          metadata);
+      return new VolumeArgs(adminName, ownerName, quotaInBytes,
+          quotaInCounts, listOfAcls, metadata);
     }
   }
 
diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
index 1b8d93a..b81e71d 100644
--- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
+++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
@@ -24,7 +24,6 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.hadoop.crypto.key.KeyProvider;
-import org.apache.hadoop.hdds.client.OzoneQuota;
 import org.apache.hadoop.hdds.client.ReplicationFactor;
 import org.apache.hadoop.hdds.client.ReplicationType;
 import org.apache.hadoop.hdds.protocol.StorageType;
@@ -101,10 +100,11 @@ public interface ClientProtocol {
   /**
    * Set Volume Quota.
    * @param volumeName Name of the Volume
-   * @param quota Quota to be set for the Volume
+   * @param quotaInBytes The maximum size this volume can be used.
+   * @param quotaInCounts The maximum number of buckets in this volume.
    * @throws IOException
    */
-  void setVolumeQuota(String volumeName, OzoneQuota quota)
+  void setVolumeQuota(String volumeName, long quotaInBytes, long quotaInCounts)
       throws IOException;
 
   /**
diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
index 3f984d2..7928805 100644
--- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
+++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
@@ -281,9 +281,12 @@ public class RpcClient implements ClientProtocol {
         ugi.getUserName() : volArgs.getAdmin();
     String owner = volArgs.getOwner() == null ?
         ugi.getUserName() : volArgs.getOwner();
-    long quota = volArgs.getQuota() == null ?
-        OzoneConsts.MAX_QUOTA_IN_BYTES :
-        OzoneQuota.parseQuota(volArgs.getQuota()).sizeInBytes();
+    long quotaInCounts = volArgs.getQuotaInCounts() == 0 ?
+        OzoneConsts.QUOTA_RESET : volArgs.getQuotaInCounts();
+    long quotaInBytes = volArgs.getQuotaInBytes() == null ?
+        OzoneConsts.QUOTA_RESET :
+        OzoneQuota.parseQuota(volArgs.getQuotaInBytes(), quotaInCounts)
+            .getQuotaInBytes();
     List<OzoneAcl> listOfAcls = new ArrayList<>();
     //User ACL
     listOfAcls.add(new OzoneAcl(ACLIdentityType.USER,
@@ -302,7 +305,8 @@ public class RpcClient implements ClientProtocol {
     builder.setVolume(volumeName);
     builder.setAdminName(admin);
     builder.setOwnerName(owner);
-    builder.setQuotaInBytes(quota);
+    builder.setQuotaInBytes(quotaInBytes);
+    builder.setQuotaInCounts(quotaInCounts);
     builder.addAllMetadata(volArgs.getMetadata());
 
     //Remove duplicates and add ACLs
@@ -311,11 +315,12 @@ public class RpcClient implements ClientProtocol {
       builder.addOzoneAcls(OzoneAcl.toProtobuf(ozoneAcl));
     }
 
-    if (volArgs.getQuota() == null) {
+    if (volArgs.getQuotaInBytes() == null) {
       LOG.info("Creating Volume: {}, with {} as owner.", volumeName, owner);
     } else {
       LOG.info("Creating Volume: {}, with {} as owner "
-              + "and quota set to {} bytes.", volumeName, owner, quota);
+              + "and space quota set to {} bytes, counts quota set" +
+              " to {}", volumeName, owner, quotaInBytes, quotaInCounts);
     }
     ozoneManagerClient.createVolume(builder.build());
   }
@@ -329,12 +334,17 @@ public class RpcClient implements ClientProtocol {
   }
 
   @Override
-  public void setVolumeQuota(String volumeName, OzoneQuota quota)
-      throws IOException {
-    verifyVolumeName(volumeName);
-    Preconditions.checkNotNull(quota);
-    long quotaInBytes = quota.sizeInBytes();
-    ozoneManagerClient.setQuota(volumeName, quotaInBytes);
+  public void setVolumeQuota(String volumeName, long quotaInCounts,
+      long quotaInBytes) throws IOException {
+    HddsClientUtils.verifyResourceName(volumeName);
+    if ((quotaInCounts <= 0 && quotaInCounts != OzoneConsts.QUOTA_RESET)
+        || (quotaInBytes <= 0 && quotaInCounts != OzoneConsts.QUOTA_RESET)) {
+      throw new IllegalArgumentException("Invalid values for quota : " +
+          "counts quota is :" + quotaInCounts + " and " +
+          "space quota is :" + quotaInBytes);
+    }
+    ozoneManagerClient.setQuota(volumeName, quotaInCounts, quotaInBytes);
+
   }
 
   @Override
@@ -349,6 +359,7 @@ public class RpcClient implements ClientProtocol {
         volume.getAdminName(),
         volume.getOwnerName(),
         volume.getQuotaInBytes(),
+        volume.getQuotaInCounts(),
         volume.getCreationTime(),
         volume.getModificationTime(),
         volume.getAclMap().ozoneAclGetProtobuf().stream().
@@ -382,6 +393,7 @@ public class RpcClient implements ClientProtocol {
         volume.getAdminName(),
         volume.getOwnerName(),
         volume.getQuotaInBytes(),
+        volume.getQuotaInCounts(),
         volume.getCreationTime(),
         volume.getModificationTime(),
         volume.getAclMap().ozoneAclGetProtobuf().stream().
@@ -403,6 +415,7 @@ public class RpcClient implements ClientProtocol {
         volume.getAdminName(),
         volume.getOwnerName(),
         volume.getQuotaInBytes(),
+        volume.getQuotaInCounts(),
         volume.getCreationTime(),
         volume.getModificationTime(),
         volume.getAclMap().ozoneAclGetProtobuf().stream().
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmVolumeArgs.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmVolumeArgs.java
index b9caf9d..1d8e954 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmVolumeArgs.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmVolumeArgs.java
@@ -44,6 +44,7 @@ public final class OmVolumeArgs extends WithObjectID implements Auditable {
   private long creationTime;
   private long modificationTime;
   private long quotaInBytes;
+  private long quotaInCounts;
   private final OmOzoneAclMap aclMap;
 
   /**
@@ -52,6 +53,7 @@ public final class OmVolumeArgs extends WithObjectID implements Auditable {
    * @param ownerName  - Volume owner's name
    * @param volume - volume name
    * @param quotaInBytes - Volume Quota in bytes.
+   * @param quotaInCounts - Volume Quota in counts.
    * @param metadata - metadata map for custom key/value data.
    * @param aclMap - User to access rights map.
    * @param creationTime - Volume creation time.
@@ -62,13 +64,14 @@ public final class OmVolumeArgs extends WithObjectID implements Auditable {
   @SuppressWarnings({"checkstyle:ParameterNumber", "This is invoked from a " +
       "builder."})
   private OmVolumeArgs(String adminName, String ownerName, String volume,
-                       long quotaInBytes, Map<String, String> metadata,
-                       OmOzoneAclMap aclMap, long creationTime,
-                       long modificationTime, long objectID, long updateID) {
+      long quotaInBytes, long quotaInCounts, Map<String, String> metadata,
+      OmOzoneAclMap aclMap, long creationTime, long modificationTime,
+      long objectID, long updateID) {
     this.adminName = adminName;
     this.ownerName = ownerName;
     this.volume = volume;
     this.quotaInBytes = quotaInBytes;
+    this.quotaInCounts = quotaInCounts;
     this.metadata = metadata;
     this.aclMap = aclMap;
     this.creationTime = creationTime;
@@ -86,6 +89,10 @@ public final class OmVolumeArgs extends WithObjectID implements Auditable {
     this.quotaInBytes = quotaInBytes;
   }
 
+  public void setQuotaInCounts(long quotaInCounts) {
+    this.quotaInCounts= quotaInCounts;
+  }
+
   public void setCreationTime(long time) {
     this.creationTime = time;
   }
@@ -154,6 +161,14 @@ public final class OmVolumeArgs extends WithObjectID implements Auditable {
     return quotaInBytes;
   }
 
+  /**
+   * Returns Quota in counts.
+   * @return long, Quota in counts.
+   */
+  public long getQuotaInCounts() {
+    return quotaInCounts;
+  }
+
   public OmOzoneAclMap getAclMap() {
     return aclMap;
   }
@@ -176,6 +191,8 @@ public final class OmVolumeArgs extends WithObjectID implements Auditable {
     auditMap.put(OzoneConsts.MODIFICATION_TIME,
         String.valueOf(this.modificationTime));
     auditMap.put(OzoneConsts.QUOTA_IN_BYTES, String.valueOf(this.quotaInBytes));
+    auditMap.put(OzoneConsts.QUOTA_IN_COUNTS,
+        String.valueOf(this.quotaInCounts));
     auditMap.put(OzoneConsts.OBJECT_ID, String.valueOf(this.getObjectID()));
     auditMap.put(OzoneConsts.UPDATE_ID, String.valueOf(this.getUpdateID()));
     return auditMap;
@@ -208,6 +225,7 @@ public final class OmVolumeArgs extends WithObjectID implements Auditable {
     private long creationTime;
     private long modificationTime;
     private long quotaInBytes;
+    private long quotaInCounts;
     private Map<String, String> metadata;
     private OmOzoneAclMap aclMap;
     private long objectID;
@@ -267,8 +285,13 @@ public final class OmVolumeArgs extends WithObjectID implements Auditable {
       return this;
     }
 
-    public Builder setQuotaInBytes(long quota) {
-      this.quotaInBytes = quota;
+    public Builder setQuotaInBytes(long quotaBytes) {
+      this.quotaInBytes = quotaBytes;
+      return this;
+    }
+
+    public Builder setQuotaInCounts(long quotaCounts) {
+      this.quotaInCounts = quotaCounts;
       return this;
     }
 
@@ -298,7 +321,8 @@ public final class OmVolumeArgs extends WithObjectID implements Auditable {
       Preconditions.checkNotNull(ownerName);
       Preconditions.checkNotNull(volume);
       return new OmVolumeArgs(adminName, ownerName, volume, quotaInBytes,
-          metadata, aclMap, creationTime, modificationTime, objectID, updateID);
+          quotaInCounts, metadata, aclMap, creationTime, modificationTime,
+          objectID, updateID);
     }
 
   }
@@ -310,6 +334,7 @@ public final class OmVolumeArgs extends WithObjectID implements Auditable {
         .setOwnerName(ownerName)
         .setVolume(volume)
         .setQuotaInBytes(quotaInBytes)
+        .setQuotaInCounts(quotaInCounts)
         .addAllMetadata(KeyValueUtil.toProtobuf(metadata))
         .addAllVolumeAcls(aclList)
         .setCreationTime(
@@ -329,6 +354,7 @@ public final class OmVolumeArgs extends WithObjectID implements Auditable {
         volInfo.getOwnerName(),
         volInfo.getVolume(),
         volInfo.getQuotaInBytes(),
+        volInfo.getQuotaInCounts(),
         KeyValueUtil.getFromProtobuf(volInfo.getMetadataList()),
         aclMap,
         volInfo.getCreationTime(),
@@ -360,7 +386,7 @@ public final class OmVolumeArgs extends WithObjectID implements Auditable {
     OmOzoneAclMap cloneAclMap = aclMap.copyObject();
 
     return new OmVolumeArgs(adminName, ownerName, volume, quotaInBytes,
-        cloneMetadata, cloneAclMap, creationTime, modificationTime,
-        objectID, updateID);
+        quotaInCounts, cloneMetadata, cloneAclMap, creationTime,
+        modificationTime, objectID, updateID);
   }
 }
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
index 267ac89..79cc926 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
@@ -89,10 +89,12 @@ public interface OzoneManagerProtocol
   /**
    * Changes the Quota on a volume.
    * @param volume - Name of the volume.
-   * @param quota - Quota in bytes.
+   * @param quotaInCounts - Volume quota in counts.
+   * @param quotaInBytes - Volume quota in bytes.
    * @throws IOException
    */
-  void setQuota(String volume, long quota) throws IOException;
+  void setQuota(String volume, long quotaInCounts, long quotaInBytes)
+      throws IOException;
 
   /**
    * Checks if the specified user can access this volume.
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
index a6ea042..be89c25 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
@@ -263,14 +263,18 @@ public final class OzoneManagerProtocolClientSideTranslatorPB
    * Changes the Quota on a volume.
    *
    * @param volume - Name of the volume.
-   * @param quota - Quota in bytes.
+   * @param quotaInCounts - Volume quota in counts.
+   * @param quotaInBytes - Volume quota in bytes.
    * @throws IOException
    */
   @Override
-  public void setQuota(String volume, long quota) throws IOException {
+  public void setQuota(String volume, long quotaInCounts,
+      long quotaInBytes) throws IOException {
     SetVolumePropertyRequest.Builder req =
         SetVolumePropertyRequest.newBuilder();
-    req.setVolumeName(volume).setQuotaInBytes(quota);
+    req.setVolumeName(volume)
+       .setQuotaInBytes(quotaInBytes)
+       .setQuotaInCounts(quotaInCounts);
 
     OMRequest omRequest = createOMRequest(Type.SetVolumeProperty)
         .setSetVolumePropertyRequest(req)
diff --git a/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell-lib.robot b/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell-lib.robot
index ba00061..87b46ec 100644
--- a/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell-lib.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell-lib.robot
@@ -31,17 +31,17 @@ Test ozone shell
     [arguments]     ${protocol}         ${server}       ${volume}
     ${result} =     Execute And Ignore Error    ozone sh volume info ${protocol}${server}/${volume}
                     Should contain      ${result}       VOLUME_NOT_FOUND
-    ${result} =     Execute             ozone sh volume create ${protocol}${server}/${volume} --quota 100TB
+    ${result} =     Execute             ozone sh volume create ${protocol}${server}/${volume} --spaceQuota 100TB --bucketQuota 100
                     Should not contain  ${result}       Failed
     ${result} =     Execute             ozone sh volume list ${protocol}${server}/ | jq -r '. | select(.name=="${volume}")'
                     Should contain      ${result}       creationTime
     ${result} =     Execute             ozone sh volume list | jq -r '. | select(.name=="${volume}")'
                     Should contain      ${result}       creationTime
 # TODO: Disable updating the owner, acls should be used to give access to other user.        
-                    Execute             ozone sh volume update ${protocol}${server}/${volume} --quota 10TB
+                    Execute             ozone sh volume update ${protocol}${server}/${volume} --spaceQuota 10TB --bucketQuota 100
 #    ${result} =     Execute             ozone sh volume info ${protocol}${server}/${volume} | jq -r '. | select(.volumeName=="${volume}") | .owner | .name'
 #                    Should Be Equal     ${result}       bill
-    ${result} =     Execute             ozone sh volume info ${protocol}${server}/${volume} | jq -r '. | select(.name=="${volume}") | .quota'
+    ${result} =     Execute             ozone sh volume info ${protocol}${server}/${volume} | jq -r '. | select(.name=="${volume}") | .quotaInBytes'
                     Should Be Equal     ${result}       10995116277760
                     Execute             ozone sh bucket create ${protocol}${server}/${volume}/bb1
     ${result} =     Execute             ozone sh bucket info ${protocol}${server}/${volume}/bb1 | jq -r '. | select(.name=="bb1") | .storageType'
diff --git a/hadoop-ozone/dist/src/main/smoketest/createbucketenv.robot b/hadoop-ozone/dist/src/main/smoketest/createbucketenv.robot
index c89abfc..551f050 100644
--- a/hadoop-ozone/dist/src/main/smoketest/createbucketenv.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/createbucketenv.robot
@@ -27,7 +27,7 @@ ${bucket}       bucket1
 
 *** Keywords ***
 Create volume
-    ${result} =     Execute             ozone sh volume create /${volume} --user hadoop --quota 100TB
+    ${result} =     Execute             ozone sh volume create /${volume} --user hadoop --spaceQuota 100TB --bucketQuota 100
                     Should not contain  ${result}       Failed
 Create bucket
                     Execute             ozone sh bucket create /${volume}/${bucket}
diff --git a/hadoop-ozone/dist/src/main/smoketest/createmrenv.robot b/hadoop-ozone/dist/src/main/smoketest/createmrenv.robot
index d36db58..c399163 100644
--- a/hadoop-ozone/dist/src/main/smoketest/createmrenv.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/createmrenv.robot
@@ -29,7 +29,7 @@ ${bucket}       bucket1
 
 *** Keywords ***
 Create volume
-    ${result} =     Execute             ozone sh volume create /${volume} --user hadoop --quota 100TB
+    ${result} =     Execute             ozone sh volume create /${volume} --user hadoop --spaceQuota 100TB --bucketQuota 100
                     Should not contain  ${result}       Failed
 Create bucket
                     Execute             ozone sh bucket create /${volume}/${bucket}
diff --git a/hadoop-ozone/dist/src/main/smoketest/debug/ozone-debug.robot b/hadoop-ozone/dist/src/main/smoketest/debug/ozone-debug.robot
index f7e3274..301c107 100644
--- a/hadoop-ozone/dist/src/main/smoketest/debug/ozone-debug.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/debug/ozone-debug.robot
@@ -23,7 +23,7 @@ Suite Setup         Write key
 
 *** Keywords ***
 Write key
-    Execute             ozone sh volume create o3://om/vol1 --quota 100TB
+    Execute             ozone sh volume create o3://om/vol1 --spaceQuota 100TB --bucketQuota 100
     Execute             ozone sh bucket create o3://om/vol1/bucket1
     Execute             ozone sh key put o3://om/vol1/bucket1/debugKey /opt/hadoop/NOTICE.txt
 
diff --git a/hadoop-ozone/dist/src/main/smoketest/gdpr/gdpr.robot b/hadoop-ozone/dist/src/main/smoketest/gdpr/gdpr.robot
index 91e41fc..d7e95b2 100644
--- a/hadoop-ozone/dist/src/main/smoketest/gdpr/gdpr.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/gdpr/gdpr.robot
@@ -46,7 +46,7 @@ Test GDPR -g=false
 *** Keywords ***
 Test GDPR(disabled) without explicit options
     [arguments]     ${volume}
-                    Execute             ozone sh volume create /${volume} --quota 100TB
+                    Execute             ozone sh volume create /${volume} --spaceQuota 100TB --bucketQuota 100
                     Execute             ozone sh bucket create /${volume}/mybucket1
     ${result} =     Execute             ozone sh bucket info /${volume}/mybucket1 | jq -r '. | select(.name=="mybucket1") | .metadata | .gdprEnabled'
                     Should Be Equal     ${result}       null
diff --git a/hadoop-ozone/dist/src/main/smoketest/ozonefs/setup.robot b/hadoop-ozone/dist/src/main/smoketest/ozonefs/setup.robot
index 441822d..22d79a4 100644
--- a/hadoop-ozone/dist/src/main/smoketest/ozonefs/setup.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/ozonefs/setup.robot
@@ -37,8 +37,8 @@ Setup for FS test
     Log    Completed setup for ${SCHEME} tests with ${BUCKET_TYPE}s in ${VOLUME}/${BUCKET} using FS base URL: ${BASE_URL}
 
 Create volumes for FS test
-    Execute And Ignore Error    ozone sh volume create ${VOLUME} --quota 100TB
-    Execute And Ignore Error    ozone sh volume create ${VOL2} --quota 100TB
+    Execute And Ignore Error    ozone sh volume create ${VOLUME} --spaceQuota 100TB
+    Execute And Ignore Error    ozone sh volume create ${VOL2} --spaceQuota 100TB
 
 Create buckets for FS test
     Execute                     ozone sh bucket create ${VOLUME}/${BUCKET}
@@ -46,8 +46,8 @@ Create buckets for FS test
     Execute                     ozone sh bucket create ${VOL2}/${BUCKET_IN_VOL2}
 
 Create links for FS test
-    Execute And Ignore Error    ozone sh volume create ${VOLUME}-src --quota 100TB
-    Execute And Ignore Error    ozone sh volume create ${VOL2}-src --quota 100TB
+    Execute And Ignore Error    ozone sh volume create ${VOLUME}-src --spaceQuota 100TB
+    Execute And Ignore Error    ozone sh volume create ${VOL2}-src --spaceQuota 100TB
     Execute                     ozone sh bucket create ${VOLUME}-src/${BUCKET}-src
     Execute                     ozone sh bucket create ${VOLUME}-src/${BUCKET2}-src
     Execute                     ozone sh bucket create ${VOL2}-src/${BUCKET_IN_VOL2}-src
diff --git a/hadoop-ozone/dist/src/main/smoketest/topology/loaddata.robot b/hadoop-ozone/dist/src/main/smoketest/topology/loaddata.robot
index 35457e6..b930312 100644
--- a/hadoop-ozone/dist/src/main/smoketest/topology/loaddata.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/topology/loaddata.robot
@@ -25,7 +25,7 @@ Test Timeout        5 minutes
 
 *** Test Cases ***
 Create a volume, bucket and key
-    ${output} =         Execute          ozone sh volume create topvol1 --quota 100TB
+    ${output} =         Execute          ozone sh volume create topvol1
                         Should not contain  ${output}       Failed
     ${output} =         Execute          ozone sh bucket create /topvol1/bucket1
                         Should not contain  ${output}       Failed
diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestRootedOzoneFileSystem.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestRootedOzoneFileSystem.java
index b812b45..2c1e336 100644
--- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestRootedOzoneFileSystem.java
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestRootedOzoneFileSystem.java
@@ -805,11 +805,14 @@ public class TestRootedOzoneFileSystem {
         userRights, ACCESS);
     // Construct VolumeArgs
     VolumeArgs volumeArgs = new VolumeArgs.Builder()
-        .setAcls(Collections.singletonList(aclWorldAccess)).build();
+        .setAcls(Collections.singletonList(aclWorldAccess))
+        .setQuotaInCounts(1000)
+        .setQuotaInBytes("1MB").build();
     // Sanity check
     Assert.assertNull(volumeArgs.getOwner());
     Assert.assertNull(volumeArgs.getAdmin());
-    Assert.assertNull(volumeArgs.getQuota());
+    Assert.assertEquals("1MB", volumeArgs.getQuotaInBytes());
+    Assert.assertEquals(1000, volumeArgs.getQuotaInCounts());
     Assert.assertEquals(0, volumeArgs.getMetadata().size());
     Assert.assertEquals(1, volumeArgs.getAcls().size());
     // Create volume "tmp" with world access. allow non-admin to create buckets
diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClientAbstract.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClientAbstract.java
index 45d07b0..a92b644 100644
--- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClientAbstract.java
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClientAbstract.java
@@ -270,14 +270,51 @@ public abstract class TestOzoneRpcClientAbstract {
   }
 
   @Test
-  public void testSetVolumeQuota()
-      throws IOException {
+  public void testSetVolumeQuota() throws IOException {
     String volumeName = UUID.randomUUID().toString();
     store.createVolume(volumeName);
-    store.getVolume(volumeName).setQuota(
-        OzoneQuota.parseQuota("100000000 BYTES"));
+    Assert.assertEquals(OzoneConsts.QUOTA_RESET,
+        store.getVolume(volumeName).getQuotaInBytes());
+    Assert.assertEquals(OzoneConsts.QUOTA_RESET,
+        store.getVolume(volumeName).getQuotaInCounts());
+    store.getVolume(volumeName).setQuota(OzoneQuota.parseQuota("1GB", 1000L));
     OzoneVolume volume = store.getVolume(volumeName);
-    Assert.assertEquals(100000000L, volume.getQuota());
+    Assert.assertEquals(1024 * 1024 * 1024,
+        volume.getQuotaInBytes());
+    Assert.assertEquals(1000L, volume.getQuotaInCounts());
+  }
+
+  @Test
+  public void testSetVolumeQuotaIllegal()
+      throws IOException {
+    String volumeName = UUID.randomUUID().toString();
+    store.createVolume(volumeName);
+    // The unit should be legal.
+    try {
+      store.getVolume(volumeName).setQuota(OzoneQuota.parseQuota(
+          "1TEST", 1000L));
+    } catch (IllegalArgumentException ex) {
+      GenericTestUtils.assertExceptionContains(
+          "Invalid values for quota", ex);
+    }
+
+    // The setting value cannot be greater than LONG.MAX_VALUE BYTES.
+    try {
+      store.getVolume(volumeName).setQuota(OzoneQuota.parseQuota(
+          "9999999999999GB", 1000L));
+    } catch (IllegalArgumentException ex) {
+      GenericTestUtils.assertExceptionContains(
+          "Invalid values for quota", ex);
+    }
+
+    // The value cannot be negative.
+    try {
+      store.getVolume(volumeName).setQuota(OzoneQuota.parseQuota(
+          "-10GB", 1000L));
+    } catch (IllegalArgumentException ex) {
+      GenericTestUtils.assertExceptionContains(
+          "Quota cannot be negative.", ex);
+    }
   }
 
   @Test
diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
index c6e2949..1fc1b16 100644
--- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
+++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
@@ -359,6 +359,7 @@ message VolumeInfo {
     optional uint64 objectID = 8;
     optional uint64 updateID = 9;
     optional uint64 modificationTime = 10;
+    optional uint64 quotaInCounts = 11;
 }
 
 /**
@@ -417,6 +418,7 @@ message SetVolumePropertyRequest {
     optional string ownerName = 2;
     optional uint64 quotaInBytes = 3;
     optional uint64 modificationTime = 4;
+    optional uint64 quotaInCounts = 5;
 }
 
 message SetVolumePropertyResponse {
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
index 9daeec1..3ae8433 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
@@ -1741,29 +1741,15 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
    * Changes the Quota on a volume.
    *
    * @param volume - Name of the volume.
-   * @param quota  - Quota in bytes.
+   * @param quotaInCounts - Volume quota in counts.
+   * @param quotaInBytes - Volume quota in bytes.
    * @throws IOException
    */
   @Override
-  public void setQuota(String volume, long quota) throws IOException {
-    if (isAclEnabled) {
-      checkAcls(ResourceType.VOLUME, StoreType.OZONE, ACLType.WRITE, volume,
-          null, null);
-    }
-
-    Map<String, String> auditMap = buildAuditMap(volume);
-    auditMap.put(OzoneConsts.QUOTA_IN_BYTES, String.valueOf(quota));
-    try {
-      metrics.incNumVolumeUpdates();
-      volumeManager.setQuota(volume, quota);
-      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(OMAction.SET_QUOTA,
-          auditMap));
-    } catch (Exception ex) {
-      metrics.incNumVolumeUpdateFails();
-      AUDIT.logWriteFailure(buildAuditMessageForFailure(OMAction.SET_QUOTA,
-          auditMap, ex));
-      throw ex;
-    }
+  public void setQuota(String volume, long quotaInCounts,
+                       long quotaInBytes) throws IOException {
+    throw new UnsupportedOperationException("OzoneManager does not require " +
+        "this to be implemented. As this requests use a new approach");
   }
 
   /**
@@ -3615,7 +3601,7 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
         .setModificationTime(time)
         .setOwnerName(userName)
         .setAdminName(userName)
-        .setQuotaInBytes(OzoneConsts.MAX_QUOTA_IN_BYTES);
+        .setQuotaInBytes(OzoneConsts.QUOTA_RESET);
 
     // Provide ACLType of ALL which is default acl rights for user and group.
     List<OzoneAcl> listOfAcls = new ArrayList<>();
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/VolumeManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/VolumeManager.java
index 01c277f..1dc370b 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/VolumeManager.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/VolumeManager.java
@@ -46,15 +46,6 @@ public interface VolumeManager extends IOzoneAcl {
       throws IOException;
 
   /**
-   * Changes the Quota on a volume.
-   *
-   * @param volume - Name of the volume.
-   * @param quota - Quota in bytes.
-   * @throws IOException
-   */
-  void setQuota(String volume, long quota) throws IOException;
-
-  /**
    * Gets the volume information.
    * @param volume - Volume name.
    * @return VolumeArgs or exception is thrown.
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/VolumeManagerImpl.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/VolumeManagerImpl.java
index f7d730a..b3e8186 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/VolumeManagerImpl.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/VolumeManagerImpl.java
@@ -244,7 +244,6 @@ public class VolumeManagerImpl implements VolumeManager {
     }
   }
 
-
   private void setOwnerCommitToDB(UserVolumeInfo oldOwnerVolumeList,
       UserVolumeInfo newOwnerVolumeList, OmVolumeArgs newOwnerVolumeArgs,
       String oldOwner) throws IOException {
@@ -268,44 +267,6 @@ public class VolumeManagerImpl implements VolumeManager {
     }
   }
 
-
-  /**
-   * Changes the Quota on a volume.
-   *
-   * @param volume - Name of the volume.
-   * @param quota - Quota in bytes.
-   *
-   * @throws IOException
-   */
-  @Override
-  public void setQuota(String volume, long quota) throws IOException {
-    Preconditions.checkNotNull(volume);
-    metadataManager.getLock().acquireLock(VOLUME_LOCK, volume);
-    try {
-      String dbVolumeKey = metadataManager.getVolumeKey(volume);
-      OmVolumeArgs volumeArgs =
-          metadataManager.getVolumeTable().get(dbVolumeKey);
-      if (volumeArgs == null) {
-        LOG.debug("volume:{} does not exist", volume);
-        throw new OMException(ResultCodes.VOLUME_NOT_FOUND);
-      }
-
-      Preconditions.checkState(volume.equals(volumeArgs.getVolume()));
-
-      volumeArgs.setQuotaInBytes(quota);
-
-      metadataManager.getVolumeTable().put(dbVolumeKey, volumeArgs);
-    } catch (IOException ex) {
-      if (!(ex instanceof OMException)) {
-        LOG.error("Changing volume quota failed for volume:{} quota:{}", volume,
-            quota, ex);
-      }
-      throw ex;
-    } finally {
-      metadataManager.getLock().releaseLock(VOLUME_LOCK, volume);
-    }
-  }
-
   /**
    * Gets the volume information.
    * @param volume - Volume name.
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/OMVolumeSetQuotaRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/OMVolumeSetQuotaRequest.java
index 746a1a6..2ad097e 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/OMVolumeSetQuotaRequest.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/OMVolumeSetQuotaRequest.java
@@ -130,6 +130,8 @@ public class OMVolumeSetQuotaRequest extends OMVolumeRequest {
       omVolumeArgs = getVolumeInfo(omMetadataManager, volume);
 
       omVolumeArgs.setQuotaInBytes(setVolumePropertyRequest.getQuotaInBytes());
+      omVolumeArgs.setQuotaInCounts(
+          setVolumePropertyRequest.getQuotaInCounts());
       omVolumeArgs.setUpdateID(transactionLogIndex,
           ozoneManager.isRatisEnabled());
       omVolumeArgs.setModificationTime(
diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMRequestUtils.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMRequestUtils.java
index 25268ff..144750d 100644
--- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMRequestUtils.java
+++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMRequestUtils.java
@@ -392,14 +392,17 @@ public final class TestOMRequestUtils {
   /**
    * Create OMRequest for set volume property request with quota set.
    * @param volumeName
-   * @param quota
+   * @param quotaInBytes
+   * @param quotaInCounts
    * @return OMRequest
    */
   public static OMRequest createSetVolumePropertyRequest(String volumeName,
-      long quota) {
+      long quotaInBytes, long quotaInCounts) {
     SetVolumePropertyRequest setVolumePropertyRequest =
         SetVolumePropertyRequest.newBuilder().setVolumeName(volumeName)
-            .setQuotaInBytes(quota).setModificationTime(Time.now()).build();
+            .setQuotaInBytes(quotaInBytes)
+            .setQuotaInCounts(quotaInCounts)
+            .setModificationTime(Time.now()).build();
 
     return OMRequest.newBuilder().setClientId(UUID.randomUUID().toString())
         .setCmdType(OzoneManagerProtocolProtos.Type.SetVolumeProperty)
diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeSetOwnerRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeSetOwnerRequest.java
index 4ccf195..cedad4b 100644
--- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeSetOwnerRequest.java
+++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeSetOwnerRequest.java
@@ -151,7 +151,7 @@ public class TestOMVolumeSetOwnerRequest extends TestOMVolumeRequest {
     // create request with quota set.
     OMRequest originalRequest =
         TestOMRequestUtils.createSetVolumePropertyRequest(volumeName,
-            100L);
+            100L, 100L);
 
     OMVolumeSetOwnerRequest omVolumeSetOwnerRequest =
         new OMVolumeSetOwnerRequest(originalRequest);
diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeSetQuotaRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeSetQuotaRequest.java
index 4d78ef0..fca734c 100644
--- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeSetQuotaRequest.java
+++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeSetQuotaRequest.java
@@ -27,8 +27,7 @@ import org.junit.Assert;
 import org.junit.Test;
 
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
-import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
-    .OMRequest;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
 
 /**
  * Tests set volume property request.
@@ -38,9 +37,11 @@ public class TestOMVolumeSetQuotaRequest extends TestOMVolumeRequest {
   @Test
   public void testPreExecute() throws Exception {
     String volumeName = UUID.randomUUID().toString();
-    long quota = 100L;
+    long quotaInBytes = 100L;
+    long quotaInCounts = 1000L;
     OMRequest originalRequest =
-        TestOMRequestUtils.createSetVolumePropertyRequest(volumeName, quota);
+        TestOMRequestUtils.createSetVolumePropertyRequest(volumeName,
+            quotaInBytes, quotaInCounts);
 
     OMVolumeSetQuotaRequest omVolumeSetQuotaRequest =
         new OMVolumeSetQuotaRequest(originalRequest);
@@ -54,14 +55,15 @@ public class TestOMVolumeSetQuotaRequest extends TestOMVolumeRequest {
   public void testValidateAndUpdateCacheSuccess() throws Exception {
     String volumeName = UUID.randomUUID().toString();
     String ownerName = "user1";
-    long quotaSet = 100L;
+    long quotaInBytes = 100L;
+    long quotaInCounts = 1000L;
 
     TestOMRequestUtils.addUserToDB(volumeName, ownerName, omMetadataManager);
     TestOMRequestUtils.addVolumeToDB(volumeName, ownerName, omMetadataManager);
 
-
     OMRequest originalRequest =
-        TestOMRequestUtils.createSetVolumePropertyRequest(volumeName, quotaSet);
+        TestOMRequestUtils.createSetVolumePropertyRequest(volumeName,
+            quotaInBytes, quotaInCounts);
 
     OMVolumeSetQuotaRequest omVolumeSetQuotaRequest =
         new OMVolumeSetQuotaRequest(originalRequest);
@@ -75,7 +77,8 @@ public class TestOMVolumeSetQuotaRequest extends TestOMVolumeRequest {
         omMetadataManager.getVolumeTable().get(volumeKey);
     // As request is valid volume table should not have entry.
     Assert.assertNotNull(omVolumeArgs);
-    long quotaBeforeSet = omVolumeArgs.getQuotaInBytes();
+    long quotaBytesBeforeSet = omVolumeArgs.getQuotaInBytes();
+    long quotaCountBeforeSet = omVolumeArgs.getQuotaInCounts();
 
     OMClientResponse omClientResponse =
         omVolumeSetQuotaRequest.validateAndUpdateCache(ozoneManager, 1,
@@ -88,10 +91,13 @@ public class TestOMVolumeSetQuotaRequest extends TestOMVolumeRequest {
         omResponse.getStatus());
 
 
-    long quotaAfterSet = omMetadataManager
-        .getVolumeTable().get(volumeKey).getQuotaInBytes();
-    Assert.assertEquals(quotaSet, quotaAfterSet);
-    Assert.assertNotEquals(quotaBeforeSet, quotaAfterSet);
+    OmVolumeArgs ova = omMetadataManager.getVolumeTable().get(volumeKey);
+    long quotaBytesAfterSet = ova.getQuotaInBytes();
+    long quotaCountAfterSet = ova.getQuotaInCounts();
+    Assert.assertEquals(quotaInBytes, quotaBytesAfterSet);
+    Assert.assertEquals(quotaInCounts, quotaCountAfterSet);
+    Assert.assertNotEquals(quotaBytesBeforeSet, quotaBytesAfterSet);
+    Assert.assertNotEquals(quotaCountBeforeSet, quotaCountAfterSet);
 
     // modificationTime should be greater than creationTime.
     long creationTime = omMetadataManager
@@ -105,10 +111,12 @@ public class TestOMVolumeSetQuotaRequest extends TestOMVolumeRequest {
   public void testValidateAndUpdateCacheWithVolumeNotFound()
       throws Exception {
     String volumeName = UUID.randomUUID().toString();
-    long quota = 100L;
+    long quotaInBytes = 100L;
+    long quotaInCounts= 100L;
 
     OMRequest originalRequest =
-        TestOMRequestUtils.createSetVolumePropertyRequest(volumeName, quota);
+        TestOMRequestUtils.createSetVolumePropertyRequest(volumeName,
+            quotaInBytes, quotaInCounts);
 
     OMVolumeSetQuotaRequest omVolumeSetQuotaRequest =
         new OMVolumeSetQuotaRequest(originalRequest);
diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ObjectStoreStub.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ObjectStoreStub.java
index b83cf6c..53c4cda 100644
--- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ObjectStoreStub.java
+++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ObjectStoreStub.java
@@ -55,7 +55,7 @@ public class ObjectStoreStub extends ObjectStore {
         VolumeArgs.newBuilder()
             .setAdmin("root")
             .setOwner("root")
-            .setQuota("" + Integer.MAX_VALUE)
+            .setQuotaInBytes("" + Integer.MAX_VALUE)
             .setAcls(new ArrayList<>()).build());
   }
 
@@ -65,7 +65,8 @@ public class ObjectStoreStub extends ObjectStore {
         new OzoneVolumeStub(volumeName,
             volumeArgs.getAdmin(),
             volumeArgs.getOwner(),
-            Long.parseLong(volumeArgs.getQuota()),
+            Long.parseLong(volumeArgs.getQuotaInBytes()),
+            volumeArgs.getQuotaInCounts(),
             Time.now(),
             volumeArgs.getAcls());
     volumes.put(volumeName, volume);
diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneVolumeStub.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneVolumeStub.java
index 8538bb2..53a5d81 100644
--- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneVolumeStub.java
+++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneVolumeStub.java
@@ -39,9 +39,9 @@ public class OzoneVolumeStub extends OzoneVolume {
   private Map<String, OzoneBucketStub> buckets = new HashMap<>();
 
   public OzoneVolumeStub(String name, String admin, String owner,
-      long quotaInBytes, long creationTime, List<OzoneAcl> acls) {
-    super(name, admin, owner, quotaInBytes,
-        creationTime, acls);
+      long quotaInBytes, long quotaInCounts, long creationTime,
+      List<OzoneAcl> acls) {
+    super(name, admin, owner, quotaInBytes, quotaInCounts, creationTime, acls);
   }
 
   @Override
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/freon/RandomKeyGenerator.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/freon/RandomKeyGenerator.java
index 6e5e627..de305dc 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/freon/RandomKeyGenerator.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/freon/RandomKeyGenerator.java
@@ -41,7 +41,6 @@ import java.util.function.LongSupplier;
 import org.apache.hadoop.hdds.HddsConfigKeys;
 import org.apache.hadoop.hdds.StringUtils;
 import org.apache.hadoop.hdds.cli.HddsVersionProvider;
-import org.apache.hadoop.hdds.client.OzoneQuota;
 import org.apache.hadoop.hdds.client.ReplicationFactor;
 import org.apache.hadoop.hdds.client.ReplicationType;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
@@ -823,22 +822,22 @@ public final class RandomKeyGenerator implements Callable<Void> {
 
     private String getInStorageUnits(Double value) {
       double size;
-      OzoneQuota.Units unit;
+      OzoneConsts.Units unit;
       if ((long) (value / OzoneConsts.TB) != 0) {
         size = value / OzoneConsts.TB;
-        unit = OzoneQuota.Units.TB;
+        unit = OzoneConsts.Units.TB;
       } else if ((long) (value / OzoneConsts.GB) != 0) {
         size = value / OzoneConsts.GB;
-        unit = OzoneQuota.Units.GB;
+        unit = OzoneConsts.Units.GB;
       } else if ((long) (value / OzoneConsts.MB) != 0) {
         size = value / OzoneConsts.MB;
-        unit = OzoneQuota.Units.MB;
+        unit = OzoneConsts.Units.MB;
       } else if ((long) (value / OzoneConsts.KB) != 0) {
         size = value / OzoneConsts.KB;
-        unit = OzoneQuota.Units.KB;
+        unit = OzoneConsts.Units.KB;
       } else {
         size = value;
-        unit = OzoneQuota.Units.BYTES;
+        unit = OzoneConsts.Units.BYTES;
       }
       return size + " " + unit;
     }
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/volume/CreateVolumeHandler.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/volume/CreateVolumeHandler.java
index af0ea1e..d8f0520 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/volume/CreateVolumeHandler.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/volume/CreateVolumeHandler.java
@@ -18,6 +18,7 @@
 
 package org.apache.hadoop.ozone.shell.volume;
 
+import org.apache.hadoop.ozone.OzoneConsts;
 import org.apache.hadoop.ozone.client.OzoneClient;
 import org.apache.hadoop.ozone.client.OzoneVolume;
 import org.apache.hadoop.ozone.client.VolumeArgs;
@@ -40,10 +41,13 @@ public class CreateVolumeHandler extends VolumeHandler {
       description = "Owner of the volume")
   private String ownerName;
 
-  @Option(names = {"--quota", "-q"},
-      description =
-          "Quota of the newly created volume (eg. 1G)")
-  private String quota;
+  @Option(names = {"--spaceQuota", "-sq"},
+      description = "Quota in bytes of the newly created volume (eg. 1GB)")
+  private String quotaInBytes;
+
+  @Option(names = {"--bucketQuota", "-bq"},
+      description = "Bucket counts of the newly created volume (eg. 5)")
+  private long quotaInCounts = OzoneConsts.QUOTA_RESET;
 
   @Override
   protected void execute(OzoneClient client, OzoneAddress address)
@@ -58,9 +62,12 @@ public class CreateVolumeHandler extends VolumeHandler {
     VolumeArgs.Builder volumeArgsBuilder = VolumeArgs.newBuilder()
         .setAdmin(adminName)
         .setOwner(ownerName);
-    if (quota != null) {
-      volumeArgsBuilder.setQuota(quota);
+    if (quotaInBytes != null) {
+      volumeArgsBuilder.setQuotaInBytes(quotaInBytes);
     }
+
+    volumeArgsBuilder.setQuotaInCounts(quotaInCounts);
+
     client.getObjectStore().createVolume(volumeName,
         volumeArgsBuilder.build());
 
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/volume/UpdateVolumeHandler.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/volume/UpdateVolumeHandler.java
index ba55e08..a57efb0 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/volume/UpdateVolumeHandler.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/volume/UpdateVolumeHandler.java
@@ -19,6 +19,7 @@
 package org.apache.hadoop.ozone.shell.volume;
 
 import org.apache.hadoop.hdds.client.OzoneQuota;
+import org.apache.hadoop.ozone.OzoneConsts;
 import org.apache.hadoop.ozone.client.OzoneClient;
 import org.apache.hadoop.ozone.client.OzoneVolume;
 import org.apache.hadoop.ozone.shell.OzoneAddress;
@@ -39,22 +40,33 @@ public class UpdateVolumeHandler extends VolumeHandler {
       description = "Owner of the volume to set")
   private String ownerName;
 
-  @Option(names = {"--quota"},
-      description = "Quota of the volume to set"
-          + "(eg. 1G)")
-  private String quota;
+  @Option(names = {"--spaceQuota", "-sq"},
+      description = "Quota in bytes of the volume to set (eg. 1GB)")
+  private String quotaInBytes;
+
+  @Option(names = {"--bucketQuota", "-bq"},
+      description = "Bucket counts of the volume to set (eg. 5)")
+  private long quotaInCounts = OzoneConsts.QUOTA_RESET;
 
   @Override
   protected void execute(OzoneClient client, OzoneAddress address)
       throws IOException {
-
     String volumeName = address.getVolumeName();
-
     OzoneVolume volume = client.getObjectStore().getVolume(volumeName);
-    if (quota != null && !quota.isEmpty()) {
-      volume.setQuota(OzoneQuota.parseQuota(quota));
+
+    long spaceQuota = volume.getQuotaInBytes();
+    long countQuota = volume.getQuotaInCounts();
+
+    if (quotaInBytes != null && !quotaInBytes.isEmpty()) {
+      spaceQuota = OzoneQuota.parseQuota(quotaInBytes,
+          quotaInCounts).getQuotaInBytes();
+    }
+    if (quotaInCounts >= 0) {
+      countQuota = quotaInCounts;
     }
 
+    volume.setQuota(OzoneQuota.getOzoneQuota(spaceQuota, countQuota));
+
     if (ownerName != null && !ownerName.isEmpty()) {
       boolean result = volume.setOwner(ownerName);
       if (LOG.isDebugEnabled() && !result) {


---------------------------------------------------------------------
To unsubscribe, e-mail: ozone-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: ozone-commits-help@hadoop.apache.org