#include <linux/ptrace.h>
 #include <linux/nvme_ioctl.h>
 #include <linux/pm_qos.h>
+#include <linux/ratelimit.h>
 #include <asm/unaligned.h>
 
 #include "nvme.h"
        return status;
 }
 
-static int nvme_identify_ns(struct nvme_ctrl *ctrl, unsigned nsid,
+int nvme_identify_ns(struct nvme_ctrl *ctrl, unsigned nsid,
                        struct nvme_id_ns **id)
 {
        struct nvme_command c = { };
        blk_mq_freeze_queue(ns->disk->queue);
        lbaf = nvme_lbaf_index(id->flbas);
        ns->head->lba_shift = id->lbaf[lbaf].ds;
+       ns->head->nuse = le64_to_cpu(id->nuse);
        nvme_set_queue_limits(ns->ctrl, ns->queue);
 
        ret = nvme_configure_metadata(ns->ctrl, ns->head, id);
        head->ns_id = info->nsid;
        head->ids = info->ids;
        head->shared = info->is_shared;
+       ratelimit_state_init(&head->rs_nuse, 5 * HZ, 1);
+       ratelimit_set_flags(&head->rs_nuse, RATELIMIT_MSG_ON_RELEASE);
        kref_init(&head->ref);
 
        if (head->ids.csi) {
 
 #include <linux/rcupdate.h>
 #include <linux/wait.h>
 #include <linux/t10-pi.h>
+#include <linux/ratelimit_types.h>
 
 #include <trace/events/block.h>
 
        u16                     pi_size;
        u16                     sgs;
        u32                     sws;
+       u64                     nuse;
        u8                      pi_type;
        u8                      guard_type;
 #ifdef CONFIG_BLK_DEV_ZONED
 #endif
        unsigned long           features;
 
+       struct ratelimit_state  rs_nuse;
+
        struct cdev             cdev;
        struct device           cdev_device;
 
                unsigned int issue_flags);
 int nvme_ns_head_chr_uring_cmd(struct io_uring_cmd *ioucmd,
                unsigned int issue_flags);
+int nvme_identify_ns(struct nvme_ctrl *ctrl, unsigned nsid,
+               struct nvme_id_ns **id);
 int nvme_getgeo(struct block_device *bdev, struct hd_geometry *geo);
 int nvme_dev_uring_cmd(struct io_uring_cmd *ioucmd, unsigned int issue_flags);
 
 
 }
 static DEVICE_ATTR_RO(nsid);
 
+static ssize_t csi_show(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       return sysfs_emit(buf, "%u\n", dev_to_ns_head(dev)->ids.csi);
+}
+static DEVICE_ATTR_RO(csi);
+
+static ssize_t metadata_bytes_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       return sysfs_emit(buf, "%u\n", dev_to_ns_head(dev)->ms);
+}
+static DEVICE_ATTR_RO(metadata_bytes);
+
+static int ns_head_update_nuse(struct nvme_ns_head *head)
+{
+       struct nvme_id_ns *id;
+       struct nvme_ns *ns;
+       int srcu_idx, ret = -EWOULDBLOCK;
+
+       /* Avoid issuing commands too often by rate limiting the update */
+       if (!__ratelimit(&head->rs_nuse))
+               return 0;
+
+       srcu_idx = srcu_read_lock(&head->srcu);
+       ns = nvme_find_path(head);
+       if (!ns)
+               goto out_unlock;
+
+       ret = nvme_identify_ns(ns->ctrl, head->ns_id, &id);
+       if (ret)
+               goto out_unlock;
+
+       head->nuse = le64_to_cpu(id->nuse);
+       kfree(id);
+
+out_unlock:
+       srcu_read_unlock(&head->srcu, srcu_idx);
+       return ret;
+}
+
+static int ns_update_nuse(struct nvme_ns *ns)
+{
+       struct nvme_id_ns *id;
+       int ret;
+
+       /* Avoid issuing commands too often by rate limiting the update. */
+       if (!__ratelimit(&ns->head->rs_nuse))
+               return 0;
+
+       ret = nvme_identify_ns(ns->ctrl, ns->head->ns_id, &id);
+       if (ret)
+               goto out_free_id;
+
+       ns->head->nuse = le64_to_cpu(id->nuse);
+
+out_free_id:
+       kfree(id);
+
+       return ret;
+}
+
+static ssize_t nuse_show(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct nvme_ns_head *head = dev_to_ns_head(dev);
+       struct gendisk *disk = dev_to_disk(dev);
+       struct block_device *bdev = disk->part0;
+       int ret;
+
+       if (IS_ENABLED(CONFIG_NVME_MULTIPATH) &&
+           bdev->bd_disk->fops == &nvme_ns_head_ops)
+               ret = ns_head_update_nuse(head);
+       else
+               ret = ns_update_nuse(bdev->bd_disk->private_data);
+       if (ret)
+               return ret;
+
+       return sysfs_emit(buf, "%llu\n", head->nuse);
+}
+static DEVICE_ATTR_RO(nuse);
+
 static struct attribute *nvme_ns_attrs[] = {
        &dev_attr_wwid.attr,
        &dev_attr_uuid.attr,
        &dev_attr_nguid.attr,
        &dev_attr_eui.attr,
+       &dev_attr_csi.attr,
        &dev_attr_nsid.attr,
+       &dev_attr_metadata_bytes.attr,
+       &dev_attr_nuse.attr,
 #ifdef CONFIG_NVME_MULTIPATH
        &dev_attr_ana_grpid.attr,
        &dev_attr_ana_state.attr,