4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "nvme_internal.h"
36 static inline struct spdk_nvme_ns_data
*
37 _nvme_ns_get_data(struct spdk_nvme_ns
*ns
)
39 return &ns
->ctrlr
->nsdata
[ns
->id
- 1];
43 int nvme_ns_identify_update(struct spdk_nvme_ns
*ns
)
45 struct nvme_completion_poll_status status
;
46 struct spdk_nvme_ns_data
*nsdata
;
49 nsdata
= _nvme_ns_get_data(ns
);
51 rc
= nvme_ctrlr_cmd_identify_namespace(ns
->ctrlr
, ns
->id
, nsdata
,
52 nvme_completion_poll_cb
, &status
);
57 while (status
.done
== false) {
58 nvme_robust_mutex_lock(&ns
->ctrlr
->ctrlr_lock
);
59 spdk_nvme_qpair_process_completions(ns
->ctrlr
->adminq
, 0);
60 nvme_robust_mutex_unlock(&ns
->ctrlr
->ctrlr_lock
);
62 if (spdk_nvme_cpl_is_error(&status
.cpl
)) {
63 /* This can occur if the namespace is not active. Simply zero the
64 * namespace data and continue. */
65 memset(nsdata
, 0, sizeof(*nsdata
));
68 ns
->extended_lba_size
= 0;
71 ns
->sectors_per_max_io
= 0;
72 ns
->sectors_per_stripe
= 0;
79 ns
->sector_size
= 1 << nsdata
->lbaf
[nsdata
->flbas
.format
].lbads
;
80 ns
->extended_lba_size
= ns
->sector_size
;
82 ns
->md_size
= nsdata
->lbaf
[nsdata
->flbas
.format
].ms
;
83 if (nsdata
->flbas
.extended
) {
84 ns
->flags
|= SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED
;
85 ns
->extended_lba_size
+= ns
->md_size
;
88 ns
->sectors_per_max_io
= spdk_nvme_ns_get_max_io_xfer_size(ns
) / ns
->extended_lba_size
;
89 ns
->sectors_per_stripe
= ns
->stripe_size
/ ns
->sector_size
;
91 if (ns
->ctrlr
->cdata
.oncs
.dsm
) {
92 ns
->flags
|= SPDK_NVME_NS_DEALLOCATE_SUPPORTED
;
95 if (ns
->ctrlr
->cdata
.vwc
.present
) {
96 ns
->flags
|= SPDK_NVME_NS_FLUSH_SUPPORTED
;
99 if (ns
->ctrlr
->cdata
.oncs
.write_zeroes
) {
100 ns
->flags
|= SPDK_NVME_NS_WRITE_ZEROES_SUPPORTED
;
103 if (nsdata
->nsrescap
.raw
) {
104 ns
->flags
|= SPDK_NVME_NS_RESERVATION_SUPPORTED
;
107 ns
->pi_type
= SPDK_NVME_FMT_NVM_PROTECTION_DISABLE
;
108 if (nsdata
->lbaf
[nsdata
->flbas
.format
].ms
&& nsdata
->dps
.pit
) {
109 ns
->flags
|= SPDK_NVME_NS_DPS_PI_SUPPORTED
;
110 ns
->pi_type
= nsdata
->dps
.pit
;
116 spdk_nvme_ns_get_id(struct spdk_nvme_ns
*ns
)
122 spdk_nvme_ns_is_active(struct spdk_nvme_ns
*ns
)
124 const struct spdk_nvme_ns_data
*nsdata
= _nvme_ns_get_data(ns
);
127 * According to the spec, Identify Namespace will return a zero-filled structure for
128 * inactive namespace IDs.
129 * Check NCAP since it must be nonzero for an active namespace.
131 return nsdata
->ncap
!= 0;
135 spdk_nvme_ns_get_max_io_xfer_size(struct spdk_nvme_ns
*ns
)
137 return ns
->ctrlr
->max_xfer_size
;
141 spdk_nvme_ns_get_sector_size(struct spdk_nvme_ns
*ns
)
143 return ns
->sector_size
;
147 spdk_nvme_ns_get_num_sectors(struct spdk_nvme_ns
*ns
)
149 return _nvme_ns_get_data(ns
)->nsze
;
153 spdk_nvme_ns_get_size(struct spdk_nvme_ns
*ns
)
155 return spdk_nvme_ns_get_num_sectors(ns
) * spdk_nvme_ns_get_sector_size(ns
);
159 spdk_nvme_ns_get_flags(struct spdk_nvme_ns
*ns
)
164 enum spdk_nvme_pi_type
165 spdk_nvme_ns_get_pi_type(struct spdk_nvme_ns
*ns
) {
170 spdk_nvme_ns_supports_extended_lba(struct spdk_nvme_ns
*ns
)
172 return (ns
->flags
& SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED
) ? true : false;
176 spdk_nvme_ns_get_md_size(struct spdk_nvme_ns
*ns
)
181 const struct spdk_nvme_ns_data
*
182 spdk_nvme_ns_get_data(struct spdk_nvme_ns
*ns
)
184 nvme_ns_identify_update(ns
);
185 return _nvme_ns_get_data(ns
);
188 int nvme_ns_construct(struct spdk_nvme_ns
*ns
, uint16_t id
,
189 struct spdk_nvme_ctrlr
*ctrlr
)
197 if (ctrlr
->quirks
& NVME_INTEL_QUIRK_STRIPING
&&
198 ctrlr
->cdata
.vs
[3] != 0) {
199 ns
->stripe_size
= (1 << ctrlr
->cdata
.vs
[3]) * ctrlr
->min_page_size
;
202 return nvme_ns_identify_update(ns
);
205 void nvme_ns_destruct(struct spdk_nvme_ns
*ns
)