Merge ~ahasenack/ubuntu/+source/ndctl:ndctl-update-61.2 into ubuntu/+source/ndctl:ubuntu/devel

Proposed by Andreas Hasenack
Status: Merged
Merge reported by: Christian Ehrhardt 
Merged at revision: 47adf392aa25bc4fc06b633c2eb79c4e57771cb0
Proposed branch: ~ahasenack/ubuntu/+source/ndctl:ndctl-update-61.2
Merge into: ubuntu/+source/ndctl:ubuntu/devel
Diff against target: 4760 lines (+1911/-844)
63 files modified
.gitignore (+3/-0)
Documentation/asciidoctor-extensions.rb.in (+30/-0)
Documentation/daxctl/Makefile.am (+27/-2)
Documentation/daxctl/daxctl-list.txt (+7/-6)
Documentation/ndctl/Makefile.am (+27/-2)
Documentation/ndctl/namespace-description.txt (+50/-6)
Documentation/ndctl/ndctl-create-namespace.txt (+1/-0)
Documentation/ndctl/ndctl-disable-dimm.txt (+1/-1)
Documentation/ndctl/ndctl-enable-region.txt (+1/-1)
Documentation/ndctl/ndctl-init-labels.txt (+10/-5)
Documentation/ndctl/ndctl-inject-error.txt (+14/-0)
Documentation/ndctl/ndctl-list.txt (+8/-5)
Documentation/ndctl/ndctl-start-scrub.txt (+4/-2)
Documentation/ndctl/ndctl-wait-scrub.txt (+4/-2)
Makefile.am (+2/-1)
Makefile.am.in (+3/-3)
README.md (+61/-41)
autogen.sh (+1/-1)
configure.ac (+28/-3)
contrib/do_abidiff (+73/-0)
contrib/prepare-release.sh (+198/-0)
debian/changelog (+9/-0)
debian/control (+1/-1)
debian/libndctl6.symbols (+5/-0)
git-version (+1/-1)
ndctl/inject-error.c (+24/-16)
ndctl/lib/ars.c (+60/-26)
ndctl/lib/inject.c (+151/-50)
ndctl/lib/libndctl.c (+11/-4)
ndctl/lib/libndctl.sym (+8/-0)
ndctl/lib/private.h (+3/-0)
ndctl/libndctl.h (+12/-0)
ndctl/util/json-smart.c (+27/-0)
test.h (+12/-0)
test/Makefile.am (+20/-3)
test/blk-exhaust.sh (+11/-29)
test/btt-check.sh (+34/-53)
test/btt-errors.sh (+19/-31)
test/btt-pad-compat.sh (+35/-53)
test/clear.sh (+13/-33)
test/common (+83/-0)
test/create.sh (+16/-31)
test/dax-pmd.c (+25/-8)
test/dax-poison.c (+153/-0)
test/dax.sh (+14/-5)
test/daxdev-errors.sh (+14/-34)
test/device-dax.c (+19/-9)
test/dsm-fail.c (+254/-59)
test/firmware-update.sh (+12/-39)
test/inject-error.sh (+18/-37)
test/label-compat.sh (+9/-27)
test/libndctl.c (+10/-10)
test/multi-dax.sh (+11/-31)
test/pmem-errors.sh (+12/-27)
test/rescan-partitions.sh (+22/-46)
test/sector-mode.sh (+13/-26)
util/abspath.c (+29/-0)
util/filter.c (+104/-49)
util/help.c (+0/-5)
util/json.c (+27/-12)
util/parse-options.c (+41/-6)
util/parse-options.h (+9/-2)
util/util.h (+7/-0)
Reviewer Review Type Date Requested Status
Christian Ehrhardt  (community) Approve
Canonical Server Pending
Review via email: mp+349590@code.launchpad.net

Description of the change

Update to new upstream release 61.2

I bumped standards-version to 4.1.5, after going over the checklist at https://www.debian.org/doc/packaging-manuals/upgrading-checklist.txt. For the FHS version bump from 2.3 to 3.0, I used https://web.archive.org/web/20160624022300/wiki.linuxfoundation.org/en/FHSReleaseNotes30 and https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=787816 as pointers to what changed and determined this package is not affected.

Lintian output for ndctl 61.2-0ubuntu1, pedantic level: https://pastebin.ubuntu.com/p/TX4qfg3mg3/

https://launchpad.net/~ahasenack/+archive/ubuntu/nvdimm-update/+packages (ppa:ahasenack/nvdimm-update) has test packages.

DEP8 run with packages from the ppa: http://people.ubuntu.com/~ahasenack/dep8-cosmic-ndctl-61.2-ppa/

To post a comment you must log in.
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

The changes I see LGTM, I can't test build it on my own as with being a native package in Ubuntu there is no tarball at all yet on the review.
In general we should think about that case on the sprint, I'll take a note.

I tried to fetch the one from your ppa but that fails to buildpackage for a hell lot of diff of git to the tarball.
I got:
 4cc7c300703dc33a97608ae1f79512ff ../ndctl_61.2.orig.tar.gz
And Build against:
 037e8f8b4c84fd4ef30740c67f44f991291528f5 HEAD -> ndctl-update-61.2

Isn't that the same you have?

I might be too late on the versioning discussion (and I actually agree to the version).
But I saw "dpkg-source: warning: Version number suggests Ubuntu changes, but there is no XSBC-Original-Maintainer field"
Do you think we should extend that test to not report on -0ubuntu ?

TL;DR: Changes LGTM, some confusion on package details

review: Needs Information
Revision history for this message
Andreas Hasenack (ahasenack) wrote :

I'll check the orig tarball against the git content. Regarding versioning, I wouldn't want to make this a native package. There are other packages with a 0ubuntuN suffix, I just checked uvtool and it also doesn't have an original maintainer field in d/control, and doesn't exist in debian. I guess the warning has just been ignored in such cases.

22b52ab... by Andreas Hasenack

uupdate to 61.2

Revision history for this message
Andreas Hasenack (ahasenack) wrote :

Ok, as discussed in standup, my uupdate was incorrect as it added built files into the branch, files that are not part of the orig tarball. I don't know how the ppa build worked, but it was incorrect and thanks for catching it.

I fixed that and pushed --force. I'm about to run dep8 tests.

Revision history for this message
Andreas Hasenack (ahasenack) wrote :

Tests are good, ppa updated, dep8 results updated at http://people.ubuntu.com/~ahasenack/dep8-cosmic-ndctl-61.2-ppa/

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Thanks for fixing the built files!
It now also builds fine and LGTM.

If there is prio-art for the ignoring of the warning about Ubuntu versions without being a derivative then I'll be fine.

I tagged and pushed upload/61.2-0ubuntu1 but did not sponsor it yet as I wanted to be 100% sure that this is what should be sponsored. Obviously the tag can be move more easily as a bad-sponsored package content :-)

review: Approve
Revision history for this message
Andreas Hasenack (ahasenack) wrote :

The upload tag is pointing at the correct hash, please sponsor. Thanks!

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Done

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/.gitignore b/.gitignore
2index 20a04de..1016b3b 100644
3--- a/.gitignore
4+++ b/.gitignore
5@@ -15,6 +15,8 @@ Makefile.in
6 *.1
7 Documentation/daxctl/asciidoc.conf
8 Documentation/ndctl/asciidoc.conf
9+Documentation/daxctl/asciidoctor-extensions.rb
10+Documentation/ndctl/asciidoctor-extensions.rb
11 .dirstamp
12 daxctl/daxctl
13 daxctl/lib/libdaxctl.la
14@@ -53,3 +55,4 @@ test/smart-listen
15 test/smart-notify
16 test/fio.job
17 test/local-write-0-verify.state
18+test/ack-shutdown-count-set
19diff --git a/Documentation/asciidoctor-extensions.rb.in b/Documentation/asciidoctor-extensions.rb.in
20new file mode 100644
21index 0000000..a0307d0
22--- /dev/null
23+++ b/Documentation/asciidoctor-extensions.rb.in
24@@ -0,0 +1,30 @@
25+require 'asciidoctor'
26+require 'asciidoctor/extensions'
27+
28+module @Utility@
29+ module Documentation
30+ class Link@Utility@Processor < Asciidoctor::Extensions::InlineMacroProcessor
31+ use_dsl
32+
33+ named :chrome
34+
35+ def process(parent, target, attrs)
36+ if parent.document.basebackend? 'html'
37+ prefix = parent.document.attr('@utility@-relative-html-prefix')
38+ %(<a href="#{prefix}#{target}.html">#{target}(#{attrs[1]})</a>\n)
39+ elsif parent.document.basebackend? 'manpage'
40+ "#{target}(#{attrs[1]})"
41+ elsif parent.document.basebackend? 'docbook'
42+ "<citerefentry>\n" \
43+ "<refentrytitle>#{target}</refentrytitle>" \
44+ "<manvolnum>#{attrs[1]}</manvolnum>\n" \
45+ "</citerefentry>\n"
46+ end
47+ end
48+ end
49+ end
50+end
51+
52+Asciidoctor::Extensions.register do
53+ inline_macro @Utility@::Documentation::Link@Utility@Processor, :link@utility@
54+end
55diff --git a/Documentation/daxctl/Makefile.am b/Documentation/daxctl/Makefile.am
56index 259dafd..fc0fbe1 100644
57--- a/Documentation/daxctl/Makefile.am
58+++ b/Documentation/daxctl/Makefile.am
59@@ -9,11 +9,22 @@
60 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
61 # General Public License for more details.
62
63-do_subst = sed -e 's,UTILITY,daxctl,g'
64+if USE_ASCIIDOCTOR
65+
66+do_subst = sed -e 's,@Utility@,Daxctl,g' -e's,@utility@,daxctl,g'
67+CONFFILE = asciidoctor-extensions.rb
68+asciidoctor-extensions.rb: ../asciidoctor-extensions.rb.in
69+ $(AM_V_GEN) $(do_subst) < $< > $@
70
71+else
72+
73+do_subst = sed -e 's,UTILITY,daxctl,g'
74+CONFFILE = asciidoc.conf
75 asciidoc.conf: ../asciidoc.conf.in
76 $(AM_V_GEN) $(do_subst) < $< > $@
77
78+endif
79+
80 man1_MANS = \
81 daxctl.1 \
82 daxctl-list.1
83@@ -24,10 +35,22 @@ XML_DEPS = \
84 ../../version.m4 \
85 ../copyright.txt \
86 Makefile \
87- asciidoc.conf
88+ $(CONFFILE)
89
90 RM ?= rm -f
91
92+if USE_ASCIIDOCTOR
93+
94+%.1: %.txt $(XML_DEPS)
95+ $(AM_V_GEN)$(RM) $@+ $@ && \
96+ $(ASCIIDOC) -b manpage -d manpage -acompat-mode \
97+ -I. -rasciidoctor-extensions \
98+ -amansource=daxctl -amanmanual="daxctl Manual" \
99+ -andctl_version=$(VERSION) -o $@+ $< && \
100+ mv $@+ $@
101+
102+else
103+
104 %.xml: %.txt $(XML_DEPS)
105 $(AM_V_GEN)$(RM) $@+ $@ && \
106 $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
107@@ -37,3 +60,5 @@ RM ?= rm -f
108 %.1: %.xml $(XML_DEPS)
109 $(AM_V_GEN)$(RM) $@ && \
110 $(XMLTO) -o . -m ../manpage-normal.xsl man $<
111+
112+endif
113diff --git a/Documentation/daxctl/daxctl-list.txt b/Documentation/daxctl/daxctl-list.txt
114index 99ca4a1..cb82c3c 100644
115--- a/Documentation/daxctl/daxctl-list.txt
116+++ b/Documentation/daxctl/daxctl-list.txt
117@@ -1,7 +1,7 @@
118 // SPDX-License-Identifier: GPL-2.0
119
120 daxctl-list(1)
121-=============
122+==============
123
124 NAME
125 ----
126@@ -24,10 +24,9 @@ daxctl list --devices
127
128 EXAMPLE
129 -------
130-[verse]
131+----
132 # daxctl list --regions --devices
133
134-["literal"]
135 {
136 "id":1,
137 "devices":[
138@@ -37,6 +36,7 @@ EXAMPLE
139 }
140 ]
141 }
142+----
143
144 OPTIONS
145 -------
146@@ -54,14 +54,14 @@ OPTIONS
147 tuple, or keyword 'all' to filter the listing. For
148 example to list the first device instance in region1:
149
150-[verse]
151+----
152 # daxctl list --dev=1.0
153
154-["literal"]
155 {
156 "chardev":"dax1.0",
157 "size":3233808384
158 }
159+----
160
161 -D::
162 --devices::
163@@ -82,7 +82,7 @@ OPTIONS
164 will be formatted as human readable strings with units, other
165 fields are converted to hexadecimal strings. Example:
166
167-[verse]
168+----
169 # daxctl list
170 {
171 "chardev":"dax1.0",
172@@ -94,5 +94,6 @@ OPTIONS
173 "chardev":"dax1.0",
174 "size":"30.57 GiB (32.83 GB)"
175 }
176+----
177
178 include::../copyright.txt[]
179diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
180index fab05b9..4fd9636 100644
181--- a/Documentation/ndctl/Makefile.am
182+++ b/Documentation/ndctl/Makefile.am
183@@ -9,11 +9,22 @@
184 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
185 # General Public License for more details.
186
187-do_subst = sed -e 's,UTILITY,ndctl,g'
188+if USE_ASCIIDOCTOR
189+
190+do_subst = sed -e 's,@Utility@,Ndctl,g' -e's,@utility@,ndctl,g'
191+CONFFILE = asciidoctor-extensions.rb
192+asciidoctor-extensions.rb: ../asciidoctor-extensions.rb.in
193+ $(AM_V_GEN) $(do_subst) < $< > $@
194
195+else
196+
197+do_subst = sed -e 's,UTILITY,ndctl,g'
198+CONFFILE = asciidoc.conf
199 asciidoc.conf: ../asciidoc.conf.in
200 $(AM_V_GEN) $(do_subst) < $< > $@
201
202+endif
203+
204 man1_MANS = \
205 ndctl.1 \
206 ndctl-wait-scrub.1 \
207@@ -42,7 +53,7 @@ CLEANFILES = $(man1_MANS)
208 XML_DEPS = \
209 ../../version.m4 \
210 Makefile \
211- asciidoc.conf \
212+ $(CONFFILE) \
213 ../copyright.txt \
214 region-description.txt \
215 xable-region-options.txt \
216@@ -55,6 +66,18 @@ XML_DEPS = \
217
218 RM ?= rm -f
219
220+if USE_ASCIIDOCTOR
221+
222+%.1: %.txt $(XML_DEPS)
223+ $(AM_V_GEN)$(RM) $@+ $@ && \
224+ $(ASCIIDOC) -b manpage -d manpage -acompat-mode \
225+ -I. -rasciidoctor-extensions \
226+ -amansource=ndctl -amanmanual="ndctl Manual" \
227+ -andctl_version=$(VERSION) -o $@+ $< && \
228+ mv $@+ $@
229+
230+else
231+
232 %.xml: %.txt $(XML_DEPS)
233 $(AM_V_GEN)$(RM) $@+ $@ && \
234 $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
235@@ -64,3 +87,5 @@ RM ?= rm -f
236 %.1: %.xml $(XML_DEPS)
237 $(AM_V_GEN)$(RM) $@ && \
238 $(XMLTO) -o . -m ../manpage-normal.xsl man $<
239+
240+endif
241diff --git a/Documentation/ndctl/namespace-description.txt b/Documentation/ndctl/namespace-description.txt
242index 32ab5cd..1dd687e 100644
243--- a/Documentation/ndctl/namespace-description.txt
244+++ b/Documentation/ndctl/namespace-description.txt
245@@ -1,8 +1,52 @@
246 // SPDX-License-Identifier: GPL-2.0
247
248-DESCRIPTION
249------------
250-A REGION, after resolving DPA aliasing and LABEL specified boundaries,
251-surfaces one or more "namespace" devices. The arrival of a "namespace"
252-device currently triggers either the nd_blk or nd_pmem driver to load
253-and register a disk/block device.
254+THEORY OF OPERATION
255+-------------------
256+The capacity of an NVDIMM REGION (contiguous span of persistent memory)
257+is accessed via one or more NAMESPACE devices. REGION is the Linux term
258+for what ACPI and UEFI call a DIMM-interleave-set, or a
259+system-physical-address-range that is striped (by the memory controller)
260+across one or more memory modules.
261+
262+The UEFI specification defines the 'NVDIMM Label Protocol' as the
263+combination of label area access methods and a data format for
264+provisioning one or more NAMESPACE objects from a REGION. Note that
265+label support is optional and if Linux does not detect the label
266+capability it will automatically instantiate a "label-less" namespace
267+per region. Examples of label-less namespaces are the ones created by
268+the kernel's 'memmap=ss!nn' command line option (see the nvdimm wiki on
269+kernel.org), or NVDIMMs without a valid 'namespace index' in their label
270+area.
271+
272+A namespace can be provisioned to operate in one of 4 modes, 'fsdax',
273+'devdax', 'sector', and 'raw'. Here are the expected usage models for
274+these modes:
275+ - fsdax: Filesystem-DAX mode is the default mode of a namespace
276+ when specifying 'ndctl create-namespace' with no options. It creates
277+ a block device (/dev/pmemX[.Y]) that supports the DAX capabilities
278+ of Linux filesystems (xfs and ext4 to date). DAX removes the page
279+ cache from the I/O path and allows mmap(2) to establish direct
280+ mappings to persistent memory media. The DAX capability enables
281+ workloads / working-sets that would exceed the capacity of the page
282+ cache to scale up to the capacity of persistent memory. Workloads
283+ that fit in page cache or perform bulk data transfers may not see
284+ benefit from DAX. When in doubt, pick this mode.
285+
286+ - devdax: Device-DAX mode enables similar mmap(2) DAX mapping
287+ capabilities as Filesystem-DAX. However, instead of a block-device
288+ that can support a DAX-enabled filesystem, this mode emits a single
289+ character device file (/dev/daxX.Y). Use this mode to assign
290+ persistent memory to a virtual-machine, register persistent memory
291+ for RDMA, or when gigantic mappings are needed.
292+
293+ - sector: Use this mode to host legacy filesystems that do
294+ not checksum metadata or applications that are not prepared for torn
295+ sectors after a crash. Expected usage for this mode is for small
296+ boot volumes. This mode is compatible with other operating systems.
297+
298+ - raw: Raw mode is effectively just a memory disk that does
299+ not support DAX. Typically this indicates a namespace that was
300+ created by tooling or another operating system that did not know how
301+ to create a Linux 'fsdax' or 'devdax' mode namespace. This mode is
302+ compatible with other operating systems, but again, does not support
303+ DAX operation.
304diff --git a/Documentation/ndctl/ndctl-create-namespace.txt b/Documentation/ndctl/ndctl-create-namespace.txt
305index 14c5409..4b8b0d1 100644
306--- a/Documentation/ndctl/ndctl-create-namespace.txt
307+++ b/Documentation/ndctl/ndctl-create-namespace.txt
308@@ -219,3 +219,4 @@ linkndctl:ndctl-init-labels[1],
309 linkndctl:ndctl-disable-namespace[1],
310 linkndctl:ndctl-enable-namespace[1],
311 http://www.uefi.org/sites/default/files/resources/UEFI_Spec_2_7.pdf[UEFI NVDIMM Label Protocol]
312+https://nvdimm.wiki.kernel.org[Linux Persistent Memory Wiki]
313diff --git a/Documentation/ndctl/ndctl-disable-dimm.txt b/Documentation/ndctl/ndctl-disable-dimm.txt
314index d5a8d19..7706ac3 100644
315--- a/Documentation/ndctl/ndctl-disable-dimm.txt
316+++ b/Documentation/ndctl/ndctl-disable-dimm.txt
317@@ -1,7 +1,7 @@
318 // SPDX-License-Identifier: GPL-2.0
319
320 ndctl-disable-dimm(1)
321-=======================
322+=====================
323
324 NAME
325 ----
326diff --git a/Documentation/ndctl/ndctl-enable-region.txt b/Documentation/ndctl/ndctl-enable-region.txt
327index 6c4ad9f..e5cbddb 100644
328--- a/Documentation/ndctl/ndctl-enable-region.txt
329+++ b/Documentation/ndctl/ndctl-enable-region.txt
330@@ -1,7 +1,7 @@
331 // SPDX-License-Identifier: GPL-2.0
332
333 ndctl-enable-region(1)
334-====================
335+======================
336
337 NAME
338 ----
339diff --git a/Documentation/ndctl/ndctl-init-labels.txt b/Documentation/ndctl/ndctl-init-labels.txt
340index 580d82a..736d52d 100644
341--- a/Documentation/ndctl/ndctl-init-labels.txt
342+++ b/Documentation/ndctl/ndctl-init-labels.txt
343@@ -26,7 +26,7 @@ the DIMM.
344 EXAMPLE
345 -------
346 Find the DIMMs that comprise a given region:
347-[verse]
348+----
349 # ndctl list -RD --region=region1
350 {
351 "dimms":[
352@@ -51,23 +51,28 @@ Find the DIMMs that comprise a given region:
353 }
354 ]
355 }
356+----
357
358 Disable that region so the DIMM label area can be written from
359 userspace:
360-[verse]
361+----
362 # ndctl disable-region region1
363+----
364
365 Initialize labels:
366-[verse]
367+----
368 # ndctl init-labels nmem0
369+----
370
371 Re-enable the region:
372-[verse]
373+----
374 # ndctl enable-region region1
375+----
376
377 Create a namespace in that region:
378-[verse]
379+----
380 # ndctl create-namespace --region=region1
381+----
382
383 OPTIONS
384 -------
385diff --git a/Documentation/ndctl/ndctl-inject-error.txt b/Documentation/ndctl/ndctl-inject-error.txt
386index 94c4e69..744ea50 100644
387--- a/Documentation/ndctl/ndctl-inject-error.txt
388+++ b/Documentation/ndctl/ndctl-inject-error.txt
389@@ -18,6 +18,15 @@ ndctl-inject-error can be used to ask the platform to simulate media errors
390 in the NVDIMM address space to aid debugging and development of features
391 related to error handling.
392
393+By default, injecting an error actually only injects an error to the first 'n'
394+bytes of the block, where 'n' is the output of ndctl_cmd_ars_cap_get_size().
395+In other words, we only inject one 'ars_unit' per sector. This is sufficient
396+for Linux to mark the whole sector as bad, and will show up as such in the
397+various 'badblocks' lists in the kernel. If multiple blocks are being injected,
398+only the first 'n' bytes of each block specified will be injected as errors.
399+This can be overridden by the --saturate option, which will force the entire
400+block to be injected as an error.
401+
402 WARNING: These commands are DANGEROUS and can cause data loss. They are
403 only provided for testing and debugging purposes.
404
405@@ -88,6 +97,11 @@ OPTIONS
406 when the location is accessed. If the platform firmware does not
407 support this feature, this will have no effect.
408
409+-S::
410+--saturate::
411+ This option forces error injection or un-injection to cover the entire
412+ address range covered by the specified block(s).
413+
414 -v::
415 --verbose::
416 Emit debug messages for the error injection process
417diff --git a/Documentation/ndctl/ndctl-list.txt b/Documentation/ndctl/ndctl-list.txt
418index 2abc572..13ebdcd 100644
419--- a/Documentation/ndctl/ndctl-list.txt
420+++ b/Documentation/ndctl/ndctl-list.txt
421@@ -23,10 +23,9 @@ ndctl list --namespaces --bus=all --region=all
422
423 EXAMPLE
424 -------
425-[verse]
426+----
427 # ndctl list --buses --namespaces
428
429-["literal"]
430 {
431 "provider":"nfit_test.1",
432 "dev":"ndbus2",
433@@ -55,6 +54,7 @@ EXAMPLE
434 }
435 ]
436 }
437+----
438
439 OPTIONS
440 -------
441@@ -67,8 +67,9 @@ include::xable-region-options.txt[]
442 An 'nmemX' device name, or dimm id number. Filter listing by
443 devices that reference the given dimm. For example to see all
444 namespaces comprised of storage capacity on nmem0:
445-[verse]
446+----
447 # ndctl list --dimm=nmem0 --namespaces
448+----
449
450 -n::
451 --namespace=::
452@@ -201,7 +202,7 @@ include::xable-region-options.txt[]
453
454 include::human-option.txt[]
455
456-[verse]
457+----
458 # ndctl list --region=7
459 {
460 "dev":"region7",
461@@ -211,8 +212,9 @@ include::human-option.txt[]
462 "iset_id":-6382611090938810793,
463 "badblock_count":8
464 }
465+----
466
467-[verse]
468+----
469 # ndctl list --human --region=7
470 {
471 "dev":"region7",
472@@ -222,6 +224,7 @@ include::human-option.txt[]
473 "iset_id":"0xa76c6907811fae57",
474 "badblock_count":8
475 }
476+----
477
478 include::../copyright.txt[]
479
480diff --git a/Documentation/ndctl/ndctl-start-scrub.txt b/Documentation/ndctl/ndctl-start-scrub.txt
481index 365918d..eb49fc2 100644
482--- a/Documentation/ndctl/ndctl-start-scrub.txt
483+++ b/Documentation/ndctl/ndctl-start-scrub.txt
484@@ -24,7 +24,7 @@ EXAMPLE
485 -------
486 Start a scrub on all nvdimm buses in the system. The json listing report
487 only includes the buses that support ARS operations.
488-[verse]
489+----
490
491 # ndctl start-scrub
492 [
493@@ -39,12 +39,14 @@ only includes the buses that support ARS operations.
494 "scrub_state":"active"
495 }
496 ]
497+----
498
499 When specifying an individual bus, or if there is only one bus in the
500 system, the command reports whether ARS support is available.
501-[verse]
502+----
503 # ndctl start-scrub e820
504 error starting scrub: Operation not supported
505+----
506
507 OPTIONS
508 -------
509diff --git a/Documentation/ndctl/ndctl-wait-scrub.txt b/Documentation/ndctl/ndctl-wait-scrub.txt
510index 6b5f61f..9aef687 100644
511--- a/Documentation/ndctl/ndctl-wait-scrub.txt
512+++ b/Documentation/ndctl/ndctl-wait-scrub.txt
513@@ -25,7 +25,7 @@ EXAMPLE
514 -------
515 Wait for scrub on all nvdimm buses in the system. The json listing
516 report at the end only includes the buses that support ARS operations.
517-[verse]
518+----
519 # ndctl wait-scrub
520 [
521 {
522@@ -39,12 +39,14 @@ report at the end only includes the buses that support ARS operations.
523 "scrub_state":"idle"
524 }
525 ]
526+----
527
528 When specifying an individual bus, or if there is only one bus in the
529 system, the command reports whether ARS support is available.
530-[verse]
531+----
532 # ndctl wait-scrub e820
533 error waiting for scrub completion: Operation not supported
534+----
535
536 OPTIONS
537 -------
538diff --git a/Makefile.am b/Makefile.am
539index b538b1f..e0c463a 100644
540--- a/Makefile.am
541+++ b/Makefile.am
542@@ -69,6 +69,7 @@ libutil_a_SOURCES = \
543 util/strbuf.c \
544 util/wrapper.c \
545 util/filter.c \
546- util/bitmap.c
547+ util/bitmap.c \
548+ util/abspath.c
549
550 nobase_include_HEADERS = daxctl/libdaxctl.h
551diff --git a/Makefile.am.in b/Makefile.am.in
552index 8a7bb6f..a148490 100644
553--- a/Makefile.am.in
554+++ b/Makefile.am.in
555@@ -35,9 +35,9 @@ SED_PROCESS = \
556 -e 's,@includedir\@,$(includedir),g' \
557 < $< > $@ || rm $@
558
559-LIBNDCTL_CURRENT=15
560-LIBNDCTL_REVISION=0
561-LIBNDCTL_AGE=9
562+LIBNDCTL_CURRENT=16
563+LIBNDCTL_REVISION=1
564+LIBNDCTL_AGE=10
565
566 LIBDAXCTL_CURRENT=3
567 LIBDAXCTL_REVISION=0
568diff --git a/README.md b/README.md
569index 899dcbb..b4cf673 100644
570--- a/README.md
571+++ b/README.md
572@@ -5,11 +5,14 @@ sub-system in the Linux kernel
573
574 Build
575 =====
576-`./autogen.sh`
577-`./configure CFLAGS='-g -O0' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64`
578-`make`
579-`make check`
580-`sudo make install`
581+
582+```
583+./autogen.sh
584+./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
585+make
586+make check
587+sudo make install
588+```
589
590 There are a number of packages required for the build steps that may not
591 be installed by default. For information about the required packages,
592@@ -23,45 +26,56 @@ See the latest documentation for the NVDIMM kernel sub-system here:
593
594 https://git.kernel.org/cgit/linux/kernel/git/nvdimm/nvdimm.git/tree/Documentation/nvdimm/nvdimm.txt?h=libnvdimm-for-next
595
596+A getting started guide is also available on the kernel.org nvdimm wiki:
597+
598+https://nvdimm.wiki.kernel.org/start
599+
600 Unit Tests
601 ==========
602 The unit tests run by `make check` require the nfit_test.ko module to be
603 loaded. To build and install nfit_test.ko:
604
605 1. Obtain the kernel source. For example,
606-`git clone -b libnvdimm-for-next
607-git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git`
608+ `git clone -b libnvdimm-for-next git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git`
609
610-2. Skip to step 3 if the kernel version is >= v4.8. Otherwise, for
611+1. Skip to step 3 if the kernel version is >= v4.8. Otherwise, for
612 kernel versions < v4.8, configure the kernel to make some memory
613 available to CMA (contiguous memory allocator). This will be used to
614 emulate DAX.
615-`CONFIG_DMA_CMA=y`
616-`CONFIG_CMA_SIZE_MBYTES=200`
617-**or**
618-`cma=200M` on the kernel command line.
619+ ```
620+ CONFIG_DMA_CMA=y
621+ CONFIG_CMA_SIZE_MBYTES=200
622+ ```
623+ **or**
624+ `cma=200M` on the kernel command line.
625
626-3. Compile the libnvdimm sub-system as a module, make sure "zone device"
627+1. Compile the libnvdimm sub-system as a module, make sure "zone device"
628 memory is enabled, and enable the btt, pfn, and dax features of the
629 sub-system:
630-`CONFIG_X86_PMEM_LEGACY=m`
631-`CONFIG_ZONE_DEVICE=y`
632-`CONFIG_LIBNVDIMM=m`
633-`CONFIG_BLK_DEV_PMEM=m`
634-`CONFIG_ND_BLK=m`
635-`CONFIG_BTT=y`
636-`CONFIG_NVDIMM_PFN=y`
637-`CONFIG_NVDIMM_DAX=y`
638-`CONFIG_DEV_DAX_PMEM=m`
639-
640-4. Build and install the unit test enabled libnvdimm modules in the
641+
642+ ```
643+ CONFIG_X86_PMEM_LEGACY=m
644+ CONFIG_ZONE_DEVICE=y
645+ CONFIG_LIBNVDIMM=m
646+ CONFIG_BLK_DEV_PMEM=m
647+ CONFIG_ND_BLK=m
648+ CONFIG_BTT=y
649+ CONFIG_NVDIMM_PFN=y
650+ CONFIG_NVDIMM_DAX=y
651+ CONFIG_DEV_DAX_PMEM=m
652+ ```
653+
654+1. Build and install the unit test enabled libnvdimm modules in the
655 following order. The unit test modules need to be in place prior to
656 the `depmod` that runs during the final `modules_install`
657-`make M=tools/testing/nvdimm`
658-`sudo make M=tools/testing/nvdimm modules_install`
659-`sudo make modules_install`
660
661-5. Now run `make check` in the ndctl source directory, or `ndctl test`,
662+ ```
663+ make M=tools/testing/nvdimm
664+ sudo make M=tools/testing/nvdimm modules_install
665+ sudo make modules_install
666+ ```
667+
668+1. Now run `make check` in the ndctl source directory, or `ndctl test`,
669 if ndctl was built with `--enable-test`.
670
671 Troubleshooting
672@@ -73,23 +87,29 @@ test modules are not available, or the test versions of the modules are
673 superseded by the "in-tree/production" version of the modules `make
674 check` will skip tests and report a message like the following in
675 test/test-suite.log:
676-`SKIP: libndctl`
677-`==============`
678-`test/init: nfit_test_init: nfit.ko: appears to be production version: /lib/modules/4.8.8-200.fc24.x86_64/kernel/drivers/acpi/nfit/nfit.ko.xz`
679-`__ndctl_test_skip: explicit skip test_libndctl:2684`
680-`nfit_test unavailable skipping tests`
681+
682+```
683+SKIP: libndctl
684+==============
685+test/init: nfit_test_init: nfit.ko: appears to be production version: /lib/modules/4.8.8-200.fc24.x86_64/kernel/drivers/acpi/nfit/nfit.ko.xz
686+__ndctl_test_skip: explicit skip test_libndctl:2684
687+nfit_test unavailable skipping tests
688+```
689
690 If the unit test modules are indeed available in the modules 'extra'
691 directory the default depmod policy can be overridden by adding a file
692 to /etc/depmod.d with the following contents:
693-`override nfit * extra`
694-`override device_dax * extra`
695-`override dax_pmem * extra`
696-`override libnvdimm * extra`
697-`override nd_blk * extra`
698-`override nd_btt * extra`
699-`override nd_e820 * extra`
700-`override nd_pmem * extra`
701+
702+```
703+override nfit * extra
704+override device_dax * extra
705+override dax_pmem * extra
706+override libnvdimm * extra
707+override nd_blk * extra
708+override nd_btt * extra
709+override nd_e820 * extra
710+override nd_pmem * extra
711+```
712
713 The nfit_test module emulates pmem with memory allocated via vmalloc().
714 One of the side effects is that this breaks 'physically contiguous'
715diff --git a/autogen.sh b/autogen.sh
716index a23cf53..2a52688 100755
717--- a/autogen.sh
718+++ b/autogen.sh
719@@ -24,5 +24,5 @@ echo "----------------------------------------------------------------"
720 echo "Initialized build system. For a common configuration please run:"
721 echo "----------------------------------------------------------------"
722 echo
723-echo "./configure CFLAGS='-g -O0' $args"
724+echo "./configure CFLAGS='-g -O2' $args"
725 echo
726diff --git a/configure.ac b/configure.ac
727index 3eaac32..cf44260 100644
728--- a/configure.ac
729+++ b/configure.ac
730@@ -42,16 +42,29 @@ AS_IF([test "x$enable_docs" = "xyes"], [
731 ])
732 AM_CONDITIONAL([ENABLE_DOCS], [test "x$enable_docs" = "xyes"])
733
734-AC_CHECK_PROG(ASCIIDOC, [asciidoc], [$(which asciidoc)], [missing])
735+AC_ARG_ENABLE([asciidoctor],
736+ AS_HELP_STRING([--enable-asciidoctor],
737+ [use asciidoctor for documentation build]),
738+ [], enable_asciidoctor=no)
739+AM_CONDITIONAL([USE_ASCIIDOCTOR], [test "x$enable_asciidoctor" = "xyes"])
740+if test "x$enable_asciidoctor" = "xyes"; then
741+ asciidoc="asciidoctor"
742+else
743+ asciidoc="asciidoc"
744+fi
745+AC_CHECK_PROG(ASCIIDOC, [$asciidoc], [$(which $asciidoc)], [missing])
746 if test "x$ASCIIDOC" = xmissing -a "x$enable_docs" = "xyes"; then
747- AC_MSG_ERROR([asciidoc needed to build documentation])
748+ AC_MSG_ERROR([$asciidoc needed to build documentation])
749 fi
750 AC_SUBST([ASCIIDOC])
751+
752+if test x"$asciidoc" = x"asciidoc"; then
753 AC_CHECK_PROG(XMLTO, [xmlto], [$(which xmlto)], [missing])
754 if test "x$XMLTO" = xmissing -a "x$enable_docs" = "xyes"; then
755 AC_MSG_ERROR([xmlto needed to build documentation])
756 fi
757 AC_SUBST([XMLTO])
758+fi
759
760 AC_C_TYPEOF
761 AC_DEFINE([HAVE_STATEMENT_EXPR], 1, [Define to 1 if you have statement expressions.])
762@@ -89,6 +102,14 @@ AS_IF([test "x$enable_test" = "xyes"],
763 [AC_DEFINE([ENABLE_TEST], [1], [ndctl test support])])
764 AM_CONDITIONAL([ENABLE_TEST], [test "x$enable_test" = "xyes"])
765
766+AC_CHECK_DECLS([BUS_MCEERR_AR], [enable_bus_mc_err=yes], [], [[#include <signal.h>]])
767+AC_CHECK_DECLS([MAP_SYNC], [enable_map_sync=yes], [], [[#include <linux/mman.h>]])
768+
769+AS_IF([test "x$enable_bus_mc_err" = "xyes" -a "x$enable_map_sync" = "xyes"],
770+ [AC_DEFINE([ENABLE_POISON], [1], [ndctl test poison support])])
771+AM_CONDITIONAL([ENABLE_POISON],
772+ [test "x$enable_bus_mc_err" = "xyes" -a "x$enable_map_sync" = "xyes"])
773+
774 PKG_CHECK_MODULES([KMOD], [libkmod])
775 PKG_CHECK_MODULES([UDEV], [libudev])
776 PKG_CHECK_MODULES([UUID], [uuid])
777@@ -134,7 +155,11 @@ my_CFLAGS="\
778 -Wsign-compare \
779 -Wstrict-prototypes \
780 -Wtype-limits \
781--Wmaybe-uninitialized
782+-Wmaybe-uninitialized \
783+-Wdeclaration-after-statement \
784+-Wunused-result \
785+-D_FORTIFY_SOURCE=2 \
786+-O2
787 "
788 AC_SUBST([my_CFLAGS])
789
790diff --git a/contrib/do_abidiff b/contrib/do_abidiff
791new file mode 100755
792index 0000000..a520c3c
793--- /dev/null
794+++ b/contrib/do_abidiff
795@@ -0,0 +1,73 @@
796+#!/bin/bash -e
797+
798+range="$*"
799+old="${range%%..*}"
800+new="${range##*..}"
801+
802+err()
803+{
804+ echo "$1"
805+ exit 1
806+}
807+
808+build_rpm()
809+{
810+ local cur=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
811+ local ref="$1"
812+ local version=""
813+
814+ # prepare ndctl tree
815+ rm -rf results_ndctl
816+ git checkout -b rel_${ref} $ref
817+ ./autogen.sh
818+ ./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
819+ make clean
820+ make rhel/ndctl.spec
821+ cp rhel/ndctl.spec .
822+
823+ # build and copy RPMs
824+ version="$(./git-version)"
825+ git archive --format=tar --prefix="ndctl-${version}/" HEAD | gzip > ndctl-${version}.tar.gz
826+ fedpkg --release master --module-name ndctl mockbuild
827+ mkdir -p release/rel_${ref}/
828+ cp results_ndctl/*/*/*.x86_64.rpm release/rel_${ref}/
829+
830+ # restore ndctl branch and cleanup
831+ git checkout $cur
832+ git branch -D rel_${ref}
833+ rm ndctl-${version}.tar.gz
834+ rm ndctl-${version}*.src.rpm
835+ rm -rf results_ndctl
836+ rm -f ndctl.spec
837+}
838+
839+do_diff()
840+{
841+ local pkg="$1"
842+ local old_base="$(find . -regex "./release/rel_${old}/${pkg}-[0-9]+.*" | head -1)"
843+ local new_base="$(find . -regex "./release/rel_${new}/${pkg}-[0-9]+.*" | head -1)"
844+ local old_dev="$(find . -regex "./release/rel_${old}/${pkg}-devel-[0-9]+.*" | head -1)"
845+ local new_dev="$(find . -regex "./release/rel_${new}/${pkg}-devel-[0-9]+.*" | head -1)"
846+ local old_lib="$(find . -regex "./release/rel_${old}/${pkg}-libs-[0-9]+.*" | head -1)"
847+ local new_lib="$(find . -regex "./release/rel_${new}/${pkg}-libs-[0-9]+.*" | head -1)"
848+
849+ [ -n "$pkg" ] || err "specify a package for diff (ndctl, daxctl)"
850+
851+ abipkgdiff --dso-only --no-added-syms --harmless --drop-private-types \
852+ --devel1 "$old_dev" --devel2 "$new_dev" \
853+ "$old_base" "$new_base"
854+ abipkgdiff --no-added-syms --harmless --drop-private-types \
855+ --devel1 "$old_dev" --devel2 "$new_dev" \
856+ "$old_lib" "$new_lib"
857+}
858+
859+[ -e "COPYING" ] || err "Run from the top level of an ndctl tree"
860+if ! command -v "abipkgdiff" >/dev/null; then
861+ err "missing abipkgdiff. Please install libabigail"
862+fi
863+rm -rf release/rel*
864+
865+build_rpm $old > release/buildlog_$old 2>&1
866+build_rpm $new > release/buildlog_$new 2>&1
867+do_diff ndctl
868+do_diff daxctl
869diff --git a/contrib/prepare-release.sh b/contrib/prepare-release.sh
870new file mode 100755
871index 0000000..45be4d8
872--- /dev/null
873+++ b/contrib/prepare-release.sh
874@@ -0,0 +1,198 @@
875+#!/bin/bash -e
876+
877+# Arguments:
878+# fix - fixup release instead of a full release
879+# ignore_rev - ignore the check for _REVISION in libtool versioning checks
880+
881+# Notes:
882+# - Checkout to the appropriate branch beforehand
883+# master - for major release
884+# ndctl-xx.y - for fixup release
885+# This is important for generating the shortlog
886+# - Add a temporary commit that updates the libtool versions as needed.
887+# This will later become the release commit. Use --amend to add in the
888+# git-version update and the message body.
889+
890+# Pre-reqs:
891+# - libabigail (for abipkgdiff)
892+# - fedpkg (for mock build)
893+
894+# TODO
895+# - auto generate a release commit/tag message template
896+# - determine the most recent kernel release and add it to the above
897+# - perform documentation update for pmem.io/ndctl
898+
899+cleanup()
900+{
901+ rm -rf release
902+ mkdir release/
903+}
904+
905+err()
906+{
907+ echo "$1"
908+ exit 1
909+}
910+
911+parse_args()
912+{
913+ local args="$*"
914+ grep -q "fix" <<< "$args" && rel_fix="1" || rel_fix=""
915+ grep -q "ignore_rev" <<< "$args" && ignore_rev="1" || ignore_rev=""
916+}
917+
918+check_branch()
919+{
920+ local cur=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
921+ if [ -n "$rel_fix" ]; then
922+ # fixup release, expect ndctl-xx.y branch
923+ if ! grep -Eq "^ndctl.[0-9]+\.y$" <<< "$cur"; then
924+ err "expected an ndctl-xx.y branch for fixup release"
925+ fi
926+ else
927+ # major release, expect master branch
928+ if ! grep -Eq "^master$" <<< "$cur"; then
929+ err "expected master branch for a major release"
930+ fi
931+ fi
932+ if ! git diff-index --quiet HEAD --; then
933+ err "$cur has uncommitted/unstaged changes"
934+ fi
935+}
936+
937+last_maj()
938+{
939+ git tag | sort -V | grep -E "v[0-9]+$" | tail -1
940+}
941+
942+last_fix()
943+{
944+ local base="$1"
945+ git tag | sort -V | grep -E "$base\.?[0-9]*$" | tail -1
946+}
947+
948+next_maj()
949+{
950+ local last="$1"
951+ local num=${last#v}
952+
953+ newnum="$((num + 1))"
954+ echo "v$newnum"
955+}
956+
957+next_fix()
958+{
959+ local last="$1"
960+ local num=${last##*.}
961+ local base=${last%%.*}
962+
963+ newnum=$((num + 1))
964+ echo "$base.$newnum"
965+}
966+
967+gen_lists()
968+{
969+ local range="$1"
970+
971+ git shortlog "$range" > release/shortlog
972+ git log --pretty=format:"%s" "$range" > release/commits
973+ c_count=$(git log --pretty=format:"%s" "$range" | wc -l)
974+}
975+
976+# Check libtool versions in Makefile.am.in
977+# $1: lib name (currently libndctl or libdaxctl)
978+check_libtool_vers()
979+{
980+ local lib="$1"
981+ local lib_u="${lib^^}"
982+ local libdir="${lib##lib}"
983+ local symfile="${libdir}/lib/${lib}.sym"
984+ local last_cur=$(git show $last_ref:Makefile.am.in | grep -E "^${lib_u}_CURRENT" | cut -d'=' -f2)
985+ local last_rev=$(git show $last_ref:Makefile.am.in | grep -E "^${lib_u}_REVISION" | cut -d'=' -f2)
986+ local last_age=$(git show $last_ref:Makefile.am.in | grep -E "^${lib_u}_AGE" | cut -d'=' -f2)
987+ local last_soname=$((last_cur - last_age))
988+ local next_cur=$(git show HEAD:Makefile.am.in | grep -E "^${lib_u}_CURRENT" | cut -d'=' -f2)
989+ local next_rev=$(git show HEAD:Makefile.am.in | grep -E "^${lib_u}_REVISION" | cut -d'=' -f2)
990+ local next_age=$(git show HEAD:Makefile.am.in | grep -E "^${lib_u}_AGE" | cut -d'=' -f2)
991+ local next_soname=$((next_cur - next_age))
992+ local soname_diff=$((next_soname - last_soname))
993+
994+ # generally libtool versions either reset to zero or increase only by one
995+ # _CURRENT monotonically increases (by one)
996+ if [ "$((next_cur - last_cur))" -gt 1 ]; then
997+ err "${lib_u}_CURRENT can increase at most by 1"
998+ fi
999+ if [ "$next_rev" -ne 0 ]; then
1000+ if [ "$((next_rev - last_rev))" -gt 1 ]; then
1001+ err "${lib_u}_REVISION can increase at most by 1"
1002+ fi
1003+ fi
1004+ if [ "$next_age" -ne 0 ]; then
1005+ if [ "$((next_age - last_age))" -gt 1 ]; then
1006+ err "${lib_u}_AGE can increase at most by 1"
1007+ fi
1008+ fi
1009+
1010+ # test for soname change
1011+ if [ "$soname_diff" -ne 0 ]; then
1012+ err "${lib}: expected soname to stay unchanged"
1013+ fi
1014+
1015+ # tests based on whether symfile changed
1016+ # compatibility breaking changes are left for libabigail to detect
1017+ test -s "$symfile" || err "$symfile: not found"
1018+ if [ -n "$(git diff --name-only $last_ref..HEAD $symfile)" ]; then
1019+ # symfile has changed, cur and age should increase
1020+ if [ "$((next_cur - last_cur))" -ne 1 ]; then
1021+ err "based on $symfile, ${lib_u}_CURRENT should've increased by 1"
1022+ fi
1023+ if [ "$((next_age - last_age))" -ne 1 ]; then
1024+ err "based on $symfile, ${lib_u}_AGE should've increased by 1"
1025+ fi
1026+ else
1027+ # no changes to symfile, revision should've increased if source changed
1028+ if [ -n "$ignore_rev" ]; then
1029+ : # skip
1030+ elif [ -n "$(git diff --name-only $last_ref..HEAD $libdir/)" ]; then
1031+ if [ "$((next_rev - last_rev))" -ne 1 ]; then
1032+ err "based on $symfile, ${lib_u}_REVISION should've increased by 1"
1033+ fi
1034+ fi
1035+ fi
1036+}
1037+
1038+
1039+# main
1040+cleanup
1041+parse_args "$*"
1042+check_branch
1043+[ -e "COPYING" ] || err "Run from the top level of an ndctl tree"
1044+
1045+last_maj=$(last_maj)
1046+test -n "$last_maj" || err "Unable to determine last release"
1047+
1048+last_fix=$(last_fix $last_maj)
1049+test -n "$last_fix" || err "Unable to determine last fixup tag for $last_maj"
1050+
1051+next_maj=$(next_maj "$last_maj")
1052+next_fix=$(next_fix "$last_fix")
1053+[ -n "$rel_fix" ] && last_ref="$last_fix" || last_ref="$last_maj"
1054+[ -n "$rel_fix" ] && next_ref="$next_fix" || next_ref="$next_maj"
1055+
1056+check_libtool_vers "libndctl"
1057+check_libtool_vers "libdaxctl"
1058+
1059+gen_lists ${last_ref}..HEAD
1060+
1061+# For ABI diff purposes, use the latest fixes tag
1062+contrib/do_abidiff ${last_fix}..HEAD
1063+
1064+# once everything passes, update the git-version
1065+sed -i -e "s/DEF_VER=[0-9]\+.*/DEF_VER=${next_ref#v}/" git-version
1066+
1067+echo "Ready to release ndctl-$next_ref with $c_count new commits."
1068+echo "Add git-version to the top commit to get the updated version."
1069+echo "Use release/commits and release/shortlog to compose the release message"
1070+echo "The release commit typically contains the Makefile.am.in libtool version"
1071+echo "update, and the git-version update."
1072+echo "Finally, ensure the release commit as well as the tag are PGP signed."
1073diff --git a/debian/changelog b/debian/changelog
1074index 3185fb0..0996418 100644
1075--- a/debian/changelog
1076+++ b/debian/changelog
1077@@ -1,3 +1,12 @@
1078+ndctl (61.2-0ubuntu1) cosmic; urgency=medium
1079+
1080+ * New upstream release
1081+ * d/libndctl6.symbols: added new symbols for version 61.2
1082+ * d/control: updated Standards-Version to 4.1.5, no changes necessary.
1083+ Verified that the package isn't affected by the FHS 2.3->3.0 bump.
1084+
1085+ -- Andreas Hasenack <andreas@canonical.com> Thu, 12 Jul 2018 12:00:59 -0300
1086+
1087 ndctl (60.1-0ubuntu1) cosmic; urgency=medium
1088
1089 * Initial release. Closes: LP: #1752378.
1090diff --git a/debian/control b/debian/control
1091index b0617a4..c774907 100644
1092--- a/debian/control
1093+++ b/debian/control
1094@@ -11,7 +11,7 @@ Build-Depends: asciidoc,
1095 pkg-config,
1096 uuid-dev,
1097 xmlto
1098-Standards-Version: 4.1.4
1099+Standards-Version: 4.1.5
1100 Homepage: https://github.com/pmem/ndctl
1101 Vcs-Git: https://git.launchpad.net/ubuntu/+source/ndctl
1102 Vcs-Browser: https://code.launchpad.net/ubuntu/+source/ndctl/+git
1103diff --git a/debian/libndctl6.symbols b/debian/libndctl6.symbols
1104index 655be41..c4d186c 100644
1105--- a/debian/libndctl6.symbols
1106+++ b/debian/libndctl6.symbols
1107@@ -2,6 +2,7 @@ libndctl.so.6 libndctl6 #MINVER#
1108 LIBNDCTL_13@LIBNDCTL_13 60.1
1109 LIBNDCTL_14@LIBNDCTL_14 60.1
1110 LIBNDCTL_15@LIBNDCTL_15 60.1
1111+ LIBNDCTL_16@LIBNDCTL_16 61.2
1112 LIBNDCTL_1@LIBNDCTL_1 60.1
1113 LIBNDCTL_3@LIBNDCTL_3 60.1
1114 ndctl_bb_get_block@LIBNDCTL_14 60.1
1115@@ -55,12 +56,14 @@ libndctl.so.6 libndctl6 #MINVER#
1116 ndctl_bus_start_scrub@LIBNDCTL_15 60.1
1117 ndctl_bus_wait_for_scrub_completion@LIBNDCTL_14 60.1
1118 ndctl_bus_wait_probe@LIBNDCTL_3 60.1
1119+ ndctl_cmd_ars_cap_get_clear_unit@LIBNDCTL_16 61.2
1120 ndctl_cmd_ars_cap_get_range@LIBNDCTL_3 60.1
1121 ndctl_cmd_ars_cap_get_size@LIBNDCTL_3 60.1
1122 ndctl_cmd_ars_get_record_addr@LIBNDCTL_3 60.1
1123 ndctl_cmd_ars_get_record_len@LIBNDCTL_3 60.1
1124 ndctl_cmd_ars_in_progress@LIBNDCTL_3 60.1
1125 ndctl_cmd_ars_num_records@LIBNDCTL_3 60.1
1126+ ndctl_cmd_ars_stat_get_flag_overflow@LIBNDCTL_16 61.2
1127 ndctl_cmd_cfg_read_get_data@LIBNDCTL_3 60.1
1128 ndctl_cmd_cfg_read_get_size@LIBNDCTL_3 60.1
1129 ndctl_cmd_cfg_size_get_size@LIBNDCTL_3 60.1
1130@@ -259,6 +262,7 @@ libndctl.so.6 libndctl6 #MINVER#
1131 ndctl_namespace_get_type@LIBNDCTL_3 60.1
1132 ndctl_namespace_get_type_name@LIBNDCTL_3 60.1
1133 ndctl_namespace_get_uuid@LIBNDCTL_3 60.1
1134+ ndctl_namespace_inject_error2@LIBNDCTL_16 61.2
1135 ndctl_namespace_inject_error@LIBNDCTL_14 60.1
1136 ndctl_namespace_injection_get_first_bb@LIBNDCTL_14 60.1
1137 ndctl_namespace_injection_get_next_bb@LIBNDCTL_14 60.1
1138@@ -273,6 +277,7 @@ libndctl.so.6 libndctl6 #MINVER#
1139 ndctl_namespace_set_sector_size@LIBNDCTL_3 60.1
1140 ndctl_namespace_set_size@LIBNDCTL_3 60.1
1141 ndctl_namespace_set_uuid@LIBNDCTL_3 60.1
1142+ ndctl_namespace_uninject_error2@LIBNDCTL_16 61.2
1143 ndctl_namespace_uninject_error@LIBNDCTL_14 60.1
1144 ndctl_namespace_write_cache_is_enabled@LIBNDCTL_15 60.1
1145 ndctl_new@LIBNDCTL_1 60.1
1146diff --git a/git-version b/git-version
1147index 19983ff..acc1d78 100755
1148--- a/git-version
1149+++ b/git-version
1150@@ -19,7 +19,7 @@ dirty() {
1151 fi
1152 }
1153
1154-DEF_VER=60.1
1155+DEF_VER=61.2
1156
1157 LF='
1158 '
1159diff --git a/ndctl/inject-error.c b/ndctl/inject-error.c
1160index 32a58a5..2b2fec0 100644
1161--- a/ndctl/inject-error.c
1162+++ b/ndctl/inject-error.c
1163@@ -47,6 +47,7 @@ static struct parameters {
1164 bool clear;
1165 bool status;
1166 bool no_notify;
1167+ bool saturate;
1168 bool human;
1169 } param;
1170
1171@@ -54,8 +55,8 @@ static struct inject_ctx {
1172 u64 block;
1173 u64 count;
1174 unsigned int op_mask;
1175- unsigned long flags;
1176- bool notify;
1177+ unsigned long json_flags;
1178+ unsigned int inject_flags;
1179 } ictx;
1180
1181 #define BASE_OPTIONS() \
1182@@ -74,6 +75,8 @@ OPT_BOOLEAN('d', "uninject", &param.clear, \
1183 "un-inject a previously injected error"), \
1184 OPT_BOOLEAN('t', "status", &param.status, "get error injection status"), \
1185 OPT_BOOLEAN('N', "no-notify", &param.no_notify, "firmware should not notify OS"), \
1186+OPT_BOOLEAN('S', "saturate", &param.saturate, \
1187+ "inject full sector, not just 'ars_unit' bytes"), \
1188 OPT_BOOLEAN('u', "human", &param.human, "use human friendly number formats ")
1189
1190 static const struct option inject_options[] = {
1191@@ -92,9 +95,9 @@ static int inject_init(void)
1192 {
1193 if (!param.clear && !param.status) {
1194 ictx.op_mask |= 1 << OP_INJECT;
1195- ictx.notify = true;
1196+ ictx.inject_flags |= (1 << NDCTL_NS_INJECT_NOTIFY);
1197 if (param.no_notify)
1198- ictx.notify = false;
1199+ ictx.inject_flags &= ~(1 << NDCTL_NS_INJECT_NOTIFY);
1200 }
1201 if (param.clear) {
1202 if (param.status) {
1203@@ -104,7 +107,7 @@ static int inject_init(void)
1204 ictx.op_mask |= 1 << OP_CLEAR;
1205 }
1206 if (param.status) {
1207- if (param.block || param.count) {
1208+ if (param.block || param.count || param.saturate) {
1209 error("status is invalid with inject or uninject\n");
1210 return -EINVAL;
1211 }
1212@@ -144,7 +147,9 @@ static int inject_init(void)
1213 }
1214
1215 if (param.human)
1216- ictx.flags |= UTIL_JSON_HUMAN;
1217+ ictx.json_flags |= UTIL_JSON_HUMAN;
1218+ if (param.saturate)
1219+ ictx.inject_flags |= 1 << NDCTL_NS_INJECT_SATURATE;
1220
1221 return 0;
1222 }
1223@@ -152,14 +157,15 @@ static int inject_init(void)
1224 static int ns_errors_to_json(struct ndctl_namespace *ndns,
1225 unsigned int start_count)
1226 {
1227- unsigned long flags = ictx.flags | UTIL_JSON_MEDIA_ERRORS;
1228+ unsigned long json_flags = ictx.json_flags | UTIL_JSON_MEDIA_ERRORS;
1229 struct ndctl_bus *bus = ndctl_namespace_get_bus(ndns);
1230 struct json_object *jndns;
1231 unsigned int count;
1232 int rc, tmo = 30;
1233
1234 /* only wait for scrubs for the inject and notify case */
1235- if ((ictx.op_mask & (1 << OP_INJECT)) && ictx.notify) {
1236+ if ((ictx.op_mask & (1 << OP_INJECT)) &&
1237+ (ictx.inject_flags & (1 << NDCTL_NS_INJECT_NOTIFY))) {
1238 do {
1239 /* wait for a scrub to start */
1240 count = ndctl_bus_get_scrub_count(bus);
1241@@ -177,7 +183,7 @@ static int ns_errors_to_json(struct ndctl_namespace *ndns,
1242 }
1243 }
1244
1245- jndns = util_namespace_to_json(ndns, flags);
1246+ jndns = util_namespace_to_json(ndns, json_flags);
1247 if (jndns)
1248 printf("%s\n", json_object_to_json_string_ext(jndns,
1249 JSON_C_TO_STRING_PRETTY));
1250@@ -185,7 +191,7 @@ static int ns_errors_to_json(struct ndctl_namespace *ndns,
1251 }
1252
1253 static int inject_error(struct ndctl_namespace *ndns, u64 offset, u64 length,
1254- bool notify)
1255+ unsigned int flags)
1256 {
1257 struct ndctl_bus *bus = ndctl_namespace_get_bus(ndns);
1258 unsigned int scrub_count;
1259@@ -197,7 +203,7 @@ static int inject_error(struct ndctl_namespace *ndns, u64 offset, u64 length,
1260 return -ENXIO;
1261 }
1262
1263- rc = ndctl_namespace_inject_error(ndns, offset, length, notify);
1264+ rc = ndctl_namespace_inject_error2(ndns, offset, length, flags);
1265 if (rc) {
1266 fprintf(stderr, "Unable to inject error: %s (%d)\n",
1267 strerror(abs(rc)), rc);
1268@@ -207,11 +213,12 @@ static int inject_error(struct ndctl_namespace *ndns, u64 offset, u64 length,
1269 return ns_errors_to_json(ndns, scrub_count);
1270 }
1271
1272-static int uninject_error(struct ndctl_namespace *ndns, u64 offset, u64 length)
1273+static int uninject_error(struct ndctl_namespace *ndns, u64 offset, u64 length,
1274+ unsigned int flags)
1275 {
1276 int rc;
1277
1278- rc = ndctl_namespace_uninject_error(ndns, offset, length);
1279+ rc = ndctl_namespace_uninject_error2(ndns, offset, length, flags);
1280 if (rc) {
1281 fprintf(stderr, "Unable to uninject error: %s (%d)\n",
1282 strerror(abs(rc)), rc);
1283@@ -254,7 +261,7 @@ static int injection_status(struct ndctl_namespace *ndns)
1284
1285 block = ndctl_bb_get_block(bb);
1286 count = ndctl_bb_get_count(bb);
1287- jbb = util_badblock_rec_to_json(block, count, ictx.flags);
1288+ jbb = util_badblock_rec_to_json(block, count, ictx.json_flags);
1289 if (!jbb)
1290 break;
1291 json_object_array_add(jbbs, jbb);
1292@@ -280,13 +287,14 @@ static int err_inject_ns(struct ndctl_namespace *ndns)
1293 while (op_mask) {
1294 if (op_mask & (1 << OP_INJECT)) {
1295 rc = inject_error(ndns, ictx.block, ictx.count,
1296- ictx.notify);
1297+ ictx.inject_flags);
1298 if (rc)
1299 return rc;
1300 op_mask &= ~(1 << OP_INJECT);
1301 }
1302 if (op_mask & (1 << OP_CLEAR)) {
1303- rc = uninject_error(ndns, ictx.block, ictx.count);
1304+ rc = uninject_error(ndns, ictx.block, ictx.count,
1305+ ictx.inject_flags);
1306 if (rc)
1307 return rc;
1308 op_mask &= ~(1 << OP_CLEAR);
1309diff --git a/ndctl/lib/ars.c b/ndctl/lib/ars.c
1310index d53d898..c78e3bf 100644
1311--- a/ndctl/lib/ars.c
1312+++ b/ndctl/lib/ars.c
1313@@ -180,36 +180,61 @@ NDCTL_EXPORT int ndctl_cmd_ars_cap_get_range(struct ndctl_cmd *ars_cap,
1314 return -EINVAL;
1315 }
1316
1317+NDCTL_EXPORT unsigned int ndctl_cmd_ars_cap_get_clear_unit(
1318+ struct ndctl_cmd *ars_cap)
1319+{
1320+ struct ndctl_ctx *ctx = ndctl_bus_get_ctx(cmd_to_bus(ars_cap));
1321+
1322+ if (ars_cap->type == ND_CMD_ARS_CAP && ars_cap->status == 0) {
1323+ dbg(ctx, "clear_err_unit: %d\n",
1324+ ars_cap->ars_cap->clear_err_unit);
1325+ return ars_cap->ars_cap->clear_err_unit;
1326+ }
1327+
1328+ dbg(ctx, "invalid ars_cap\n");
1329+ return 0;
1330+}
1331+
1332+static bool __validate_ars_stat(struct ndctl_cmd *ars_stat)
1333+{
1334+ /*
1335+ * A positive status indicates an underrun, but that is fine since
1336+ * the firmware is not expected to completely fill the max_ars_out
1337+ * sized buffer.
1338+ */
1339+ if (ars_stat->type != ND_CMD_ARS_STATUS || ars_stat->status < 0)
1340+ return false;
1341+ if ((ndctl_cmd_get_firmware_status(ars_stat) & ARS_STATUS_MASK) != 0)
1342+ return false;
1343+ return true;
1344+}
1345+
1346+#define validate_ars_stat(ctx, ars_stat) \
1347+({ \
1348+ bool __valid = __validate_ars_stat(ars_stat); \
1349+ if (!__valid) \
1350+ dbg(ctx, "expected sucessfully completed ars_stat command\n"); \
1351+ __valid; \
1352+})
1353+
1354 NDCTL_EXPORT int ndctl_cmd_ars_in_progress(struct ndctl_cmd *cmd)
1355 {
1356 struct ndctl_ctx *ctx = ndctl_bus_get_ctx(cmd_to_bus(cmd));
1357
1358- if (cmd->type == ND_CMD_ARS_STATUS && cmd->status == 0) {
1359- if (cmd->ars_status->status == 1 << 16) {
1360- /*
1361- * If in-progress, invalidate the ndctl_cmd, so
1362- * that if we're called again without a fresh
1363- * ars_status command, we fail.
1364- */
1365- cmd->status = 1;
1366- return 1;
1367- }
1368+ if (!validate_ars_stat(ctx, cmd))
1369 return 0;
1370- }
1371
1372- dbg(ctx, "invalid ars_status\n");
1373- return 0;
1374+ return (ndctl_cmd_get_firmware_status(cmd) == 1 << 16);
1375 }
1376
1377 NDCTL_EXPORT unsigned int ndctl_cmd_ars_num_records(struct ndctl_cmd *ars_stat)
1378 {
1379 struct ndctl_ctx *ctx = ndctl_bus_get_ctx(cmd_to_bus(ars_stat));
1380
1381- if (ars_stat->type == ND_CMD_ARS_STATUS && ars_stat->status == 0)
1382- return ars_stat->ars_status->num_records;
1383+ if (!validate_ars_stat(ctx, ars_stat))
1384+ return 0;
1385
1386- dbg(ctx, "invalid ars_status\n");
1387- return 0;
1388+ return ars_stat->ars_status->num_records;
1389 }
1390
1391 NDCTL_EXPORT unsigned long long ndctl_cmd_ars_get_record_addr(
1392@@ -217,16 +242,15 @@ NDCTL_EXPORT unsigned long long ndctl_cmd_ars_get_record_addr(
1393 {
1394 struct ndctl_ctx *ctx = ndctl_bus_get_ctx(cmd_to_bus(ars_stat));
1395
1396+ if (!validate_ars_stat(ctx, ars_stat))
1397+ return 0;
1398+
1399 if (rec_index >= ars_stat->ars_status->num_records) {
1400 dbg(ctx, "invalid record index\n");
1401 return 0;
1402 }
1403
1404- if (ars_stat->type == ND_CMD_ARS_STATUS && ars_stat->status == 0)
1405- return ars_stat->ars_status->records[rec_index].err_address;
1406-
1407- dbg(ctx, "invalid ars_status\n");
1408- return 0;
1409+ return ars_stat->ars_status->records[rec_index].err_address;
1410 }
1411
1412 NDCTL_EXPORT unsigned long long ndctl_cmd_ars_get_record_len(
1413@@ -234,16 +258,26 @@ NDCTL_EXPORT unsigned long long ndctl_cmd_ars_get_record_len(
1414 {
1415 struct ndctl_ctx *ctx = ndctl_bus_get_ctx(cmd_to_bus(ars_stat));
1416
1417+ if (!validate_ars_stat(ctx, ars_stat))
1418+ return 0;
1419+
1420 if (rec_index >= ars_stat->ars_status->num_records) {
1421 dbg(ctx, "invalid record index\n");
1422 return 0;
1423 }
1424
1425- if (ars_stat->type == ND_CMD_ARS_STATUS && ars_stat->status == 0)
1426- return ars_stat->ars_status->records[rec_index].length;
1427+ return ars_stat->ars_status->records[rec_index].length;
1428+}
1429
1430- dbg(ctx, "invalid ars_status\n");
1431- return 0;
1432+NDCTL_EXPORT int ndctl_cmd_ars_stat_get_flag_overflow(
1433+ struct ndctl_cmd *ars_stat)
1434+{
1435+ struct ndctl_ctx *ctx = ndctl_bus_get_ctx(cmd_to_bus(ars_stat));
1436+
1437+ if (!validate_ars_stat(ctx, ars_stat))
1438+ return -EINVAL;
1439+
1440+ return !!(ars_stat->ars_status->flags & ND_ARS_STAT_FLAG_OVERFLOW);
1441 }
1442
1443 NDCTL_EXPORT struct ndctl_cmd *ndctl_bus_cmd_new_clear_error(
1444diff --git a/ndctl/lib/inject.c b/ndctl/lib/inject.c
1445index 8bfb5c9..f9da02d 100644
1446--- a/ndctl/lib/inject.c
1447+++ b/ndctl/lib/inject.c
1448@@ -89,90 +89,191 @@ static int translate_status(u32 status)
1449 return 0;
1450 }
1451
1452-NDCTL_EXPORT int ndctl_namespace_inject_error(struct ndctl_namespace *ndns,
1453- unsigned long long block, unsigned long long count, bool notify)
1454+static int ndctl_namespace_get_clear_unit(struct ndctl_namespace *ndns)
1455+{
1456+ struct ndctl_bus *bus = ndctl_namespace_get_bus(ndns);
1457+ struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
1458+ unsigned long long ns_offset, ns_size;
1459+ unsigned int clear_unit;
1460+ struct ndctl_cmd *cmd;
1461+ int rc;
1462+
1463+ ndctl_namespace_get_injection_bounds(ndns, &ns_offset,
1464+ &ns_size);
1465+ cmd = ndctl_bus_cmd_new_ars_cap(bus, ns_offset, ns_size);
1466+ rc = ndctl_cmd_submit(cmd);
1467+ if (rc) {
1468+ dbg(ctx, "Error submitting ars_cap: %d\n", rc);
1469+ return rc;
1470+ }
1471+ clear_unit = ndctl_cmd_ars_cap_get_clear_unit(cmd);
1472+ if (clear_unit == 0) {
1473+ dbg(ctx, "Got an invalid clear_err_unit from ars_cap\n");
1474+ return -EINVAL;
1475+ }
1476+
1477+ ndctl_cmd_unref(cmd);
1478+ return clear_unit;
1479+}
1480+
1481+static int ndctl_namespace_inject_one_error(struct ndctl_namespace *ndns,
1482+ unsigned long long block, unsigned int flags)
1483 {
1484 struct ndctl_bus *bus = ndctl_namespace_get_bus(ndns);
1485 struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
1486 struct nd_cmd_ars_err_inj *err_inj;
1487 struct nd_cmd_pkg *pkg;
1488 struct ndctl_cmd *cmd;
1489- int rc = -EOPNOTSUPP;
1490+ u64 offset, length;
1491+ int rc, clear_unit;
1492
1493- if (!ndctl_bus_has_error_injection(bus))
1494- return -EOPNOTSUPP;
1495+ rc = block_to_spa_offset(ndns, block, 1, &offset, &length);
1496+ if (rc)
1497+ return rc;
1498
1499- if (ndctl_bus_has_nfit(bus)) {
1500- u64 offset, length;
1501+ clear_unit = ndctl_namespace_get_clear_unit(ndns);
1502+ if (clear_unit < 0)
1503+ return clear_unit;
1504
1505- rc = block_to_spa_offset(ndns, block, count, &offset, &length);
1506- if (rc)
1507- return rc;
1508- cmd = ndctl_bus_cmd_new_err_inj(bus);
1509- if (!cmd)
1510- return -ENOMEM;
1511+ if (!(flags & (1 << NDCTL_NS_INJECT_SATURATE))) {
1512+ /* clamp injection length per block to the clear_unit */
1513+ if (length > (unsigned int)clear_unit)
1514+ length = clear_unit;
1515+ }
1516
1517- pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
1518- err_inj = (struct nd_cmd_ars_err_inj *)&pkg->nd_payload[0];
1519- err_inj->err_inj_spa_range_base = offset;
1520- err_inj->err_inj_spa_range_length = length;
1521- if (notify)
1522- err_inj->err_inj_options |=
1523- (1 << ND_ARS_ERR_INJ_OPT_NOTIFY);
1524+ cmd = ndctl_bus_cmd_new_err_inj(bus);
1525+ if (!cmd)
1526+ return -ENOMEM;
1527
1528- rc = ndctl_cmd_submit(cmd);
1529+ pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
1530+ err_inj = (struct nd_cmd_ars_err_inj *)&pkg->nd_payload[0];
1531+ err_inj->err_inj_spa_range_base = offset;
1532+ err_inj->err_inj_spa_range_length = length;
1533+ if (flags & (1 << NDCTL_NS_INJECT_NOTIFY))
1534+ err_inj->err_inj_options |=
1535+ (1 << ND_ARS_ERR_INJ_OPT_NOTIFY);
1536+
1537+ rc = ndctl_cmd_submit(cmd);
1538+ if (rc) {
1539+ dbg(ctx, "Error submitting command: %d\n", rc);
1540+ goto out;
1541+ }
1542+ rc = translate_status(err_inj->status);
1543+ out:
1544+ ndctl_cmd_unref(cmd);
1545+ return rc;
1546+}
1547+
1548+NDCTL_EXPORT int ndctl_namespace_inject_error2(struct ndctl_namespace *ndns,
1549+ unsigned long long block, unsigned long long count,
1550+ unsigned int flags)
1551+{
1552+ struct ndctl_bus *bus = ndctl_namespace_get_bus(ndns);
1553+ struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
1554+ unsigned long long i;
1555+ int rc = -EINVAL;
1556+
1557+ if (!ndctl_bus_has_error_injection(bus))
1558+ return -EOPNOTSUPP;
1559+ if (!ndctl_bus_has_nfit(bus))
1560+ return -EOPNOTSUPP;
1561+
1562+ for (i = 0; i < count; i++) {
1563+ rc = ndctl_namespace_inject_one_error(ndns, block + i, flags);
1564 if (rc) {
1565- dbg(ctx, "Error submitting command: %d\n", rc);
1566- goto out;
1567+ err(ctx, "Injection failed at block %llx\n",
1568+ block + i);
1569+ return rc;
1570 }
1571- rc = translate_status(err_inj->status);
1572- out:
1573- ndctl_cmd_unref(cmd);
1574 }
1575 return rc;
1576 }
1577
1578-NDCTL_EXPORT int ndctl_namespace_uninject_error(struct ndctl_namespace *ndns,
1579- unsigned long long block, unsigned long long count)
1580+NDCTL_EXPORT int ndctl_namespace_inject_error(struct ndctl_namespace *ndns,
1581+ unsigned long long block, unsigned long long count, bool notify)
1582+{
1583+ return ndctl_namespace_inject_error2(ndns, block, count,
1584+ notify ? (1 << NDCTL_NS_INJECT_NOTIFY) : 0);
1585+}
1586+
1587+static int ndctl_namespace_uninject_one_error(struct ndctl_namespace *ndns,
1588+ unsigned long long block, unsigned int flags)
1589 {
1590 struct ndctl_bus *bus = ndctl_namespace_get_bus(ndns);
1591 struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
1592 struct nd_cmd_ars_err_inj_clr *err_inj_clr;
1593 struct nd_cmd_pkg *pkg;
1594 struct ndctl_cmd *cmd;
1595- int rc = -EOPNOTSUPP;
1596+ u64 offset, length;
1597+ int rc, clear_unit;
1598
1599- if (!ndctl_bus_has_error_injection(bus))
1600- return -EOPNOTSUPP;
1601+ rc = block_to_spa_offset(ndns, block, 1, &offset, &length);
1602+ if (rc)
1603+ return rc;
1604
1605- if (ndctl_bus_has_nfit(bus)) {
1606- u64 offset, length;
1607+ clear_unit = ndctl_namespace_get_clear_unit(ndns);
1608+ if (clear_unit < 0)
1609+ return clear_unit;
1610
1611- rc = block_to_spa_offset(ndns, block, count, &offset, &length);
1612- if (rc)
1613- return rc;
1614- cmd = ndctl_bus_cmd_new_err_inj_clr(bus);
1615- if (!cmd)
1616- return -ENOMEM;
1617+ if (!(flags & (1 << NDCTL_NS_INJECT_SATURATE))) {
1618+ /* clamp injection length per block to the clear_unit */
1619+ if (length > (unsigned int)clear_unit)
1620+ length = clear_unit;
1621+ }
1622
1623- pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
1624- err_inj_clr =
1625- (struct nd_cmd_ars_err_inj_clr *)&pkg->nd_payload[0];
1626- err_inj_clr->err_inj_clr_spa_range_base = offset;
1627- err_inj_clr->err_inj_clr_spa_range_length = length;
1628+ cmd = ndctl_bus_cmd_new_err_inj_clr(bus);
1629+ if (!cmd)
1630+ return -ENOMEM;
1631
1632- rc = ndctl_cmd_submit(cmd);
1633+ pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
1634+ err_inj_clr =
1635+ (struct nd_cmd_ars_err_inj_clr *)&pkg->nd_payload[0];
1636+ err_inj_clr->err_inj_clr_spa_range_base = offset;
1637+ err_inj_clr->err_inj_clr_spa_range_length = length;
1638+
1639+ rc = ndctl_cmd_submit(cmd);
1640+ if (rc) {
1641+ dbg(ctx, "Error submitting command: %d\n", rc);
1642+ goto out;
1643+ }
1644+ rc = translate_status(err_inj_clr->status);
1645+ out:
1646+ ndctl_cmd_unref(cmd);
1647+ return rc;
1648+}
1649+
1650+NDCTL_EXPORT int ndctl_namespace_uninject_error2(struct ndctl_namespace *ndns,
1651+ unsigned long long block, unsigned long long count,
1652+ unsigned int flags)
1653+{
1654+ struct ndctl_bus *bus = ndctl_namespace_get_bus(ndns);
1655+ struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
1656+ unsigned long long i;
1657+ int rc = -EINVAL;
1658+
1659+ if (!ndctl_bus_has_error_injection(bus))
1660+ return -EOPNOTSUPP;
1661+ if (!ndctl_bus_has_nfit(bus))
1662+ return -EOPNOTSUPP;
1663+
1664+ for (i = 0; i < count; i++) {
1665+ rc = ndctl_namespace_uninject_one_error(ndns, block + i,
1666+ flags);
1667 if (rc) {
1668- dbg(ctx, "Error submitting command: %d\n", rc);
1669- goto out;
1670+ err(ctx, "Un-injection failed at block %llx\n",
1671+ block + i);
1672+ return rc;
1673 }
1674- rc = translate_status(err_inj_clr->status);
1675- out:
1676- ndctl_cmd_unref(cmd);
1677 }
1678 return rc;
1679 }
1680
1681+NDCTL_EXPORT int ndctl_namespace_uninject_error(struct ndctl_namespace *ndns,
1682+ unsigned long long block, unsigned long long count)
1683+{
1684+ return ndctl_namespace_uninject_error2(ndns, block, count, 0);
1685+}
1686+
1687 static int bb_add_record(struct list_head *h, u64 block, u64 count)
1688 {
1689 struct ndctl_bb *bb, *bb_iter, *bb_next, *bb_prev;
1690diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
1691index 59ea82a..47e005e 100644
1692--- a/ndctl/lib/libndctl.c
1693+++ b/ndctl/lib/libndctl.c
1694@@ -1243,12 +1243,19 @@ NDCTL_EXPORT int ndctl_bus_wait_for_scrub_completion(struct ndctl_bus *bus)
1695 break;
1696 }
1697 dbg(ctx, "poll wake: revents: %d\n", fds.revents);
1698- pread(fd, buf, 1, 0);
1699+ if (pread(fd, buf, 1, 0) == -1) {
1700+ rc = -errno;
1701+ break;
1702+ }
1703 fds.revents = 0;
1704 }
1705 }
1706
1707- dbg(ctx, "bus%d: scrub complete\n", ndctl_bus_get_id(bus));
1708+ if (rc == 0)
1709+ dbg(ctx, "bus%d: scrub complete\n", ndctl_bus_get_id(bus));
1710+ else
1711+ dbg(ctx, "bus%d: error waiting for scrub completion: %s\n",
1712+ ndctl_bus_get_id(bus), strerror(-rc));
1713 if (fd)
1714 close (fd);
1715 return rc;
1716@@ -3991,10 +3998,10 @@ static int __ndctl_namespace_set_write_cache(struct ndctl_namespace *ndns,
1717 {
1718 struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns);
1719 struct ndctl_pfn *pfn = ndctl_namespace_get_pfn(ndns);
1720+ char *path = ndns->ndns_buf;
1721 char buf[SYSFS_ATTR_SIZE];
1722 int len = ndns->buf_len;
1723 const char *bdev;
1724- char path[50];
1725
1726 if (state != 1 && state != 0)
1727 return -ENXIO;
1728@@ -4034,9 +4041,9 @@ NDCTL_EXPORT int ndctl_namespace_write_cache_is_enabled(
1729 struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns);
1730 struct ndctl_pfn *pfn = ndctl_namespace_get_pfn(ndns);
1731 int len = ndns->buf_len, wc;
1732+ char *path = ndns->ndns_buf;
1733 char buf[SYSFS_ATTR_SIZE];
1734 const char *bdev;
1735- char path[50];
1736
1737 if (pfn)
1738 bdev = ndctl_pfn_get_block_device(pfn);
1739diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
1740index 65e735f..e939993 100644
1741--- a/ndctl/lib/libndctl.sym
1742+++ b/ndctl/lib/libndctl.sym
1743@@ -359,3 +359,11 @@ global:
1744 ndctl_bus_start_scrub;
1745 ndctl_region_deep_flush;
1746 } LIBNDCTL_14;
1747+
1748+LIBNDCTL_16 {
1749+global:
1750+ ndctl_cmd_ars_cap_get_clear_unit;
1751+ ndctl_namespace_inject_error2;
1752+ ndctl_namespace_uninject_error2;
1753+ ndctl_cmd_ars_stat_get_flag_overflow;
1754+} LIBNDCTL_15;
1755diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
1756index 73bbeed..b756b74 100644
1757--- a/ndctl/lib/private.h
1758+++ b/ndctl/lib/private.h
1759@@ -278,6 +278,9 @@ struct ndctl_bb {
1760 struct list_node list;
1761 };
1762
1763+/* ars_status flags */
1764+#define ND_ARS_STAT_FLAG_OVERFLOW (1 << 0)
1765+
1766 struct ndctl_dimm_ops {
1767 const char *(*cmd_desc)(int);
1768 struct ndctl_cmd *(*new_smart)(struct ndctl_dimm *);
1769diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
1770index 498ae19..9270bae 100644
1771--- a/ndctl/libndctl.h
1772+++ b/ndctl/libndctl.h
1773@@ -209,6 +209,8 @@ struct ndctl_cmd *ndctl_bus_cmd_new_clear_error(unsigned long long address,
1774 unsigned long long len, struct ndctl_cmd *ars_cap);
1775 unsigned long long ndctl_cmd_clear_error_get_cleared(
1776 struct ndctl_cmd *clear_err);
1777+unsigned int ndctl_cmd_ars_cap_get_clear_unit(struct ndctl_cmd *ars_cap);
1778+int ndctl_cmd_ars_stat_get_flag_overflow(struct ndctl_cmd *ars_stat);
1779
1780 /*
1781 * Note: ndctl_cmd_smart_get_temperature is an alias for
1782@@ -478,9 +480,19 @@ int ndctl_namespace_get_numa_node(struct ndctl_namespace *ndns);
1783 int ndctl_namespace_inject_error(struct ndctl_namespace *ndns,
1784 unsigned long long block, unsigned long long count,
1785 bool notify);
1786+int ndctl_namespace_inject_error2(struct ndctl_namespace *ndns,
1787+ unsigned long long block, unsigned long long count,
1788+ unsigned int flags);
1789 int ndctl_namespace_uninject_error(struct ndctl_namespace *ndns,
1790 unsigned long long block, unsigned long long count);
1791+int ndctl_namespace_uninject_error2(struct ndctl_namespace *ndns,
1792+ unsigned long long block, unsigned long long count,
1793+ unsigned int flags);
1794 int ndctl_namespace_injection_status(struct ndctl_namespace *ndns);
1795+enum ndctl_namespace_inject_flags {
1796+ NDCTL_NS_INJECT_NOTIFY = 0,
1797+ NDCTL_NS_INJECT_SATURATE,
1798+};
1799
1800 struct ndctl_bb;
1801 unsigned long long ndctl_bb_get_block(struct ndctl_bb *bb);
1802diff --git a/ndctl/util/json-smart.c b/ndctl/util/json-smart.c
1803index 4020423..6a1f294 100644
1804--- a/ndctl/util/json-smart.c
1805+++ b/ndctl/util/json-smart.c
1806@@ -47,6 +47,18 @@ static void smart_threshold_to_json(struct ndctl_dimm *dimm,
1807 "temperature_threshold", jobj);
1808 }
1809
1810+ if (alarm_control & ND_SMART_CTEMP_TRIP) {
1811+ unsigned int temp;
1812+ double t;
1813+
1814+ temp = ndctl_cmd_smart_threshold_get_ctrl_temperature(cmd);
1815+ t = ndctl_decode_smart_temperature(temp);
1816+ jobj = json_object_new_double(t);
1817+ if (jobj)
1818+ json_object_object_add(jhealth,
1819+ "controller_temperature_threshold", jobj);
1820+ }
1821+
1822 if (alarm_control & ND_SMART_SPARE_TRIP) {
1823 unsigned int spares;
1824
1825@@ -109,6 +121,16 @@ struct json_object *util_dimm_health_to_json(struct ndctl_dimm *dimm)
1826 json_object_object_add(jhealth, "temperature_celsius", jobj);
1827 }
1828
1829+ if (flags & ND_SMART_CTEMP_VALID) {
1830+ unsigned int temp = ndctl_cmd_smart_get_ctrl_temperature(cmd);
1831+ double t = ndctl_decode_smart_temperature(temp);
1832+
1833+ jobj = json_object_new_double(t);
1834+ if (jobj)
1835+ json_object_object_add(jhealth,
1836+ "controller_temperature_celsius", jobj);
1837+ }
1838+
1839 if (flags & ND_SMART_SPARES_VALID) {
1840 unsigned int spares = ndctl_cmd_smart_get_spares(cmd);
1841
1842@@ -120,12 +142,17 @@ struct json_object *util_dimm_health_to_json(struct ndctl_dimm *dimm)
1843 if (flags & ND_SMART_ALARM_VALID) {
1844 unsigned int alarm_flags = ndctl_cmd_smart_get_alarm_flags(cmd);
1845 bool temp_flag = !!(alarm_flags & ND_SMART_TEMP_TRIP);
1846+ bool ctrl_temp_flag = !!(alarm_flags & ND_SMART_CTEMP_TRIP);
1847 bool spares_flag = !!(alarm_flags & ND_SMART_SPARE_TRIP);
1848
1849 jobj = json_object_new_boolean(temp_flag);
1850 if (jobj)
1851 json_object_object_add(jhealth, "alarm_temperature", jobj);
1852
1853+ jobj = json_object_new_boolean(ctrl_temp_flag);
1854+ if (jobj)
1855+ json_object_object_add(jhealth, "alarm_controller_temperature", jobj);
1856+
1857 jobj = json_object_new_boolean(spares_flag);
1858 if (jobj)
1859 json_object_object_add(jhealth, "alarm_spares", jobj);
1860diff --git a/test.h b/test.h
1861index 5f2d629..fa0c0cf 100644
1862--- a/test.h
1863+++ b/test.h
1864@@ -12,6 +12,8 @@
1865 */
1866 #ifndef __TEST_H__
1867 #define __TEST_H__
1868+#include <stdbool.h>
1869+
1870 struct ndctl_test;
1871 struct ndctl_ctx;
1872 struct ndctl_test *ndctl_test_new(unsigned int kver);
1873@@ -36,6 +38,16 @@ struct ndctl_ctx;
1874 int test_parent_uuid(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx);
1875 int test_multi_pmem(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx);
1876 int test_dax_directio(int dax_fd, unsigned long align, void *dax_addr, off_t offset);
1877+#ifdef ENABLE_POISON
1878+int test_dax_poison(struct ndctl_test *test, int dax_fd, unsigned long align,
1879+ void *dax_addr, off_t offset, bool fsdax);
1880+#else
1881+static inline int test_dax_poison(struct ndctl_test *test, int dax_fd,
1882+ unsigned long align, void *dax_addr, off_t offset, bool fsdax)
1883+{
1884+ return 0;
1885+}
1886+#endif
1887 int test_dpa_alloc(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx);
1888 int test_dsm_fail(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx);
1889 int test_libndctl(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx);
1890diff --git a/test/Makefile.am b/test/Makefile.am
1891index 496a663..cd451e9 100644
1892--- a/test/Makefile.am
1893+++ b/test/Makefile.am
1894@@ -69,9 +69,16 @@ libndctl_LDADD = $(LIBNDCTL_LIB) $(UUID_LIBS) $(KMOD_LIBS)
1895
1896 dsm_fail_SOURCES =\
1897 dsm-fail.c \
1898- $(testcore)
1899+ $(testcore) \
1900+ ../ndctl/namespace.c \
1901+ ../ndctl/check.c \
1902+ ../util/json.c
1903
1904-dsm_fail_LDADD = $(LIBNDCTL_LIB) $(KMOD_LIBS)
1905+dsm_fail_LDADD = $(LIBNDCTL_LIB) \
1906+ $(KMOD_LIBS) \
1907+ $(JSON_LIBS) \
1908+ $(UUID_LIBS) \
1909+ ../libutil.a
1910
1911 ack_shutdown_count_set_SOURCES =\
1912 ack-shutdown-count-set.c \
1913@@ -94,9 +101,12 @@ parent_uuid_LDADD = $(LIBNDCTL_LIB) $(UUID_LIBS) $(KMOD_LIBS)
1914 dax_dev_SOURCES = dax-dev.c $(testcore)
1915 dax_dev_LDADD = $(LIBNDCTL_LIB) $(KMOD_LIBS)
1916
1917-dax_pmd_SOURCES = dax-pmd.c
1918+dax_pmd_SOURCES = dax-pmd.c \
1919+ $(testcore)
1920+
1921 hugetlb_SOURCES = hugetlb.c \
1922 dax-pmd.c
1923+
1924 mmap_SOURCES = mmap.c
1925 dax_errors_SOURCES = dax-errors.c
1926 daxdev_errors_SOURCES = daxdev-errors.c \
1927@@ -111,6 +121,13 @@ device_dax_SOURCES = \
1928 ../ndctl/namespace.c \
1929 ../ndctl/check.c \
1930 ../util/json.c
1931+
1932+if ENABLE_POISON
1933+dax_pmd_SOURCES += dax-poison.c
1934+hugetlb_SOURCES += dax-poison.c
1935+device_dax_SOURCES += dax-poison.c
1936+endif
1937+
1938 device_dax_LDADD = \
1939 $(LIBNDCTL_LIB) \
1940 $(KMOD_LIBS) \
1941diff --git a/test/blk-exhaust.sh b/test/blk-exhaust.sh
1942index b6991f6..326ce73 100755
1943--- a/test/blk-exhaust.sh
1944+++ b/test/blk-exhaust.sh
1945@@ -11,49 +11,31 @@
1946 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1947 # General Public License for more details.
1948
1949-NDCTL="../ndctl/ndctl"
1950-BUS="-b nfit_test.0"
1951-BUS1="-b nfit_test.1"
1952-rc=77
1953-
1954 set -e
1955
1956-err() {
1957- echo "test/label-compat.sh: failed at line $1"
1958- exit $rc
1959-}
1960-
1961-check_min_kver()
1962-{
1963- local ver="$1"
1964- : "${KVER:=$(uname -r)}"
1965+rc=77
1966
1967- [ -n "$ver" ] || return 1
1968- [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
1969-}
1970+. ./common
1971
1972-check_min_kver "4.11" || { echo "kernel $KVER may lack blk-exhaustion fix"; exit $rc; }
1973+check_min_kver "4.11" || do_skip "may lack blk-exhaustion fix"
1974
1975-set -e
1976 trap 'err $LINENO' ERR
1977
1978 # setup (reset nfit_test dimms)
1979 modprobe nfit_test
1980-$NDCTL disable-region $BUS all
1981-$NDCTL zero-labels $BUS all
1982-$NDCTL enable-region $BUS all
1983+$NDCTL disable-region -b $NFIT_TEST_BUS0 all
1984+$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
1985+$NDCTL enable-region -b $NFIT_TEST_BUS0 all
1986
1987 # if the kernel accounting is correct we should be able to create two
1988 # pmem and two blk namespaces on nfit_test.0
1989 rc=1
1990-$NDCTL create-namespace $BUS -t pmem
1991-$NDCTL create-namespace $BUS -t pmem
1992-$NDCTL create-namespace $BUS -t blk -m raw
1993-$NDCTL create-namespace $BUS -t blk -m raw
1994+$NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem
1995+$NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem
1996+$NDCTL create-namespace -b $NFIT_TEST_BUS0 -t blk -m raw
1997+$NDCTL create-namespace -b $NFIT_TEST_BUS0 -t blk -m raw
1998
1999 # clearnup and exit
2000-$NDCTL disable-region $BUS all
2001-$NDCTL disable-region $BUS1 all
2002-modprobe -r nfit_test
2003+_cleanup
2004
2005 exit 0
2006diff --git a/test/btt-check.sh b/test/btt-check.sh
2007index 353d437..ceabee5 100755
2008--- a/test/btt-check.sh
2009+++ b/test/btt-check.sh
2010@@ -11,11 +11,6 @@
2011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2012 # General Public License for more details.
2013
2014-[ -f "../ndctl/ndctl" ] && [ -x "../ndctl/ndctl" ] && ndctl="../ndctl/ndctl"
2015-[ -f "./ndctl/ndctl" ] && [ -x "./ndctl/ndctl" ] && ndctl="./ndctl/ndctl"
2016-[ -z "$ndctl" ] && echo "Couldn't find an ndctl binary" && exit 1
2017-bus="nfit_test.0"
2018-json2var="s/[{}\",]//g; s/:/=/g"
2019 dev=""
2020 mode=""
2021 size=""
2022@@ -24,6 +19,8 @@ blockdev=""
2023 bs=4096
2024 rc=77
2025
2026+. ./common
2027+
2028 trap 'err $LINENO' ERR
2029
2030 # sample json:
2031@@ -36,43 +33,26 @@ trap 'err $LINENO' ERR
2032 # "blockdev":"pmem5s"
2033 # }
2034
2035-# $1: Line number
2036-# $2: exit code
2037-err()
2038-{
2039- [ -n "$2" ] && rc="$2"
2040- echo "test/btt-check: failed at line $1"
2041- exit "$rc"
2042-}
2043-
2044-check_min_kver()
2045-{
2046- local ver="$1"
2047- : "${KVER:=$(uname -r)}"
2048-
2049- [ -n "$ver" ] || return 1
2050- [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
2051-}
2052-
2053-check_min_kver "4.14" || { echo "kernel $KVER may not support badblocks clearing on pmem via btt"; exit $rc; }
2054+check_min_kver "4.14" || do_skip "may not support badblocks clearing on pmem via btt"
2055
2056 create()
2057 {
2058- json=$($ndctl create-namespace -b "$bus" -t pmem -m sector)
2059- eval "$(echo "$json" | sed -e "$json2var")"
2060- [ -n "$dev" ] || err "$LINENO" 2
2061- [ "$mode" = "sector" ] || err "$LINENO" 2
2062- [ -n "$size" ] || err "$LINENO" 2
2063- [ -n "$sector_size" ] || err "$LINENO" 2
2064- [ -n "$blockdev" ] || err "$LINENO" 2
2065- [ $size -gt 0 ] || err "$LINENO" 2
2066+ json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem -m sector)
2067+ rc=2
2068+ eval "$(echo "$json" | json2var)"
2069+ [ -n "$dev" ] || err "$LINENO"
2070+ [ "$mode" = "sector" ] || err "$LINENO"
2071+ [ -n "$size" ] || err "$LINENO"
2072+ [ -n "$sector_size" ] || err "$LINENO"
2073+ [ -n "$blockdev" ] || err "$LINENO"
2074+ [ $size -gt 0 ] || err "$LINENO"
2075 }
2076
2077 reset()
2078 {
2079- $ndctl disable-region -b "$bus" all
2080- $ndctl zero-labels -b "$bus" all
2081- $ndctl enable-region -b "$bus" all
2082+ $NDCTL disable-region -b $NFIT_TEST_BUS0 all
2083+ $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
2084+ $NDCTL enable-region -b $NFIT_TEST_BUS0 all
2085 }
2086
2087 # re-enable the BTT namespace, and do IO to it in an attempt to
2088@@ -93,25 +73,25 @@ test_normal()
2089 {
2090 echo "=== ${FUNCNAME[0]} ==="
2091 # disable the namespace
2092- $ndctl disable-namespace $dev
2093- $ndctl check-namespace $dev
2094- $ndctl enable-namespace $dev
2095+ $NDCTL disable-namespace $dev
2096+ $NDCTL check-namespace $dev
2097+ $NDCTL enable-namespace $dev
2098 post_repair_test
2099 }
2100
2101 test_force()
2102 {
2103 echo "=== ${FUNCNAME[0]} ==="
2104- $ndctl check-namespace --force $dev
2105+ $NDCTL check-namespace --force $dev
2106 post_repair_test
2107 }
2108
2109 set_raw()
2110 {
2111- $ndctl disable-namespace $dev
2112+ $NDCTL disable-namespace $dev
2113 echo -n "set raw_mode: "
2114 echo 1 | tee /sys/bus/nd/devices/$dev/force_raw
2115- $ndctl enable-namespace $dev
2116+ $NDCTL enable-namespace $dev
2117 raw_bdev="${blockdev%%s}"
2118 test -b /dev/$raw_bdev
2119 raw_size="$(cat /sys/bus/nd/devices/$dev/size)"
2120@@ -119,10 +99,10 @@ set_raw()
2121
2122 unset_raw()
2123 {
2124- $ndctl disable-namespace $dev
2125+ $NDCTL disable-namespace $dev
2126 echo -n "set raw_mode: "
2127 echo 0 | tee /sys/bus/nd/devices/$dev/force_raw
2128- $ndctl enable-namespace $dev
2129+ $NDCTL enable-namespace $dev
2130 raw_bdev=""
2131 }
2132
2133@@ -134,10 +114,10 @@ test_bad_info2()
2134 echo "wiping info2 block (offset = $seek blocks)"
2135 dd if=/dev/zero of=/dev/$raw_bdev bs=$bs count=1 seek=$seek
2136 unset_raw
2137- $ndctl disable-namespace $dev
2138- $ndctl check-namespace $dev 2>&1 | grep "info2 needs to be restored"
2139- $ndctl check-namespace --repair $dev
2140- $ndctl enable-namespace $dev
2141+ $NDCTL disable-namespace $dev
2142+ $NDCTL check-namespace $dev 2>&1 | grep "info2 needs to be restored"
2143+ $NDCTL check-namespace --repair $dev
2144+ $NDCTL enable-namespace $dev
2145 post_repair_test
2146 }
2147
2148@@ -148,10 +128,10 @@ test_bad_info()
2149 echo "wiping info block"
2150 dd if=/dev/zero of=/dev/$raw_bdev bs=$bs count=2 seek=0
2151 unset_raw
2152- $ndctl disable-namespace $dev
2153- $ndctl check-namespace $dev 2>&1 | grep -E "info block at offset .* needs to be restored"
2154- $ndctl check-namespace --repair $dev
2155- $ndctl enable-namespace $dev
2156+ $NDCTL disable-namespace $dev
2157+ $NDCTL check-namespace $dev 2>&1 | grep -E "info block at offset .* needs to be restored"
2158+ $NDCTL check-namespace --repair $dev
2159+ $NDCTL enable-namespace $dev
2160 post_repair_test
2161 }
2162
2163@@ -170,8 +150,8 @@ test_bitmap()
2164 dd if=/tmp/scribble of=/dev/$raw_bdev bs=$bs seek=$seek
2165 rm -f /tmp/scribble
2166 unset_raw
2167- $ndctl disable-namespace $dev
2168- $ndctl check-namespace $dev 2>&1 | grep "bitmap error"
2169+ $NDCTL disable-namespace $dev
2170+ $NDCTL check-namespace $dev 2>&1 | grep "bitmap error"
2171 # This is not repairable
2172 reset && create
2173 }
2174@@ -191,4 +171,5 @@ rc=1
2175 reset && create
2176 do_tests
2177 reset
2178+_cleanup
2179 exit 0
2180diff --git a/test/btt-errors.sh b/test/btt-errors.sh
2181index ecc1282..e9cc209 100755
2182--- a/test/btt-errors.sh
2183+++ b/test/btt-errors.sh
2184@@ -11,18 +11,15 @@
2185 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2186 # General Public License for more details.
2187
2188-NDCTL="../ndctl/ndctl"
2189-BUS="nfit_test.0"
2190 MNT=test_btt_mnt
2191 FILE=image
2192-json2var="s/[{}\",]//g; s/:/=/g"
2193 blockdev=""
2194 rc=77
2195
2196-err() {
2197- rc=1
2198- echo "test/btt-errors: failed at line $1"
2199+. ./common
2200
2201+cleanup()
2202+{
2203 rm -f $FILE
2204 rm -f $MNT/$FILE
2205 if [ -n "$blockdev" ]; then
2206@@ -31,16 +28,6 @@ err() {
2207 rc=77
2208 fi
2209 rmdir $MNT
2210- exit $rc
2211-}
2212-
2213-check_min_kver()
2214-{
2215- local ver="$1"
2216- : "${KVER:=$(uname -r)}"
2217-
2218- [ -n "$ver" ] || return 1
2219- [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
2220 }
2221
2222 force_raw()
2223@@ -59,24 +46,24 @@ force_raw()
2224 fi
2225 }
2226
2227-check_min_kver "4.15" || { echo "kernel $KVER may lack BTT error handling"; exit $rc; }
2228+check_min_kver "4.15" || do_skip "may lack BTT error handling"
2229
2230 set -e
2231 mkdir -p $MNT
2232-trap 'err $LINENO' ERR
2233+trap 'err $LINENO cleanup' ERR
2234
2235 # setup (reset nfit_test dimms)
2236 modprobe nfit_test
2237-$NDCTL disable-region -b "$BUS" all
2238-$NDCTL zero-labels -b "$BUS" all
2239-$NDCTL enable-region -b "$BUS" all
2240+$NDCTL disable-region -b $NFIT_TEST_BUS0 all
2241+$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
2242+$NDCTL enable-region -b $NFIT_TEST_BUS0 all
2243
2244 rc=1
2245
2246 # create a btt namespace and clear errors (if any)
2247 dev="x"
2248-json=$($NDCTL create-namespace -b "$BUS" -t pmem -m sector)
2249-eval "$(echo "$json" | sed -e "$json2var")"
2250+json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem -m sector)
2251+eval "$(echo "$json" | json2var)"
2252 [ $dev = "x" ] && echo "fail: $LINENO" && exit 1
2253
2254 force_raw 1
2255@@ -147,12 +134,12 @@ dd if=$MNT/$FILE of=/dev/null iflag=direct bs=4096 count=1
2256
2257 # reset everything to get a clean log
2258 if grep -q "$MNT" /proc/mounts; then umount $MNT; fi
2259-$NDCTL disable-region -b "$BUS" all
2260-$NDCTL zero-labels -b "$BUS" all
2261-$NDCTL enable-region -b "$BUS" all
2262+$NDCTL disable-region -b $NFIT_TEST_BUS0 all
2263+$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
2264+$NDCTL enable-region -b $NFIT_TEST_BUS0 all
2265 dev="x"
2266-json=$($NDCTL create-namespace -b "$BUS" -t pmem -m sector)
2267-eval "$(echo "$json" | sed -e "$json2var")"
2268+json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem -m sector)
2269+eval "$(echo "$json" | json2var)"
2270 [ $dev = "x" ] && echo "fail: $LINENO" && exit 1
2271
2272 # insert error at an arbitrary offset in the map (sector 0)
2273@@ -168,7 +155,8 @@ force_raw 0
2274 dd if=/dev/$blockdev of=/dev/null iflag=direct bs=4096 count=1 && err $LINENO || true
2275
2276 # done, exit
2277-$NDCTL disable-region -b "$BUS" all
2278-$NDCTL zero-labels -b "$BUS" all
2279-$NDCTL enable-region -b "$BUS" all
2280+$NDCTL disable-region -b $NFIT_TEST_BUS0 all
2281+$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
2282+$NDCTL enable-region -b $NFIT_TEST_BUS0 all
2283+_cleanup
2284 exit 0
2285diff --git a/test/btt-pad-compat.sh b/test/btt-pad-compat.sh
2286index 281a8e5..2c1f271 100755
2287--- a/test/btt-pad-compat.sh
2288+++ b/test/btt-pad-compat.sh
2289@@ -11,16 +11,13 @@
2290 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2291 # General Public License for more details.
2292
2293-[ -f "../ndctl/ndctl" ] && [ -x "../ndctl/ndctl" ] && ndctl="../ndctl/ndctl"
2294-[ -f "./ndctl/ndctl" ] && [ -x "./ndctl/ndctl" ] && ndctl="./ndctl/ndctl"
2295-[ -z "$ndctl" ] && echo "Couldn't find an ndctl binary" && exit 1
2296-bus="nfit_test.0"
2297-json2var="s/[{}\",]//g; s/:/=/g"
2298 dev=""
2299 size=""
2300 blockdev=""
2301 rc=77
2302
2303+. ./common
2304+
2305 trap 'err $LINENO' ERR
2306
2307 # sample json:
2308@@ -32,44 +29,27 @@ trap 'err $LINENO' ERR
2309 # "blockdev":"pmem7",
2310 #}
2311
2312-# $1: Line number
2313-# $2: exit code
2314-err()
2315-{
2316- [ -n "$2" ] && rc="$2"
2317- echo "test/btt-pad-compat.sh: failed at line $1"
2318- exit "$rc"
2319-}
2320-
2321-check_prereq()
2322-{
2323- if ! command -v "$1" >/dev/null; then
2324- echo "missing '$1', skipping.."
2325- exit "$rc"
2326- fi
2327-}
2328-
2329 create()
2330 {
2331- json=$($ndctl create-namespace -b "$bus" -t pmem -m sector)
2332- eval "$(echo "$json" | sed -e "$json2var")"
2333- [ -n "$dev" ] || err "$LINENO" 2
2334- [ -n "$size" ] || err "$LINENO" 2
2335- [ -n "$blockdev" ] || err "$LINENO" 2
2336- [ $size -gt 0 ] || err "$LINENO" 2
2337+ json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem -m sector)
2338+ rc=2
2339+ eval "$(echo "$json" | json2var)"
2340+ [ -n "$dev" ] || err "$LINENO"
2341+ [ -n "$size" ] || err "$LINENO"
2342+ [ -n "$blockdev" ] || err "$LINENO"
2343+ [ $size -gt 0 ] || err "$LINENO"
2344 bttdev=$(cat /sys/bus/nd/devices/$dev/holder)
2345- [ -n "$bttdev" ] || err "$LINENO" 2
2346+ [ -n "$bttdev" ] || err "$LINENO"
2347 if [ ! -e /sys/kernel/debug/btt/$bttdev/arena0/log_index_0 ]; then
2348- echo "kernel $(uname -r) seems to be missing the BTT compatibility fixes, skipping"
2349- exit 77
2350+ do_skip "seems to be missing the BTT compatibility fixes, skipping."
2351 fi
2352 }
2353
2354 reset()
2355 {
2356- $ndctl disable-region -b "$bus" all
2357- $ndctl zero-labels -b "$bus" all
2358- $ndctl enable-region -b "$bus" all
2359+ $NDCTL disable-region -b $NFIT_TEST_BUS0 all
2360+ $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
2361+ $NDCTL enable-region -b $NFIT_TEST_BUS0 all
2362 }
2363
2364 verify_idx()
2365@@ -105,16 +85,16 @@ cycle_ns()
2366 {
2367 local ns="$1"
2368
2369- $ndctl disable-namespace $ns
2370- $ndctl enable-namespace $ns
2371+ $NDCTL disable-namespace $ns
2372+ $NDCTL enable-namespace $ns
2373 }
2374
2375 force_raw()
2376 {
2377 raw="$1"
2378- $ndctl disable-namespace "$dev"
2379+ $NDCTL disable-namespace "$dev"
2380 echo "$raw" > "/sys/bus/nd/devices/$dev/force_raw"
2381- $ndctl enable-namespace "$dev"
2382+ $NDCTL enable-namespace "$dev"
2383 echo "Set $dev to raw mode: $raw"
2384 if [[ "$raw" == "1" ]]; then
2385 raw_bdev=${blockdev%s}
2386@@ -140,23 +120,24 @@ create_oldfmt_ns()
2387 # that supports a raw namespace with a 4K sector size, prior to
2388 # v4.13 raw namespaces are limited to 512-byte sector size.
2389 rc=77
2390- json=$($ndctl create-namespace -b "$bus" -s 64M -t pmem -m raw -l 4096 -u 00000000-0000-0000-0000-000000000000)
2391- rc=1
2392- eval "$(echo "$json" | sed -e "$json2var")"
2393- [ -n "$dev" ] || err "$LINENO" 2
2394- [ -n "$size" ] || err "$LINENO" 2
2395- [ $size -gt 0 ] || err "$LINENO" 2
2396+ json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -s 64M -t pmem -m raw -l 4096 -u 00000000-0000-0000-0000-000000000000)
2397+ rc=2
2398+ eval "$(echo "$json" | json2var)"
2399+ [ -n "$dev" ] || err "$LINENO"
2400+ [ -n "$size" ] || err "$LINENO"
2401+ [ $size -gt 0 ] || err "$LINENO"
2402
2403 # reconfig it to sector mode
2404- json=$($ndctl create-namespace -b "$bus" -e $dev -m sector --force)
2405- eval "$(echo "$json" | sed -e "$json2var")"
2406- [ -n "$dev" ] || err "$LINENO" 2
2407- [ -n "$size" ] || err "$LINENO" 2
2408- [ -n "$blockdev" ] || err "$LINENO" 2
2409- [ $size -gt 0 ] || err "$LINENO" 2
2410+ json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -e $dev -m sector --force)
2411+ eval "$(echo "$json" | json2var)"
2412+ [ -n "$dev" ] || err "$LINENO"
2413+ [ -n "$size" ] || err "$LINENO"
2414+ [ -n "$blockdev" ] || err "$LINENO"
2415+ [ $size -gt 0 ] || err "$LINENO"
2416 bttdev=$(cat /sys/bus/nd/devices/$dev/holder)
2417- [ -n "$bttdev" ] || err "$LINENO" 2
2418+ [ -n "$bttdev" ] || err "$LINENO"
2419
2420+ rc=1
2421 # copy old-padding-format btt image, and try to re-enable the resulting btt
2422 force_raw 1
2423 copy_xxd_img "/dev/$raw_bdev"
2424@@ -192,13 +173,13 @@ do_tests()
2425 verify_idx 0 2
2426
2427 # rewrite log using ndctl, verify conversion to new format
2428- $ndctl check-namespace --rewrite-log --repair --force --verbose $dev
2429+ $NDCTL check-namespace --rewrite-log --repair --force --verbose $dev
2430 do_random_io "/dev/$blockdev"
2431 cycle_ns "$dev"
2432 verify_idx 0 1
2433
2434 # check-namespace again to make sure everything is ok
2435- $ndctl check-namespace --force --verbose $dev
2436+ $NDCTL check-namespace --force --verbose $dev
2437
2438 # the old format btt metadata was created with a null parent uuid,
2439 # making it 'stickier' than a normally created btt. Be sure to clean
2440@@ -212,4 +193,5 @@ rc=1
2441 reset
2442 do_tests
2443 reset
2444+_cleanup
2445 exit 0
2446diff --git a/test/clear.sh b/test/clear.sh
2447index d64dd27..6cc43db 100755
2448--- a/test/clear.sh
2449+++ b/test/clear.sh
2450@@ -11,46 +11,28 @@
2451 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2452 # General Public License for more details.
2453
2454-DEV=""
2455-NDCTL="../ndctl/ndctl"
2456-BUS="-b nfit_test.0"
2457-BUS1="-b nfit_test.1"
2458-json2var="s/[{}\",]//g; s/:/=/g"
2459-rc=77
2460-
2461 set -e
2462
2463-err() {
2464- echo "test/clear: failed at line $1"
2465- exit $rc
2466-}
2467-
2468-check_min_kver()
2469-{
2470- local ver="$1"
2471- : "${KVER:=$(uname -r)}"
2472+rc=77
2473
2474- [ -n "$ver" ] || return 1
2475- [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
2476-}
2477+. ./common
2478
2479-check_min_kver "4.6" || { echo "kernel $KVER lacks clear poison support"; exit $rc; }
2480+check_min_kver "4.6" || do_skip "lacks clear poison support"
2481
2482-set -e
2483 trap 'err $LINENO' ERR
2484
2485 # setup (reset nfit_test dimms)
2486 modprobe nfit_test
2487-$NDCTL disable-region $BUS all
2488-$NDCTL zero-labels $BUS all
2489-$NDCTL enable-region $BUS all
2490+$NDCTL disable-region -b $NFIT_TEST_BUS0 all
2491+$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
2492+$NDCTL enable-region -b $NFIT_TEST_BUS0 all
2493
2494 rc=1
2495
2496 # create pmem
2497 dev="x"
2498-json=$($NDCTL create-namespace $BUS -t pmem -m raw)
2499-eval $(echo $json | sed -e "$json2var")
2500+json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem -m raw)
2501+eval $(echo $json | json2var)
2502 [ $dev = "x" ] && echo "fail: $LINENO" && exit 1
2503 [ $mode != "raw" ] && echo "fail: $LINENO" && exit 1
2504
2505@@ -71,7 +53,7 @@ sector_raw=$sector
2506
2507 # convert pmem to fsdax mode
2508 json=$($NDCTL create-namespace -m fsdax -f -e $dev)
2509-eval $(echo $json | sed -e "$json2var")
2510+eval $(echo $json | json2var)
2511 [ $mode != "fsdax" ] && echo "fail: $LINENO" && exit 1
2512
2513 # check for errors relative to the offset injected by the pfn device
2514@@ -88,10 +70,10 @@ if read sector len < /sys/block/$blockdev/badblocks; then
2515 echo "fail: $LINENO" && exit 1
2516 fi
2517
2518-if check_min_kver "4.9.0"; then
2519+if check_min_kver "4.9"; then
2520 # check for re-appearance of stale badblocks from poison_list
2521- $NDCTL disable-region $BUS all
2522- $NDCTL enable-region $BUS all
2523+ $NDCTL disable-region -b $NFIT_TEST_BUS0 all
2524+ $NDCTL enable-region -b $NFIT_TEST_BUS0 all
2525
2526 # since we have cleared the errors, a disable/reenable shouldn't bring them back
2527 if read sector len < /sys/block/$blockdev/badblocks; then
2528@@ -100,8 +82,6 @@ if check_min_kver "4.9.0"; then
2529 fi
2530 fi
2531
2532-$NDCTL disable-region $BUS all
2533-$NDCTL disable-region $BUS1 all
2534-modprobe -r nfit_test
2535+_cleanup
2536
2537 exit 0
2538diff --git a/test/common b/test/common
2539new file mode 100644
2540index 0000000..fb4e18e
2541--- /dev/null
2542+++ b/test/common
2543@@ -0,0 +1,83 @@
2544+
2545+# SPDX-License-Identifier: GPL-2.0
2546+# Copyright(c) 2018, FUJITSU LIMITED. All rights reserved.
2547+
2548+# Global variables
2549+
2550+# NDCTL
2551+#
2552+if [ -f "../ndctl/ndctl" ] && [ -x "../ndctl/ndctl" ]; then
2553+ export NDCTL=../ndctl/ndctl
2554+elif [ -f "./ndctl/ndctl" ] && [ -x "./ndctl/ndctl" ]; then
2555+ export NDCTL=./ndctl/ndctl
2556+else
2557+ echo "Couldn't find an ndctl binary"
2558+ exit 1
2559+fi
2560+
2561+# NFIT_TEST_BUS[01]
2562+#
2563+NFIT_TEST_BUS0=nfit_test.0
2564+NFIT_TEST_BUS1=nfit_test.1
2565+
2566+
2567+# Functions
2568+
2569+# err
2570+# $1: line number which error detected
2571+# $2: cleanup function (optional)
2572+#
2573+err()
2574+{
2575+ echo test/$(basename $0): failed at line $1
2576+ [ -n "$2" ] && "$2"
2577+ exit $rc
2578+}
2579+
2580+# check_min_kver
2581+# $1: Supported kernel version. format: X.Y
2582+#
2583+check_min_kver()
2584+{
2585+ local ver="$1"
2586+ : "${KVER:=$(uname -r)}"
2587+
2588+ [ -n "$ver" ] || return 1
2589+ [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
2590+}
2591+
2592+# do_skip
2593+# $1: Skip message
2594+#
2595+do_skip()
2596+{
2597+ echo kernel $(uname -r): $1
2598+ exit 77
2599+}
2600+
2601+# check_prereq
2602+# $1: command to check
2603+#
2604+check_prereq()
2605+{
2606+ if ! command -v "$1" >/dev/null; then
2607+ do_skip "missing $1, skipping..."
2608+ fi
2609+}
2610+
2611+# _cleanup
2612+#
2613+_cleanup()
2614+{
2615+ $NDCTL disable-region -b $NFIT_TEST_BUS0 all
2616+ $NDCTL disable-region -b $NFIT_TEST_BUS1 all
2617+ modprobe -r nfit_test
2618+}
2619+
2620+# json2var
2621+# stdin: json
2622+#
2623+json2var()
2624+{
2625+ sed -e "s/[{}\",]//g; s/:/=/g"
2626+}
2627diff --git a/test/create.sh b/test/create.sh
2628index 3f30d6e..8d78797 100755
2629--- a/test/create.sh
2630+++ b/test/create.sh
2631@@ -11,57 +11,40 @@
2632 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2633 # General Public License for more details.
2634
2635-DEV=""
2636-NDCTL="../ndctl/ndctl"
2637-BUS="-b nfit_test.0"
2638-json2var="s/[{}\",]//g; s/:/=/g"
2639-SECTOR_SIZE="4096"
2640-rc=77
2641-
2642 set -e
2643
2644-err() {
2645- echo "test/create: failed at line $1"
2646- exit $rc
2647-}
2648-
2649-check_min_kver()
2650-{
2651- local ver="$1"
2652- : "${KVER:=$(uname -r)}"
2653+SECTOR_SIZE="4096"
2654+rc=77
2655
2656- [ -n "$ver" ] || return 1
2657- [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
2658-}
2659+. ./common
2660
2661-check_min_kver "4.5" || { echo "kernel $KVER may lack namespace mode attribute"; exit $rc; }
2662+check_min_kver "4.5" || do_skip "may lack namespace mode attribute"
2663
2664-set -e
2665 trap 'err $LINENO' ERR
2666
2667 # setup (reset nfit_test dimms)
2668 modprobe nfit_test
2669-$NDCTL disable-region $BUS all
2670-$NDCTL zero-labels $BUS all
2671-$NDCTL enable-region $BUS all
2672+$NDCTL disable-region -b $NFIT_TEST_BUS0 all
2673+$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
2674+$NDCTL enable-region -b $NFIT_TEST_BUS0 all
2675
2676 rc=1
2677
2678 # create pmem
2679 dev="x"
2680-json=$($NDCTL create-namespace $BUS -t pmem -m raw)
2681-eval $(echo $json | sed -e "$json2var")
2682+json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem -m raw)
2683+eval $(echo $json | json2var )
2684 [ $dev = "x" ] && echo "fail: $LINENO" && exit 1
2685 [ $mode != "raw" ] && echo "fail: $LINENO" && exit 1
2686
2687 # convert pmem to fsdax mode
2688 json=$($NDCTL create-namespace -m fsdax -f -e $dev)
2689-eval $(echo $json | sed -e "$json2var")
2690+eval $(echo $json | json2var)
2691 [ $mode != "fsdax" ] && echo "fail: $LINENO" && exit 1
2692
2693 # convert pmem to sector mode
2694 json=$($NDCTL create-namespace -m sector -l $SECTOR_SIZE -f -e $dev)
2695-eval $(echo $json | sed -e "$json2var")
2696+eval $(echo $json | json2var)
2697 [ $sector_size != $SECTOR_SIZE ] && echo "fail: $LINENO" && exit 1
2698 [ $mode != "sector" ] && echo "fail: $LINENO" && exit 1
2699
2700@@ -70,15 +53,17 @@ $NDCTL destroy-namespace -f $dev
2701
2702 # create blk
2703 dev="x"
2704-json=$($NDCTL create-namespace $BUS -t blk -m raw -v)
2705-eval $(echo $json | sed -e "$json2var")
2706+json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t blk -m raw -v)
2707+eval $(echo $json | json2var)
2708 [ $dev = "x" ] && echo "fail: $LINENO" && exit 1
2709 [ $mode != "raw" ] && echo "fail: $LINENO" && exit 1
2710
2711 # convert blk to sector mode
2712 json=$($NDCTL create-namespace -m sector -l $SECTOR_SIZE -f -e $dev)
2713-eval $(echo $json | sed -e "$json2var")
2714+eval $(echo $json | json2var)
2715 [ $sector_size != $SECTOR_SIZE ] && echo "fail: $LINENO" && exit 1
2716 [ $mode != "sector" ] && echo "fail: $LINENO" && exit 1
2717
2718+_cleanup
2719+
2720 exit 0
2721diff --git a/test/dax-pmd.c b/test/dax-pmd.c
2722index 06fe522..8ed3e9b 100644
2723--- a/test/dax-pmd.c
2724+++ b/test/dax-pmd.c
2725@@ -12,6 +12,7 @@
2726 */
2727 #include <stdio.h>
2728 #include <unistd.h>
2729+#include <setjmp.h>
2730 #include <sys/mman.h>
2731 #include <linux/mman.h>
2732 #include <sys/types.h>
2733@@ -125,7 +126,10 @@ int test_dax_directio(int dax_fd, unsigned long align, void *dax_addr, off_t off
2734 rc = -ENXIO;
2735 }
2736 ((char *) buf)[0] = 0;
2737- pread(fd2, buf, 4096, 0);
2738+ if (pread(fd2, buf, 4096, 0) != 4096) {
2739+ faili(i);
2740+ rc = -ENXIO;
2741+ }
2742 if (strcmp(buf, "odirect data") != 0) {
2743 faili(i);
2744 rc = -ENXIO;
2745@@ -190,14 +194,15 @@ int test_dax_directio(int dax_fd, unsigned long align, void *dax_addr, off_t off
2746 }
2747
2748 /* test_pmd assumes that fd references a pre-allocated + dax-capable file */
2749-static int test_pmd(int fd)
2750+static int test_pmd(struct ndctl_test *test, int fd)
2751 {
2752- unsigned long long m_align, p_align;
2753+ unsigned long long m_align, p_align, pmd_off;
2754+ static const bool fsdax = true;
2755 struct fiemap_extent *ext;
2756+ void *base, *pmd_addr;
2757 struct fiemap *map;
2758 int rc = -ENXIO;
2759 unsigned long i;
2760- void *base;
2761
2762 if (fd < 0) {
2763 fail();
2764@@ -246,9 +251,15 @@ static int test_pmd(int fd)
2765 m_align = ALIGN(base, HPAGE_SIZE) - ((unsigned long) base);
2766 p_align = ALIGN(ext->fe_physical, HPAGE_SIZE) - ext->fe_physical;
2767
2768- rc = test_dax_directio(fd, HPAGE_SIZE, (char *) base + m_align,
2769- ext->fe_logical + p_align);
2770+ pmd_addr = (char *) base + m_align;
2771+ pmd_off = ext->fe_logical + p_align;
2772+ rc = test_dax_directio(fd, HPAGE_SIZE, pmd_addr, pmd_off);
2773+ if (rc)
2774+ goto err_directio;
2775+
2776+ rc = test_dax_poison(test, fd, HPAGE_SIZE, pmd_addr, pmd_off, fsdax);
2777
2778+ err_directio:
2779 err_extent:
2780 err_mmap:
2781 free(map);
2782@@ -257,14 +268,20 @@ static int test_pmd(int fd)
2783
2784 int __attribute__((weak)) main(int argc, char *argv[])
2785 {
2786+ struct ndctl_test *test = ndctl_test_new(0);
2787 int fd, rc;
2788
2789+ if (!test) {
2790+ fprintf(stderr, "failed to initialize test\n");
2791+ return EXIT_FAILURE;
2792+ }
2793+
2794 if (argc < 1)
2795 return -EINVAL;
2796
2797 fd = open(argv[1], O_RDWR);
2798- rc = test_pmd(fd);
2799+ rc = test_pmd(test, fd);
2800 if (fd >= 0)
2801 close(fd);
2802- return rc;
2803+ return ndctl_test_result(test, rc);
2804 }
2805diff --git a/test/dax-poison.c b/test/dax-poison.c
2806new file mode 100644
2807index 0000000..a25bf0b
2808--- /dev/null
2809+++ b/test/dax-poison.c
2810@@ -0,0 +1,153 @@
2811+/* SPDX-License-Identifier: GPL-2.0 */
2812+/* Copyright(c) 2018 Intel Corporation. All rights reserved. */
2813+#include <stdio.h>
2814+#include <unistd.h>
2815+#include <signal.h>
2816+#include <setjmp.h>
2817+#include <sys/mman.h>
2818+#include <linux/mman.h>
2819+#include <fcntl.h>
2820+#include <string.h>
2821+#include <errno.h>
2822+#include <sys/ioctl.h>
2823+#include <stdlib.h>
2824+#include <linux/fs.h>
2825+#include <test.h>
2826+#include <util/size.h>
2827+#include <stdbool.h>
2828+#include <linux/version.h>
2829+
2830+#define fail() fprintf(stderr, "%s: failed at: %d (%s)\n", \
2831+ __func__, __LINE__, strerror(errno))
2832+
2833+static sigjmp_buf sj_env;
2834+static int sig_mcerr_ao, sig_mcerr_ar, sig_count;
2835+
2836+static void sigbus_hdl(int sig, siginfo_t *si, void *ptr)
2837+{
2838+ switch (si->si_code) {
2839+ case BUS_MCEERR_AO:
2840+ fprintf(stderr, "%s: BUS_MCEERR_AO addr: %p len: %d\n",
2841+ __func__, si->si_addr, 1 << si->si_addr_lsb);
2842+ sig_mcerr_ao++;
2843+ break;
2844+ case BUS_MCEERR_AR:
2845+ fprintf(stderr, "%s: BUS_MCEERR_AR addr: %p len: %d\n",
2846+ __func__, si->si_addr, 1 << si->si_addr_lsb);
2847+ sig_mcerr_ar++;
2848+ break;
2849+ default:
2850+ sig_count++;
2851+ break;
2852+ }
2853+
2854+ siglongjmp(sj_env, 1);
2855+}
2856+
2857+int test_dax_poison(struct ndctl_test *test, int dax_fd, unsigned long align,
2858+ void *dax_addr, off_t offset, bool fsdax)
2859+{
2860+ unsigned char *addr = MAP_FAILED;
2861+ struct sigaction act;
2862+ unsigned x = x;
2863+ void *buf;
2864+ int rc;
2865+
2866+ if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 19, 0)))
2867+ return 77;
2868+
2869+ /*
2870+ * MADV_HWPOISON must be page aligned, and this routine assumes
2871+ * align is >= 8K
2872+ */
2873+ if (align < SZ_2M)
2874+ return 0;
2875+
2876+ if (posix_memalign(&buf, 4096, 4096) != 0)
2877+ return -ENOMEM;
2878+
2879+ memset(&act, 0, sizeof(act));
2880+ act.sa_sigaction = sigbus_hdl;
2881+ act.sa_flags = SA_SIGINFO;
2882+
2883+ if (sigaction(SIGBUS, &act, 0)) {
2884+ fail();
2885+ rc = -errno;
2886+ goto out;
2887+ }
2888+
2889+ /* dirty the block on disk to bypass the default zero page */
2890+ if (fsdax) {
2891+ rc = pwrite(dax_fd, buf, 4096, offset + align / 2);
2892+ if (rc < 4096) {
2893+ fail();
2894+ rc = -ENXIO;
2895+ goto out;
2896+ }
2897+ fsync(dax_fd);
2898+ }
2899+
2900+ addr = mmap(dax_addr, 2*align, PROT_READ|PROT_WRITE,
2901+ MAP_SHARED_VALIDATE|MAP_POPULATE|MAP_SYNC, dax_fd, offset);
2902+ if (addr == MAP_FAILED) {
2903+ fail();
2904+ rc = -errno;
2905+ goto out;
2906+ }
2907+
2908+ if (sigsetjmp(sj_env, 1)) {
2909+ if (sig_mcerr_ar) {
2910+ fprintf(stderr, "madvise triggered 'action required' sigbus\n");
2911+ goto clear_error;
2912+ } else if (sig_count) {
2913+ fail();
2914+ return -ENXIO;
2915+ }
2916+ }
2917+
2918+ rc = madvise(addr + align / 2, 4096, MADV_HWPOISON);
2919+ if (rc) {
2920+ fail();
2921+ rc = -errno;
2922+ goto out;
2923+ }
2924+
2925+ /* clear the error */
2926+clear_error:
2927+ if (!sig_mcerr_ar) {
2928+ fail();
2929+ rc = -ENXIO;
2930+ goto out;
2931+ }
2932+
2933+ if (!fsdax) {
2934+ rc = 0;
2935+ goto out;
2936+ }
2937+
2938+ rc = fallocate(dax_fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE,
2939+ offset + align / 2, 4096);
2940+ if (rc) {
2941+ fail();
2942+ rc = -errno;
2943+ goto out;
2944+ }
2945+
2946+ rc = pwrite(dax_fd, buf, 4096, offset + align / 2);
2947+ if (rc < 4096) {
2948+ fail();
2949+ rc = -ENXIO;
2950+ goto out;
2951+ }
2952+ fsync(dax_fd);
2953+
2954+ /* check that we can fault in the poison page */
2955+ x = *(volatile unsigned *) addr + align / 2;
2956+ rc = 0;
2957+
2958+out:
2959+ if (addr != MAP_FAILED)
2960+ munmap(addr, 2 * align);
2961+ free(buf);
2962+ return rc;
2963+}
2964diff --git a/test/dax.sh b/test/dax.sh
2965index e35f914..30fe167 100755
2966--- a/test/dax.sh
2967+++ b/test/dax.sh
2968@@ -28,6 +28,15 @@ err() {
2969 exit $rc
2970 }
2971
2972+run_test() {
2973+ if ! ./dax-pmd $MNT/$FILE; then
2974+ rc=$?
2975+ if [ $rc -ne 77 -a $rc -ne 0 ]; then
2976+ err
2977+ fi
2978+ fi
2979+}
2980+
2981 set -e
2982 mkdir -p $MNT
2983 trap 'err $LINENO' ERR
2984@@ -40,7 +49,7 @@ rc=1
2985 mkfs.ext4 /dev/$blockdev
2986 mount /dev/$blockdev $MNT -o dax
2987 fallocate -l 1GiB $MNT/$FILE
2988-./dax-pmd $MNT/$FILE
2989+run_test
2990 umount $MNT
2991
2992 # convert pmem to put the memmap on the device
2993@@ -52,7 +61,7 @@ eval $(echo $json | sed -e "$json2var")
2994 mkfs.ext4 /dev/$blockdev
2995 mount /dev/$blockdev $MNT -o dax
2996 fallocate -l 1GiB $MNT/$FILE
2997-./dax-pmd $MNT/$FILE
2998+run_test
2999 umount $MNT
3000
3001 json=$($NDCTL create-namespace -m raw -f -e $dev)
3002@@ -62,7 +71,7 @@ eval $(echo $json | sed -e "$json2var")
3003 mkfs.xfs -f /dev/$blockdev
3004 mount /dev/$blockdev $MNT -o dax
3005 fallocate -l 1GiB $MNT/$FILE
3006-./dax-pmd $MNT/$FILE
3007+run_test
3008 umount $MNT
3009
3010 # convert pmem to put the memmap on the device
3011@@ -73,7 +82,7 @@ eval $(echo $json | sed -e "$json2var")
3012 mkfs.xfs -f /dev/$blockdev
3013 mount /dev/$blockdev $MNT -o dax
3014 fallocate -l 1GiB $MNT/$FILE
3015-./dax-pmd $MNT/$FILE
3016+run_test
3017 umount $MNT
3018
3019 # revert namespace to raw mode
3020@@ -81,4 +90,4 @@ json=$($NDCTL create-namespace -m raw -f -e $dev)
3021 eval $(echo $json | sed -e "$json2var")
3022 [ $mode != "fsdax" ] && echo "fail: $LINENO" && exit 1
3023
3024-exit 0
3025+exit $rc
3026diff --git a/test/daxdev-errors.sh b/test/daxdev-errors.sh
3027index 0c8acf5..c5adb72 100755
3028--- a/test/daxdev-errors.sh
3029+++ b/test/daxdev-errors.sh
3030@@ -11,45 +11,28 @@
3031 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3032 # General Public License for more details.
3033
3034-DEV=""
3035-NDCTL="../ndctl/ndctl"
3036-DAXCTL="../daxctl/daxctl"
3037-BUS="-b nfit_test.0"
3038-BUS1="-b nfit_test.1"
3039-json2var="s/[{}\",]//g; s/:/=/g"
3040-rc=77
3041-
3042-err() {
3043- echo "test/daxdev-errors: failed at line $1"
3044- exit $rc
3045-}
3046+set -e
3047
3048-check_min_kver()
3049-{
3050- local ver="$1"
3051- : "${KVER:=$(uname -r)}"
3052+rc=77
3053
3054- [ -n "$ver" ] || return 1
3055- [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
3056-}
3057+. ./common
3058
3059-check_min_kver "4.12" || { echo "kernel $KVER lacks dax dev error handling"; exit $rc; }
3060+check_min_kver "4.12" || do_skip "lacks dax dev error handling"
3061
3062-set -e
3063 trap 'err $LINENO' ERR
3064
3065 # setup (reset nfit_test dimms)
3066 modprobe nfit_test
3067-$NDCTL disable-region $BUS all
3068-$NDCTL zero-labels $BUS all
3069-$NDCTL enable-region $BUS all
3070+$NDCTL disable-region -b $NFIT_TEST_BUS0 all
3071+$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
3072+$NDCTL enable-region -b $NFIT_TEST_BUS0 all
3073
3074 rc=1
3075
3076 query=". | sort_by(.available_size) | reverse | .[0].dev"
3077-region=$($NDCTL list $BUS -t pmem -Ri | jq -r "$query")
3078+region=$($NDCTL list -b $NFIT_TEST_BUS0 -t pmem -Ri | jq -r "$query")
3079
3080-json=$($NDCTL create-namespace $BUS -r $region -t pmem -m devdax -a 4096)
3081+json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -r $region -t pmem -m devdax -a 4096)
3082 chardev=$(echo $json | jq ". | select(.mode == \"devdax\") | .daxregion.devices[0].chardev")
3083
3084 #{
3085@@ -70,12 +53,12 @@ chardev=$(echo $json | jq ". | select(.mode == \"devdax\") | .daxregion.devices[
3086 # }
3087 #}
3088
3089-json1=$($NDCTL list $BUS --mode=devdax --namespaces)
3090-eval $(echo $json1 | sed -e "$json2var")
3091+json1=$($NDCTL list -b $NFIT_TEST_BUS0 --mode=devdax --namespaces)
3092+eval $(echo $json1 | json2var)
3093 nsdev=$dev
3094
3095-json1=$($NDCTL list $BUS)
3096-eval $(echo $json1 | sed -e "$json2var")
3097+json1=$($NDCTL list -b $NFIT_TEST_BUS0)
3098+eval $(echo $json1 | json2var)
3099 busdev=$dev
3100
3101 # inject errors in the middle of the namespace
3102@@ -98,9 +81,6 @@ if read sector len < /sys/bus/platform/devices/nfit_test.0/$busdev/$region/badbl
3103 fi
3104 [ -n "$sector" ] && echo "fail: $LINENO" && exit 1
3105
3106-# cleanup
3107-$NDCTL disable-region $BUS all
3108-$NDCTL disable-region $BUS1 all
3109-modprobe -r nfit_test
3110+_cleanup
3111
3112 exit 0
3113diff --git a/test/device-dax.c b/test/device-dax.c
3114index 0a42a32..dd92f9a 100644
3115--- a/test/device-dax.c
3116+++ b/test/device-dax.c
3117@@ -151,15 +151,6 @@ static int __test_device_dax(unsigned long align, int loglevel,
3118 struct daxctl_region *dax_region;
3119 char *buf, path[100], data[VERIFY_BUF_SIZE];
3120
3121- memset (&act, 0, sizeof(act));
3122- act.sa_sigaction = sigbus;
3123- act.sa_flags = SA_SIGINFO;
3124-
3125- if (sigaction(SIGBUS, &act, 0)) {
3126- perror("sigaction");
3127- return 1;
3128- }
3129-
3130 ndctl_set_log_priority(ctx, loglevel);
3131
3132 ndns = ndctl_get_test_dev(ctx);
3133@@ -276,6 +267,7 @@ static int __test_device_dax(unsigned long align, int loglevel,
3134 * otherwise not supported.
3135 */
3136 if (ndctl_test_attempt(test, KERNEL_VERSION(4, 9, 0))) {
3137+ static const bool devdax = false;
3138 int fd2;
3139
3140 rc = test_dax_directio(fd, align, NULL, 0);
3141@@ -285,6 +277,15 @@ static int __test_device_dax(unsigned long align, int loglevel,
3142 goto out;
3143 }
3144
3145+ fprintf(stderr, "%s: test dax poison\n",
3146+ ndctl_namespace_get_devname(ndns));
3147+ rc = test_dax_poison(test, fd, align, NULL, 0, devdax);
3148+ if (rc) {
3149+ fprintf(stderr, "%s: failed dax poison\n",
3150+ ndctl_namespace_get_devname(ndns));
3151+ goto out;
3152+ }
3153+
3154 fd2 = open("/proc/self/smaps", O_RDONLY);
3155 if (fd2 < 0) {
3156 fprintf(stderr, "%s: failed smaps open\n",
3157@@ -312,6 +313,15 @@ static int __test_device_dax(unsigned long align, int loglevel,
3158 goto out;
3159 }
3160
3161+ memset(&act, 0, sizeof(act));
3162+ act.sa_sigaction = sigbus;
3163+ act.sa_flags = SA_SIGINFO;
3164+ if (sigaction(SIGBUS, &act, 0)) {
3165+ perror("sigaction");
3166+ rc = EXIT_FAILURE;
3167+ goto out;
3168+ }
3169+
3170 /* test fault after device-dax instance disabled */
3171 if (sigsetjmp(sj_env, 1)) {
3172 /* got sigbus, success */
3173diff --git a/test/dsm-fail.c b/test/dsm-fail.c
3174index 90d3e07..6845f81 100644
3175--- a/test/dsm-fail.c
3176+++ b/test/dsm-fail.c
3177@@ -24,12 +24,13 @@
3178
3179 #include <ccan/array_size/array_size.h>
3180 #include <ndctl/libndctl.h>
3181+#include <builtin.h>
3182 #include <ndctl.h>
3183 #include <test.h>
3184
3185 #define DIMM_PATH "/sys/devices/platform/nfit_test.0/nfit_test_dimm/test_dimm0"
3186
3187-static void reset_bus(struct ndctl_bus *bus)
3188+static int reset_bus(struct ndctl_bus *bus)
3189 {
3190 struct ndctl_region *region;
3191 struct ndctl_dimm *dimm;
3192@@ -38,20 +39,154 @@ static void reset_bus(struct ndctl_bus *bus)
3193 ndctl_region_foreach(bus, region)
3194 ndctl_region_disable_invalidate(region);
3195
3196- ndctl_dimm_foreach(bus, dimm)
3197- ndctl_dimm_zero_labels(dimm);
3198+ ndctl_dimm_foreach(bus, dimm) {
3199+ if (!ndctl_dimm_read_labels(dimm))
3200+ return -ENXIO;
3201+ ndctl_dimm_disable(dimm);
3202+ ndctl_dimm_init_labels(dimm, NDCTL_NS_VERSION_1_2);
3203+ ndctl_dimm_enable(dimm);
3204+ }
3205
3206 /* set regions back to their default state */
3207 ndctl_region_foreach(bus, region)
3208 ndctl_region_enable(region);
3209+ return 0;
3210+}
3211+
3212+static int set_dimm_response(const char *dimm_path, int cmd, int error_code,
3213+ struct log_ctx *log_ctx)
3214+{
3215+ char path[1024], buf[SYSFS_ATTR_SIZE];
3216+ int rc;
3217+
3218+ if (error_code) {
3219+ sprintf(path, "%s/fail_cmd", dimm_path);
3220+ sprintf(buf, "%#x\n", 1 << cmd);
3221+ rc = __sysfs_write_attr(log_ctx, path, buf);
3222+ if (rc)
3223+ goto out;
3224+ sprintf(path, "%s/fail_cmd_code", dimm_path);
3225+ sprintf(buf, "%d\n", error_code);
3226+ rc = __sysfs_write_attr(log_ctx, path, buf);
3227+ if (rc)
3228+ goto out;
3229+ } else {
3230+ sprintf(path, "%s/fail_cmd", dimm_path);
3231+ sprintf(buf, "0\n");
3232+ rc = __sysfs_write_attr(log_ctx, path, buf);
3233+ if (rc)
3234+ goto out;
3235+ }
3236+out:
3237+ if (rc < 0)
3238+ fprintf(stderr, "%s failed, cmd: %d code: %d\n",
3239+ __func__, cmd, error_code);
3240+ return 0;
3241+}
3242+
3243+static int dimms_disable(struct ndctl_bus *bus)
3244+{
3245+ struct ndctl_dimm *dimm;
3246+
3247+ ndctl_dimm_foreach(bus, dimm) {
3248+ int rc = ndctl_dimm_disable(dimm);
3249+
3250+ if (rc) {
3251+ fprintf(stderr, "dimm: %s failed to disable: %d\n",
3252+ ndctl_dimm_get_devname(dimm), rc);
3253+ return rc;
3254+ }
3255+ }
3256+ return 0;
3257+}
3258+
3259+static int test_dimms_enable(struct ndctl_bus *bus, struct ndctl_dimm *victim,
3260+ bool expect)
3261+{
3262+ struct ndctl_dimm *dimm;
3263+
3264+ ndctl_dimm_foreach(bus, dimm) {
3265+ int rc = ndctl_dimm_enable(dimm);
3266+
3267+ if (((expect != (rc == 0)) && (dimm == victim))
3268+ || (rc && dimm != victim)) {
3269+ bool __expect = true;
3270+
3271+ if (dimm == victim)
3272+ __expect = expect;
3273+ fprintf(stderr, "fail expected %s enable %s victim: %s rc: %d\n",
3274+ ndctl_dimm_get_devname(dimm),
3275+ __expect ? "success" : "failure",
3276+ ndctl_dimm_get_devname(victim), rc);
3277+ return -ENXIO;
3278+ }
3279+ }
3280+ return 0;
3281+}
3282+
3283+static int test_regions_enable(struct ndctl_bus *bus,
3284+ struct ndctl_dimm *victim, struct ndctl_region *victim_region,
3285+ bool region_expect, int namespace_count)
3286+{
3287+ struct ndctl_region *region;
3288+
3289+ ndctl_region_foreach(bus, region) {
3290+ struct ndctl_namespace *ndns;
3291+ struct ndctl_dimm *dimm;
3292+ bool has_victim = false;
3293+ int rc, count = 0;
3294+
3295+ ndctl_dimm_foreach_in_region(region, dimm) {
3296+ if (dimm == victim) {
3297+ has_victim = true;
3298+ break;
3299+ }
3300+ }
3301+
3302+ rc = ndctl_region_enable(region);
3303+ fprintf(stderr, "region: %s enable: %d has_victim: %d\n",
3304+ ndctl_region_get_devname(region), rc, has_victim);
3305+ if (((region_expect != (rc == 0)) && has_victim)
3306+ || (rc && !has_victim)) {
3307+ bool __expect = true;
3308+
3309+ if (has_victim)
3310+ __expect = region_expect;
3311+ fprintf(stderr, "%s: fail expected enable: %s with %s\n",
3312+ ndctl_region_get_devname(region),
3313+ __expect ? "success" : "failure",
3314+ ndctl_dimm_get_devname(victim));
3315+ return -ENXIO;
3316+ }
3317+ if (region != victim_region)
3318+ continue;
3319+ ndctl_namespace_foreach(region, ndns) {
3320+ if (ndctl_namespace_is_enabled(ndns)) {
3321+ fprintf(stderr, "%s: enabled, expected disabled\n",
3322+ ndctl_namespace_get_devname(ndns));
3323+ return -ENXIO;
3324+ }
3325+ fprintf(stderr, "%s: %s: size: %lld\n", __func__,
3326+ ndctl_namespace_get_devname(ndns),
3327+ ndctl_namespace_get_size(ndns));
3328+ count++;
3329+ }
3330+ if (count != namespace_count) {
3331+ fprintf(stderr, "%s: fail expected %d namespaces got %d\n",
3332+ ndctl_region_get_devname(region),
3333+ namespace_count, count);
3334+ return -ENXIO;
3335+ }
3336+ }
3337+ return 0;
3338 }
3339
3340 static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
3341 {
3342 struct ndctl_bus *bus = ndctl_bus_get_by_provider(ctx, "nfit_test.0");
3343+ struct ndctl_region *region, *victim_region = NULL;
3344 struct ndctl_dimm *dimm, *victim = NULL;
3345 char path[1024], buf[SYSFS_ATTR_SIZE];
3346- struct ndctl_region *region;
3347 struct log_ctx log_ctx;
3348 unsigned int handle;
3349 int rc, err = 0;
3350@@ -64,11 +199,10 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
3351
3352 log_init(&log_ctx, "test/dsm-fail", "NDCTL_TEST");
3353
3354- ndctl_bus_wait_probe(bus);
3355-
3356- /* disable all regions so that we can disable a dimm */
3357- ndctl_region_foreach(bus, region)
3358- ndctl_region_disable_invalidate(region);
3359+ if (reset_bus(bus)) {
3360+ fprintf(stderr, "failed to read labels\n");
3361+ return -ENXIO;
3362+ }
3363
3364 sprintf(path, "%s/handle", DIMM_PATH);
3365 rc = __sysfs_read_attr(&log_ctx, path, buf);
3366@@ -79,16 +213,11 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
3367
3368 handle = strtoul(buf, NULL, 0);
3369
3370- ndctl_dimm_foreach(bus, dimm) {
3371- if (ndctl_dimm_get_handle(dimm) == handle)
3372+ ndctl_dimm_foreach(bus, dimm)
3373+ if (ndctl_dimm_get_handle(dimm) == handle) {
3374 victim = dimm;
3375-
3376- if (ndctl_dimm_disable(dimm)) {
3377- fprintf(stderr, "failed to disable: %s\n",
3378- ndctl_dimm_get_devname(dimm));
3379- return -ENXIO;
3380+ break;
3381 }
3382- }
3383
3384 if (!victim) {
3385 fprintf(stderr, "failed to find victim dimm\n");
3386@@ -96,67 +225,133 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
3387 }
3388 fprintf(stderr, "victim: %s\n", ndctl_dimm_get_devname(victim));
3389
3390- sprintf(path, "%s/fail_cmd", DIMM_PATH);
3391- sprintf(buf, "%#x\n", 1 << ND_CMD_GET_CONFIG_SIZE);
3392- rc = __sysfs_write_attr(&log_ctx, path, buf);
3393- if (rc) {
3394- fprintf(stderr, "failed to set fail cmd mask\n");
3395- return -ENXIO;
3396- }
3397+ ndctl_region_foreach(bus, region) {
3398+ if (ndctl_region_get_type(region) != ND_DEVICE_REGION_PMEM)
3399+ continue;
3400+ ndctl_dimm_foreach_in_region(region, dimm) {
3401+ const char *argv[] = {
3402+ "__func__", "-v", "-r",
3403+ ndctl_region_get_devname(region),
3404+ "-s", "4M", "-m", "raw",
3405+ };
3406+ struct ndctl_namespace *ndns;
3407+ int count, i;
3408
3409- ndctl_dimm_foreach(bus, dimm) {
3410- rc = ndctl_dimm_enable(dimm);
3411- fprintf(stderr, "dimm: %s enable: %d\n",
3412- ndctl_dimm_get_devname(dimm), rc);
3413- if ((rc == 0) == (dimm == victim)) {
3414- fprintf(stderr, "fail expected %s enable %s victim: %s\n",
3415- ndctl_dimm_get_devname(dimm),
3416- (dimm == victim) ? "failure" : "success",
3417- ndctl_dimm_get_devname(victim));
3418- err = -ENXIO;
3419- goto out;
3420+ if (dimm != victim)
3421+ continue;
3422+ /*
3423+ * Validate that we only have the one seed
3424+ * namespace, and then create one so that we can
3425+ * verify namespace enumeration while locked.
3426+ */
3427+ count = 0;
3428+ ndctl_namespace_foreach(region, ndns)
3429+ count++;
3430+ if (count != 1) {
3431+ fprintf(stderr, "%s: found %d namespaces expected 1\n",
3432+ ndctl_region_get_devname(region),
3433+ count);
3434+ rc = -ENXIO;
3435+ goto out;
3436+ }
3437+ if (ndctl_region_get_size(region)
3438+ != ndctl_region_get_available_size(region)) {
3439+ fprintf(stderr, "%s: expected empty region\n",
3440+ ndctl_region_get_devname(region));
3441+ rc = -ENXIO;
3442+ goto out;
3443+ }
3444+ for (i = 0; i < 2; i++) {
3445+ builtin_xaction_namespace_reset();
3446+ rc = cmd_create_namespace(ARRAY_SIZE(argv), argv,
3447+ ndctl_region_get_ctx(region));
3448+ if (rc) {
3449+ fprintf(stderr, "%s: failed to create namespace\n",
3450+ ndctl_region_get_devname(region));
3451+ rc = -ENXIO;
3452+ goto out;
3453+ }
3454+ }
3455+ victim_region = region;
3456 }
3457+ if (victim_region)
3458+ break;
3459 }
3460
3461- ndctl_region_foreach(bus, region) {
3462- bool has_victim = false;
3463+ /* disable all regions so that we can disable a dimm */
3464+ ndctl_region_foreach(bus, region)
3465+ ndctl_region_disable_invalidate(region);
3466
3467- ndctl_dimm_foreach_in_region(region, dimm) {
3468- if (dimm == victim) {
3469- has_victim = true;
3470- break;
3471- }
3472- }
3473+ rc = dimms_disable(bus);
3474+ if (rc)
3475+ goto out;
3476
3477- rc = ndctl_region_enable(region);
3478- fprintf(stderr, "region: %s enable: %d has_victim: %d\n",
3479- ndctl_region_get_devname(region), rc, has_victim);
3480- if ((rc == 0) == has_victim) {
3481- fprintf(stderr, "fail expected %s enable %s with %s disabled\n",
3482- ndctl_region_get_devname(region),
3483- has_victim ? "failure" : "success",
3484- ndctl_dimm_get_devname(victim));
3485- err = -ENXIO;
3486- goto out;
3487- }
3488- }
3489+
3490+ rc = set_dimm_response(DIMM_PATH, ND_CMD_GET_CONFIG_SIZE, -EACCES,
3491+ &log_ctx);
3492+ if (rc)
3493+ goto out;
3494+ fprintf(stderr, "%s:%d\n", __func__, __LINE__);
3495+ rc = test_dimms_enable(bus, victim, true);
3496+ if (rc)
3497+ goto out;
3498+ fprintf(stderr, "%s:%d\n", __func__, __LINE__);
3499+ rc = test_regions_enable(bus, victim, victim_region, true, 2);
3500+ if (rc)
3501+ goto out;
3502+ fprintf(stderr, "%s:%d\n", __func__, __LINE__);
3503+ rc = set_dimm_response(DIMM_PATH, ND_CMD_GET_CONFIG_SIZE, 0, &log_ctx);
3504+ if (rc)
3505+ goto out;
3506+
3507+ ndctl_region_foreach(bus, region)
3508+ ndctl_region_disable_invalidate(region);
3509+ fprintf(stderr, "%s:%d\n", __func__, __LINE__);
3510+ rc = dimms_disable(bus);
3511+ if (rc)
3512+ goto out;
3513+ fprintf(stderr, "%s:%d\n", __func__, __LINE__);
3514+
3515+ rc = set_dimm_response(DIMM_PATH, ND_CMD_GET_CONFIG_DATA, -EACCES,
3516+ &log_ctx);
3517+ if (rc)
3518+ goto out;
3519+ fprintf(stderr, "%s:%d\n", __func__, __LINE__);
3520+ rc = test_dimms_enable(bus, victim, false);
3521+ if (rc)
3522+ goto out;
3523+ fprintf(stderr, "%s:%d\n", __func__, __LINE__);
3524+ rc = test_regions_enable(bus, victim, victim_region, false, 0);
3525+ if (rc)
3526+ goto out;
3527+ fprintf(stderr, "%s:%d\n", __func__, __LINE__);
3528+ rc = set_dimm_response(DIMM_PATH, ND_CMD_GET_CONFIG_DATA, 0, &log_ctx);
3529+ if (rc)
3530+ goto out;
3531+ fprintf(stderr, "%s:%d\n", __func__, __LINE__);
3532+ rc = dimms_disable(bus);
3533+ if (rc)
3534+ goto out;
3535+ fprintf(stderr, "%s:%d\n", __func__, __LINE__);
3536
3537 out:
3538+ err = rc;
3539+ sprintf(path, "%s/fail_cmd", DIMM_PATH);
3540 sprintf(buf, "0\n");
3541 rc = __sysfs_write_attr(&log_ctx, path, buf);
3542- if (rc) {
3543+ if (rc)
3544 fprintf(stderr, "%s: failed to clear fail_cmd mask\n",
3545 ndctl_dimm_get_devname(victim));
3546- err = -ENXIO;
3547- }
3548 rc = ndctl_dimm_enable(victim);
3549 if (rc) {
3550 fprintf(stderr, "failed to enable victim: %s after clearing error\n",
3551 ndctl_dimm_get_devname(victim));
3552- err = -ENXIO;
3553+ rc = -ENXIO;
3554 }
3555 reset_bus(bus);
3556
3557+ if (rc)
3558+ err = rc;
3559 return err;
3560 }
3561
3562diff --git a/test/firmware-update.sh b/test/firmware-update.sh
3563index c2cf578..50674a6 100755
3564--- a/test/firmware-update.sh
3565+++ b/test/firmware-update.sh
3566@@ -2,70 +2,43 @@
3567 # SPDX-License-Identifier: GPL-2.0
3568 # Copyright(c) 2018 Intel Corporation. All rights reserved.
3569
3570-[ -f "../ndctl/ndctl" ] && [ -x "../ndctl/ndctl" ] && ndctl="../ndctl/ndctl"
3571-[ -f "./ndctl/ndctl" ] && [ -x "./ndctl/ndctl" ] && ndctl="./ndctl/ndctl"
3572-[ -z "$ndctl" ] && echo "Couldn't find an ndctl binary" && exit 1
3573-bus="nfit_test.0"
3574-bus1="nfit_test.1"
3575-json2var="s/[{}\",]//g; s/:/=/g"
3576 rc=77
3577 dev=""
3578 image="update-fw.img"
3579
3580-trap 'err $LINENO' ERR
3581-
3582-# $1: Line number
3583-# $2: exit code
3584-err()
3585-{
3586- [ -n "$2" ] && rc="$2"
3587- echo "test/firmware-update.sh: failed at line $1"
3588- exit "$rc"
3589-}
3590-
3591-check_min_kver()
3592-{
3593- local ver="$1"
3594- : "${KVER:=$(uname -r)}"
3595+. ./common
3596
3597- [ -n "$ver" ] || return 1
3598- [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
3599-}
3600+trap 'err $LINENO' ERR
3601
3602 reset()
3603 {
3604- $ndctl disable-region -b "$bus" all
3605- $ndctl zero-labels -b "$bus" all
3606- $ndctl enable-region -b "$bus" all
3607+ $NDCTL disable-region -b $NFIT_TEST_BUS0 all
3608+ $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
3609+ $NDCTL enable-region -b $NFIT_TEST_BUS0 all
3610 if [ -f $image ]; then
3611 rm -f $image
3612 fi
3613 }
3614
3615-cleanup()
3616-{
3617- $ndctl disable-region -b "$bus" all
3618- $ndctl disable-region -b "$bus1" all
3619- modprobe -r nfit_test
3620-}
3621-
3622 detect()
3623 {
3624- dev=$($ndctl list -b "$bus" -D | jq .[0].dev | tr -d '"')
3625- [ -n "$dev" ] || err "$LINENO" 2
3626+ dev=$($NDCTL list -b $NFIT_TEST_BUS0 -D | jq .[0].dev | tr -d '"')
3627+ [ -n "$dev" ] || err "$LINENO"
3628 }
3629
3630 do_tests()
3631 {
3632 truncate -s 196608 $image
3633- $ndctl update-firmware -f $image $dev
3634+ $NDCTL update-firmware -f $image $dev
3635 }
3636
3637-check_min_kver "4.16" || { echo "kernel $KVER may lack firmware update test handling"; exit $rc; }
3638+check_min_kver "4.16" || do_skip "may lack firmware update test handling"
3639+
3640 modprobe nfit_test
3641 rc=1
3642 reset
3643+rc=2
3644 detect
3645 do_tests
3646-cleanup
3647+_cleanup
3648 exit 0
3649diff --git a/test/inject-error.sh b/test/inject-error.sh
3650index 8630745..7bda35b 100755
3651--- a/test/inject-error.sh
3652+++ b/test/inject-error.sh
3653@@ -11,11 +11,6 @@
3654 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3655 # General Public License for more details.
3656
3657-[ -f "../ndctl/ndctl" ] && [ -x "../ndctl/ndctl" ] && ndctl="../ndctl/ndctl"
3658-[ -f "./ndctl/ndctl" ] && [ -x "./ndctl/ndctl" ] && ndctl="./ndctl/ndctl"
3659-[ -z "$ndctl" ] && echo "Couldn't find an ndctl binary" && exit 1
3660-bus="nfit_test.0"
3661-json2var="s/[{}\",]//g; s/:/=/g"
3662 dev=""
3663 size=""
3664 blockdev=""
3665@@ -23,6 +18,8 @@ rc=77
3666 err_block=42
3667 err_count=8
3668
3669+. ./common
3670+
3671 trap 'err $LINENO' ERR
3672
3673 # sample json:
3674@@ -34,41 +31,24 @@ trap 'err $LINENO' ERR
3675 # "blockdev":"pmem7",
3676 #}
3677
3678-# $1: Line number
3679-# $2: exit code
3680-err()
3681-{
3682- [ -n "$2" ] && rc="$2"
3683- echo "test/inject-error.sh: failed at line $1"
3684- exit "$rc"
3685-}
3686-
3687-check_min_kver()
3688-{
3689- local ver="$1"
3690- : "${KVER:=$(uname -r)}"
3691-
3692- [ -n "$ver" ] || return 1
3693- [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
3694-}
3695-
3696-check_min_kver "4.15" || { echo "kernel $KVER may not support error injection"; exit "$rc"; }
3697+check_min_kver "4.15" || do_skip "kernel $KVER may not support error injection"
3698
3699 create()
3700 {
3701- json=$($ndctl create-namespace -b "$bus" -t pmem --align=4k)
3702- eval "$(echo "$json" | sed -e "$json2var")"
3703- [ -n "$dev" ] || err "$LINENO" 2
3704- [ -n "$size" ] || err "$LINENO" 2
3705- [ -n "$blockdev" ] || err "$LINENO" 2
3706- [ $size -gt 0 ] || err "$LINENO" 2
3707+ json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem --align=4k)
3708+ rc=2
3709+ eval "$(echo "$json" | json2var)"
3710+ [ -n "$dev" ] || err "$LINENO"
3711+ [ -n "$size" ] || err "$LINENO"
3712+ [ -n "$blockdev" ] || err "$LINENO"
3713+ [ $size -gt 0 ] || err "$LINENO"
3714 }
3715
3716 reset()
3717 {
3718- $ndctl disable-region -b "$bus" all
3719- $ndctl zero-labels -b "$bus" all
3720- $ndctl enable-region -b "$bus" all
3721+ $NDCTL disable-region -b $NFIT_TEST_BUS0 all
3722+ $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
3723+ $NDCTL enable-region -b $NFIT_TEST_BUS0 all
3724 }
3725
3726 check_status()
3727@@ -76,7 +56,7 @@ check_status()
3728 local sector="$1"
3729 local count="$2"
3730
3731- json="$($ndctl inject-error --status $dev)"
3732+ json="$($NDCTL inject-error --status $dev)"
3733 [[ "$sector" == "$(jq ".badblocks[0].block" <<< "$json")" ]]
3734 [[ "$count" == "$(jq ".badblocks[0].count" <<< "$json")" ]]
3735 }
3736@@ -84,7 +64,7 @@ check_status()
3737 do_tests()
3738 {
3739 # inject without notification
3740- $ndctl inject-error --block=$err_block --count=$err_count --no-notify $dev
3741+ $NDCTL inject-error --block=$err_block --count=$err_count --no-notify $dev
3742 check_status "$err_block" "$err_count"
3743 if read -r sector len < /sys/block/$blockdev/badblocks; then
3744 # fail if reading badblocks returns data
3745@@ -92,11 +72,11 @@ do_tests()
3746 fi
3747
3748 # clear via err-inj-clear
3749- $ndctl inject-error --block=$err_block --count=$err_count --uninject $dev
3750+ $NDCTL inject-error --block=$err_block --count=$err_count --uninject $dev
3751 check_status
3752
3753 # inject normally
3754- $ndctl inject-error --block=$err_block --count=$err_count $dev
3755+ $NDCTL inject-error --block=$err_block --count=$err_count $dev
3756 check_status "$err_block" "$err_count"
3757 if read -r sector len < /sys/block/$blockdev/badblocks; then
3758 test "$sector" -eq "$err_block"
3759@@ -117,4 +97,5 @@ rc=1
3760 reset && create
3761 do_tests
3762 reset
3763+_cleanup
3764 exit 0
3765diff --git a/test/label-compat.sh b/test/label-compat.sh
3766index 8c9ee63..dc6226d 100755
3767--- a/test/label-compat.sh
3768+++ b/test/label-compat.sh
3769@@ -11,40 +11,24 @@
3770 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3771 # General Public License for more details.
3772
3773-NDCTL="../ndctl/ndctl"
3774-BUS="-b nfit_test.0"
3775-BUS1="-b nfit_test.1"
3776-rc=77
3777-
3778 set -e
3779
3780-err() {
3781- echo "test/label-compat.sh: failed at line $1"
3782- exit $rc
3783-}
3784-
3785-check_min_kver()
3786-{
3787- local ver="$1"
3788- : "${KVER:=$(uname -r)}"
3789+rc=77
3790
3791- [ -n "$ver" ] || return 1
3792- [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
3793-}
3794+. ./common
3795
3796-check_min_kver "4.11" || { echo "kernel $KVER may not provide reliable isetcookie values"; exit $rc; }
3797+check_min_kver "4.11" || do_skip "may not provide reliable isetcookie values"
3798
3799-set -e
3800 trap 'err $LINENO' ERR
3801
3802 # setup (reset nfit_test dimms)
3803 modprobe nfit_test
3804-$NDCTL disable-region $BUS all
3805-$NDCTL zero-labels $BUS all
3806+$NDCTL disable-region -b $NFIT_TEST_BUS0 all
3807+$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
3808
3809-# grab the largest pmem region on $BUS
3810+# grab the largest pmem region on -b $NFIT_TEST_BUS0
3811 query=". | sort_by(.available_size) | reverse | .[0].dev"
3812-region=$($NDCTL list $BUS -t pmem -Ri | jq -r "$query")
3813+region=$($NDCTL list -b $NFIT_TEST_BUS0 -t pmem -Ri | jq -r "$query")
3814
3815 # we assume that $region is comprised of 4 dimms
3816 query=". | .regions[0].mappings | sort_by(.dimm) | .[].dimm"
3817@@ -56,7 +40,7 @@ do
3818 i=$((i+1))
3819 done
3820
3821-$NDCTL enable-region $BUS all
3822+$NDCTL enable-region -b $NFIT_TEST_BUS0 all
3823
3824 len=$($NDCTL list -r $region -N | jq -r "length")
3825
3826@@ -66,8 +50,6 @@ if [ -z $len ]; then
3827 exit 1
3828 fi
3829
3830-$NDCTL disable-region $BUS all
3831-$NDCTL disable-region $BUS1 all
3832-modprobe -r nfit_test
3833+_cleanup
3834
3835 exit 0
3836diff --git a/test/libndctl.c b/test/libndctl.c
3837index 8098c1c..edff0af 100644
3838--- a/test/libndctl.c
3839+++ b/test/libndctl.c
3840@@ -2177,8 +2177,8 @@ static int check_set_config_data(struct ndctl_bus *bus, struct ndctl_dimm *dimm,
3841 return 0;
3842 }
3843
3844-#define __check_smart(dimm, cmd, field) ({ \
3845- if (ndctl_cmd_smart_get_##field(cmd) != smart_data.field) { \
3846+#define __check_smart(dimm, cmd, field, mask) ({ \
3847+ if ((ndctl_cmd_smart_get_##field(cmd) & mask) != smart_data.field) { \
3848 fprintf(stderr, "%s dimm: %#x expected \'" #field \
3849 "\' %#x got: %#x\n", __func__, \
3850 ndctl_dimm_get_handle(dimm), \
3851@@ -2230,14 +2230,14 @@ static int check_smart(struct ndctl_bus *bus, struct ndctl_dimm *dimm,
3852 return rc;
3853 }
3854
3855- __check_smart(dimm, cmd, flags);
3856- __check_smart(dimm, cmd, health);
3857- __check_smart(dimm, cmd, temperature);
3858- __check_smart(dimm, cmd, spares);
3859- __check_smart(dimm, cmd, alarm_flags);
3860- __check_smart(dimm, cmd, life_used);
3861- __check_smart(dimm, cmd, shutdown_state);
3862- __check_smart(dimm, cmd, vendor_size);
3863+ __check_smart(dimm, cmd, flags, ~ND_SMART_CTEMP_VALID);
3864+ __check_smart(dimm, cmd, health, -1);
3865+ __check_smart(dimm, cmd, temperature, -1);
3866+ __check_smart(dimm, cmd, spares, -1);
3867+ __check_smart(dimm, cmd, alarm_flags, -1);
3868+ __check_smart(dimm, cmd, life_used, -1);
3869+ __check_smart(dimm, cmd, shutdown_state, -1);
3870+ __check_smart(dimm, cmd, vendor_size, -1);
3871
3872 check->cmd = cmd;
3873 return 0;
3874diff --git a/test/multi-dax.sh b/test/multi-dax.sh
3875index 59ec6d6..0829bf2 100755
3876--- a/test/multi-dax.sh
3877+++ b/test/multi-dax.sh
3878@@ -11,51 +11,31 @@
3879 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3880 # General Public License for more details.
3881
3882-DEV=""
3883-NDCTL="../ndctl/ndctl"
3884-DAXCTL="../daxctl/daxctl"
3885-BUS="-b nfit_test.0"
3886-BUS1="-b nfit_test.1"
3887-json2var="s/[{}\",]//g; s/:/=/g"
3888-rc=77
3889-
3890-err() {
3891- echo "test/multi-dax: failed at line $1"
3892- exit $rc
3893-}
3894+set -e
3895
3896-check_min_kver()
3897-{
3898- local ver="$1"
3899- : "${KVER:=$(uname -r)}"
3900+rc=77
3901
3902- [ -n "$ver" ] || return 1
3903- [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
3904-}
3905+. ./common
3906
3907-check_min_kver "4.13" || { echo "kernel $KVER may lack multi-dax support"; exit $rc; }
3908+check_min_kver "4.13" || do_skip "may lack multi-dax support"
3909
3910-set -e
3911 trap 'err $LINENO' ERR
3912
3913 # setup (reset nfit_test dimms)
3914 modprobe nfit_test
3915-$NDCTL disable-region $BUS all
3916-$NDCTL zero-labels $BUS all
3917-$NDCTL enable-region $BUS all
3918+$NDCTL disable-region -b $NFIT_TEST_BUS0 all
3919+$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
3920+$NDCTL enable-region -b $NFIT_TEST_BUS0 all
3921 rc=1
3922
3923 query=". | sort_by(.available_size) | reverse | .[0].dev"
3924-region=$($NDCTL list $BUS -t pmem -Ri | jq -r "$query")
3925+region=$($NDCTL list -b $NFIT_TEST_BUS0 -t pmem -Ri | jq -r "$query")
3926
3927-json=$($NDCTL create-namespace $BUS -r $region -t pmem -m devdax -a 4096 -s 16M)
3928+json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -r $region -t pmem -m devdax -a 4096 -s 16M)
3929 chardev1=$(echo $json | jq ". | select(.mode == \"devdax\") | .daxregion.devices[0].chardev")
3930-json=$($NDCTL create-namespace $BUS -r $region -t pmem -m devdax -a 4096 -s 16M)
3931+json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -r $region -t pmem -m devdax -a 4096 -s 16M)
3932 chardev2=$(echo $json | jq ". | select(.mode == \"devdax\") | .daxregion.devices[0].chardev")
3933
3934-# cleanup
3935-$NDCTL disable-region $BUS all
3936-$NDCTL disable-region $BUS1 all
3937-modprobe -r nfit_test
3938+_cleanup
3939
3940 exit 0
3941diff --git a/test/pmem-errors.sh b/test/pmem-errors.sh
3942index e0ab9e8..9553a3f 100755
3943--- a/test/pmem-errors.sh
3944+++ b/test/pmem-errors.sh
3945@@ -2,17 +2,14 @@
3946 # SPDX-License-Identifier: GPL-2.0
3947 # Copyright(c) 2015-2017 Intel Corporation. All rights reserved.
3948
3949-DEV=""
3950-NDCTL="../ndctl/ndctl"
3951-BUS="-b nfit_test.0"
3952-BUS1="-b nfit_test.1"
3953 MNT=test_dax_mnt
3954 FILE=image
3955-json2var="s/[{}\",]//g; s/:/=/g"
3956 rc=77
3957
3958-err() {
3959- echo "test/dax-errors: failed at line $1"
3960+. ./common
3961+
3962+cleanup()
3963+{
3964 rm -f $FILE
3965 rm -f $MNT/$FILE
3966 if [ -n "$blockdev" ]; then
3967@@ -21,36 +18,26 @@ err() {
3968 rc=77
3969 fi
3970 rmdir $MNT
3971- exit $rc
3972-}
3973-
3974-check_min_kver()
3975-{
3976- local ver="$1"
3977- : "${KVER:=$(uname -r)}"
3978-
3979- [ -n "$ver" ] || return 1
3980- [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
3981 }
3982
3983-check_min_kver "4.7" || { echo "kernel $KVER may lack dax error handling"; exit $rc; }
3984+check_min_kver "4.7" || do_skip "may lack dax error handling"
3985
3986 set -e
3987 mkdir -p $MNT
3988-trap 'err $LINENO' ERR
3989+trap 'err $LINENO cleanup' ERR
3990
3991 # setup (reset nfit_test dimms)
3992 modprobe nfit_test
3993-$NDCTL disable-region $BUS all
3994-$NDCTL zero-labels $BUS all
3995-$NDCTL enable-region $BUS all
3996+$NDCTL disable-region -b $NFIT_TEST_BUS0 all
3997+$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
3998+$NDCTL enable-region -b $NFIT_TEST_BUS0 all
3999
4000 rc=1
4001
4002 # create pmem
4003 dev="x"
4004-json=$($NDCTL create-namespace $BUS -t pmem -m raw)
4005-eval $(echo $json | sed -e "$json2var")
4006+json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem -m raw)
4007+eval $(echo $json | json2var)
4008 [ $dev = "x" ] && echo "fail: $LINENO" && false
4009 [ $mode != "raw" ] && echo "fail: $LINENO" && false
4010
4011@@ -134,8 +121,6 @@ if [ -n "$blockdev" ]; then
4012 fi
4013 rmdir $MNT
4014
4015-$NDCTL disable-region $BUS all
4016-$NDCTL disable-region $BUS1 all
4017-modprobe -r nfit_test
4018+_cleanup
4019
4020 exit 0
4021diff --git a/test/rescan-partitions.sh b/test/rescan-partitions.sh
4022index eb313fb..9c7b7a0 100755
4023--- a/test/rescan-partitions.sh
4024+++ b/test/rescan-partitions.sh
4025@@ -2,16 +2,13 @@
4026 # SPDX-License-Identifier: GPL-2.0
4027 # Copyright(c) 2018 Intel Corporation. All rights reserved.
4028
4029-[ -f "../ndctl/ndctl" ] && [ -x "../ndctl/ndctl" ] && ndctl="../ndctl/ndctl"
4030-[ -f "./ndctl/ndctl" ] && [ -x "./ndctl/ndctl" ] && ndctl="./ndctl/ndctl"
4031-[ -z "$ndctl" ] && echo "Couldn't find an ndctl binary" && exit 1
4032-bus="nfit_test.0"
4033-json2var="s/[{}\",]//g; s/:/=/g"
4034 dev=""
4035 size=""
4036 blockdev=""
4037 rc=77
4038
4039+. ./common
4040+
4041 trap 'err $LINENO' ERR
4042
4043 # sample json:
4044@@ -23,40 +20,16 @@ trap 'err $LINENO' ERR
4045 # "blockdev":"pmem5s",
4046 #}
4047
4048-# $1: Line number
4049-# $2: exit code
4050-err()
4051-{
4052- [ -n "$2" ] && rc="$2"
4053- echo "test/rescan-partitions.sh: failed at line $1"
4054- exit "$rc"
4055-}
4056-
4057-check_min_kver()
4058-{
4059- local ver="$1"
4060- : "${KVER:=$(uname -r)}"
4061-
4062- [ -n "$ver" ] || return 1
4063- [[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
4064-}
4065-check_min_kver "4.16" || { echo "kernel $KVER may not contain fixes for partition rescanning"; exit "$rc"; }
4066+check_min_kver "4.16" || do_skip "may not contain fixes for partition rescanning"
4067
4068-check_prereq()
4069-{
4070- if ! command -v "$1" >/dev/null; then
4071- echo "missing '$1', skipping.."
4072- exit "$rc"
4073- fi
4074-}
4075 check_prereq "parted"
4076 check_prereq "blockdev"
4077
4078 reset()
4079 {
4080- $ndctl disable-region -b "$bus" all
4081- $ndctl zero-labels -b "$bus" all
4082- $ndctl enable-region -b "$bus" all
4083+ $NDCTL disable-region -b $NFIT_TEST_BUS0 all
4084+ $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
4085+ $NDCTL enable-region -b $NFIT_TEST_BUS0 all
4086 }
4087
4088 test_mode()
4089@@ -64,13 +37,15 @@ test_mode()
4090 local mode="$1"
4091
4092 # create namespace
4093- json=$($ndctl create-namespace -b "$bus" -t pmem -m "$mode")
4094- eval "$(echo "$json" | sed -e "$json2var")"
4095- [ -n "$dev" ] || err "$LINENO" 2
4096- [ -n "$size" ] || err "$LINENO" 2
4097- [ -n "$blockdev" ] || err "$LINENO" 2
4098- [ $size -gt 0 ] || err "$LINENO" 2
4099-
4100+ json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem -m "$mode")
4101+ rc=2
4102+ eval "$(echo "$json" | json2var)"
4103+ [ -n "$dev" ] || err "$LINENO"
4104+ [ -n "$size" ] || err "$LINENO"
4105+ [ -n "$blockdev" ] || err "$LINENO"
4106+ [ $size -gt 0 ] || err "$LINENO"
4107+
4108+ rc=1
4109 # create partition
4110 parted --script /dev/$blockdev mklabel gpt mkpart primary 1MiB 10MiB
4111
4112@@ -83,17 +58,18 @@ test_mode()
4113
4114 # cycle the namespace, and verify the partition is read
4115 # without needing to do a blockdev --rereadpt
4116- $ndctl disable-namespace $dev
4117- $ndctl enable-namespace $dev
4118+ $NDCTL disable-namespace $dev
4119+ $NDCTL enable-namespace $dev
4120 if [ -b /dev/$partdev ]; then
4121 echo "mode: $mode - partition read successful"
4122 else
4123 echo "mode: $mode - partition read failed"
4124- err "$LINENO" 1
4125+ rc=1
4126+ err "$LINENO"
4127 fi
4128
4129- $ndctl disable-namespace $dev
4130- $ndctl destroy-namespace $dev
4131+ $NDCTL disable-namespace $dev
4132+ $NDCTL destroy-namespace $dev
4133 }
4134
4135 modprobe nfit_test
4136@@ -102,5 +78,5 @@ reset
4137 test_mode "raw"
4138 test_mode "fsdax"
4139 test_mode "sector"
4140-
4141+_cleanup
4142 exit 0
4143diff --git a/test/sector-mode.sh b/test/sector-mode.sh
4144index ee364eb..16c1ddf 100755
4145--- a/test/sector-mode.sh
4146+++ b/test/sector-mode.sh
4147@@ -11,45 +11,32 @@
4148 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4149 # General Public License for more details.
4150
4151-NDCTL="../ndctl/ndctl"
4152-BUS="-b nfit_test.0"
4153-BUS1="-b nfit_test.1"
4154-TEST=$0
4155 rc=77
4156
4157-err() {
4158- echo "$TEST: failed at line $1"
4159- exit $rc
4160-}
4161+. ./common
4162
4163 set -e
4164 trap 'err $LINENO' ERR
4165
4166 # setup (reset nfit_test dimms)
4167 modprobe nfit_test
4168-$NDCTL disable-region $BUS all
4169-$NDCTL zero-labels $BUS all
4170-$NDCTL enable-region $BUS all
4171-
4172-$NDCTL disable-region $BUS1 all
4173-if $NDCTL zero-labels $BUS1 all; then
4174- echo "DIMMs on $BUS1 support labels, skip..."
4175- $NDCTL enable-region $BUS1 all
4176- false
4177-fi
4178-$NDCTL enable-region $BUS1 all
4179+$NDCTL disable-region -b $NFIT_TEST_BUS0 all
4180+$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
4181+$NDCTL enable-region -b $NFIT_TEST_BUS0 all
4182+
4183+$NDCTL disable-region -b $NFIT_TEST_BUS1 all
4184+$NDCTL zero-labels -b $NFIT_TEST_BUS1 all
4185+$NDCTL enable-region -b $NFIT_TEST_BUS1 all
4186
4187 rc=1
4188 query=". | sort_by(.size) | reverse | .[0].dev"
4189-NAMESPACE=$($NDCTL list $BUS1 -N | jq -r "$query")
4190+NAMESPACE=$($NDCTL list -b $NFIT_TEST_BUS1 -N | jq -r "$query")
4191 REGION=$($NDCTL list -R --namespace=$NAMESPACE | jq -r ".dev")
4192 echo 0 > /sys/bus/nd/devices/$REGION/read_only
4193-$NDCTL create-namespace -e $NAMESPACE -m sector -f -l 4K
4194-$NDCTL create-namespace -e $NAMESPACE -m dax -f -a 4K
4195-$NDCTL create-namespace -e $NAMESPACE -m sector -f -l 4K
4196+$NDCTL create-namespace --no-autolabel -e $NAMESPACE -m sector -f -l 4K
4197+$NDCTL create-namespace --no-autolabel -e $NAMESPACE -m dax -f -a 4K
4198+$NDCTL create-namespace --no-autolabel -e $NAMESPACE -m sector -f -l 4K
4199
4200-$NDCTL disable-region $BUS all
4201-$NDCTL disable-region $BUS1 all
4202-modprobe -r nfit_test
4203+_cleanup
4204
4205 exit 0
4206diff --git a/util/abspath.c b/util/abspath.c
4207new file mode 100644
4208index 0000000..09bbd27
4209--- /dev/null
4210+++ b/util/abspath.c
4211@@ -0,0 +1,29 @@
4212+/* SPDX-License-Identifier: GPL-2.0 */
4213+/* originally copied from git/abspath.c */
4214+
4215+#include <util/util.h>
4216+#include <util/strbuf.h>
4217+
4218+char *prefix_filename(const char *pfx, const char *arg)
4219+{
4220+ struct strbuf path = STRBUF_INIT;
4221+ size_t pfx_len = pfx ? strlen(pfx) : 0;
4222+
4223+ if (!pfx_len)
4224+ ;
4225+ else if (is_absolute_path(arg))
4226+ pfx_len = 0;
4227+ else
4228+ strbuf_add(&path, pfx, pfx_len);
4229+
4230+ strbuf_addstr(&path, arg);
4231+ return strbuf_detach(&path, NULL);
4232+}
4233+
4234+void fix_filename(const char *prefix, const char **file)
4235+{
4236+ if (!file || !*file || !prefix || is_absolute_path(*file)
4237+ || !strcmp("-", *file))
4238+ return;
4239+ *file = prefix_filename(prefix, *file);
4240+}
4241diff --git a/util/filter.c b/util/filter.c
4242index 6ab391a..1734bce 100644
4243--- a/util/filter.c
4244+++ b/util/filter.c
4245@@ -25,101 +25,156 @@
4246
4247 #define NUMA_NO_NODE (-1)
4248
4249-struct ndctl_bus *util_bus_filter(struct ndctl_bus *bus, const char *ident)
4250+struct ndctl_bus *util_bus_filter(struct ndctl_bus *bus, const char *__ident)
4251 {
4252- char *end = NULL;
4253+ char *end = NULL, *ident, *save;
4254 unsigned long bus_id, id;
4255- const char *provider, *devname;
4256+ const char *provider, *devname, *name;
4257
4258- if (!ident || strcmp(ident, "all") == 0)
4259+ if (!__ident)
4260 return bus;
4261
4262- bus_id = strtoul(ident, &end, 0);
4263- if (end == ident || end[0])
4264- bus_id = ULONG_MAX;
4265+ ident = strdup(__ident);
4266+ if (!ident)
4267+ return NULL;
4268
4269- provider = ndctl_bus_get_provider(bus);
4270- devname = ndctl_bus_get_devname(bus);
4271- id = ndctl_bus_get_id(bus);
4272+ for (name = strtok_r(ident, " ", &save); name;
4273+ name = strtok_r(NULL, " ", &save)) {
4274+ if (strcmp(name, "all") == 0)
4275+ break;
4276
4277- if (bus_id < ULONG_MAX && bus_id == id)
4278- return bus;
4279+ bus_id = strtoul(ident, &end, 0);
4280+ if (end == ident || end[0])
4281+ bus_id = ULONG_MAX;
4282
4283- if (bus_id == ULONG_MAX && (strcmp(ident, provider) == 0
4284- || strcmp(ident, devname) == 0))
4285- return bus;
4286+ provider = ndctl_bus_get_provider(bus);
4287+ devname = ndctl_bus_get_devname(bus);
4288+ id = ndctl_bus_get_id(bus);
4289+
4290+ if (bus_id < ULONG_MAX && bus_id == id)
4291+ break;
4292
4293+ if (bus_id == ULONG_MAX && (strcmp(provider, name) == 0
4294+ || strcmp(devname, name) == 0))
4295+ break;
4296+ }
4297+ free(ident);
4298+
4299+ if (name)
4300+ return bus;
4301 return NULL;
4302 }
4303
4304 struct ndctl_region *util_region_filter(struct ndctl_region *region,
4305- const char *ident)
4306+ const char *__ident)
4307 {
4308- char *end = NULL;
4309- const char *name;
4310+ char *end = NULL, *ident, *save;
4311+ const char *name, *region_name;
4312 unsigned long region_id, id;
4313
4314- if (!ident || strcmp(ident, "all") == 0)
4315+ if (!__ident)
4316 return region;
4317
4318- region_id = strtoul(ident, &end, 0);
4319- if (end == ident || end[0])
4320- region_id = ULONG_MAX;
4321+ ident = strdup(__ident);
4322+ if (!ident)
4323+ return NULL;
4324
4325- name = ndctl_region_get_devname(region);
4326- id = ndctl_region_get_id(region);
4327+ for (name = strtok_r(ident, " ", &save); name;
4328+ name = strtok_r(NULL, " ", &save)) {
4329+ if (strcmp(name, "all") == 0)
4330+ break;
4331
4332- if (region_id < ULONG_MAX && region_id == id)
4333- return region;
4334+ region_id = strtoul(ident, &end, 0);
4335+ if (end == ident || end[0])
4336+ region_id = ULONG_MAX;
4337
4338- if (region_id == ULONG_MAX && strcmp(ident, name) == 0)
4339- return region;
4340+ region_name = ndctl_region_get_devname(region);
4341+ id = ndctl_region_get_id(region);
4342
4343+ if (region_id < ULONG_MAX && region_id == id)
4344+ break;
4345+
4346+ if (region_id == ULONG_MAX && strcmp(region_name, name) == 0)
4347+ break;
4348+ }
4349+ free(ident);
4350+
4351+ if (name)
4352+ return region;
4353 return NULL;
4354 }
4355
4356 struct ndctl_namespace *util_namespace_filter(struct ndctl_namespace *ndns,
4357- const char *ident)
4358+ const char *__ident)
4359 {
4360 struct ndctl_region *region = ndctl_namespace_get_region(ndns);
4361 unsigned long region_id, ndns_id;
4362+ const char *name;
4363+ char *ident, *save;
4364
4365- if (!ident || strcmp(ident, "all") == 0)
4366+ if (!__ident)
4367 return ndns;
4368
4369- if (strcmp(ident, ndctl_namespace_get_devname(ndns)) == 0)
4370- return ndns;
4371+ ident = strdup(__ident);
4372+ if (!ident)
4373+ return NULL;
4374
4375- if (sscanf(ident, "%ld.%ld", &region_id, &ndns_id) == 2
4376- && ndctl_region_get_id(region) == region_id
4377- && ndctl_namespace_get_id(ndns) == ndns_id)
4378- return ndns;
4379+ for (name = strtok_r(ident, " ", &save); name;
4380+ name = strtok_r(NULL, " ", &save)) {
4381+ if (strcmp(name, "all") == 0)
4382+ break;
4383
4384+ if (strcmp(name, ndctl_namespace_get_devname(ndns)) == 0)
4385+ break;
4386+
4387+ if (sscanf(name, "%ld.%ld", &region_id, &ndns_id) == 2
4388+ && ndctl_region_get_id(region) == region_id
4389+ && ndctl_namespace_get_id(ndns) == ndns_id)
4390+ break;
4391+ }
4392+ free(ident);
4393+
4394+ if (name)
4395+ return ndns;
4396 return NULL;
4397 }
4398
4399-struct ndctl_dimm *util_dimm_filter(struct ndctl_dimm *dimm, const char *ident)
4400+struct ndctl_dimm *util_dimm_filter(struct ndctl_dimm *dimm,
4401+ const char *__ident)
4402 {
4403- char *end = NULL;
4404- const char *name;
4405+ char *end = NULL, *ident, *save;
4406+ const char *name, *dimm_name;
4407 unsigned long dimm_id, id;
4408
4409- if (!ident || strcmp(ident, "all") == 0)
4410+ if (!__ident)
4411 return dimm;
4412
4413- dimm_id = strtoul(ident, &end, 0);
4414- if (end == ident || end[0])
4415- dimm_id = ULONG_MAX;
4416+ ident = strdup(__ident);
4417+ if (!ident)
4418+ return NULL;
4419
4420- name = ndctl_dimm_get_devname(dimm);
4421- id = ndctl_dimm_get_id(dimm);
4422+ for (name = strtok_r(ident, " ", &save); name;
4423+ name = strtok_r(NULL, " ", &save)) {
4424+ if (strcmp(name, "all") == 0)
4425+ break;
4426
4427- if (dimm_id < ULONG_MAX && dimm_id == id)
4428- return dimm;
4429+ dimm_id = strtoul(ident, &end, 0);
4430+ if (end == ident || end[0])
4431+ dimm_id = ULONG_MAX;
4432
4433- if (dimm_id == ULONG_MAX && strcmp(ident, name) == 0)
4434- return dimm;
4435+ dimm_name = ndctl_dimm_get_devname(dimm);
4436+ id = ndctl_dimm_get_id(dimm);
4437
4438+ if (dimm_id < ULONG_MAX && dimm_id == id)
4439+ break;
4440+
4441+ if (dimm_id == ULONG_MAX && strcmp(dimm_name, name) == 0)
4442+ break;
4443+ }
4444+ free(ident);
4445+
4446+ if (name)
4447+ return dimm;
4448 return NULL;
4449 }
4450
4451diff --git a/util/help.c b/util/help.c
4452index 8b8f951..2d57fa1 100644
4453--- a/util/help.c
4454+++ b/util/help.c
4455@@ -89,11 +89,6 @@ static char *cmd_to_page(const char *cmd, char **page, const char *util_name)
4456 return *page;
4457 }
4458
4459-static int is_absolute_path(const char *path)
4460-{
4461- return path[0] == '/';
4462-}
4463-
4464 static const char *system_path(const char *path)
4465 {
4466 static const char *prefix = PREFIX;
4467diff --git a/util/json.c b/util/json.c
4468index 1772177..94ed948 100644
4469--- a/util/json.c
4470+++ b/util/json.c
4471@@ -652,10 +652,12 @@ static struct json_object *util_dax_badblocks_to_json(struct ndctl_dax *dax,
4472
4473 static struct json_object *util_raw_uuid(struct ndctl_namespace *ndns)
4474 {
4475- uuid_t raw_uuid;
4476 char buf[40];
4477+ uuid_t raw_uuid;
4478
4479 ndctl_namespace_get_uuid(ndns, raw_uuid);
4480+ if (uuid_is_null(raw_uuid))
4481+ return NULL;
4482 uuid_unparse(raw_uuid, buf);
4483 return json_object_new_string(buf);
4484 }
4485@@ -664,7 +666,13 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns,
4486 unsigned long flags)
4487 {
4488 struct json_object *jndns = json_object_new_object();
4489+ enum ndctl_pfn_loc loc = NDCTL_PFN_LOC_NONE;
4490 struct json_object *jobj, *jbbs = NULL;
4491+ const char *locations[] = {
4492+ [NDCTL_PFN_LOC_NONE] = "none",
4493+ [NDCTL_PFN_LOC_RAM] = "mem",
4494+ [NDCTL_PFN_LOC_PMEM] = "dev",
4495+ };
4496 unsigned long long size = ULLONG_MAX;
4497 unsigned int sector_size = UINT_MAX;
4498 enum ndctl_namespace_mode mode;
4499@@ -691,10 +699,13 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns,
4500 mode = ndctl_namespace_get_mode(ndns);
4501 switch (mode) {
4502 case NDCTL_NS_MODE_MEMORY:
4503- if (pfn) /* dynamic memory mode */
4504+ if (pfn) { /* dynamic memory mode */
4505 size = ndctl_pfn_get_size(pfn);
4506- else /* native/static memory mode */
4507+ loc = ndctl_pfn_get_location(pfn);
4508+ } else { /* native/static memory mode */
4509 size = ndctl_namespace_get_size(ndns);
4510+ loc = NDCTL_PFN_LOC_RAM;
4511+ }
4512 jobj = json_object_new_string("fsdax");
4513 break;
4514 case NDCTL_NS_MODE_DAX:
4515@@ -702,6 +713,7 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns,
4516 goto err;
4517 size = ndctl_dax_get_size(dax);
4518 jobj = json_object_new_string("devdax");
4519+ loc = ndctl_dax_get_location(dax);
4520 break;
4521 case NDCTL_NS_MODE_SAFE:
4522 if (!btt)
4523@@ -719,6 +731,12 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns,
4524 if (jobj)
4525 json_object_object_add(jndns, "mode", jobj);
4526
4527+ if ((mode != NDCTL_NS_MODE_SAFE) && (mode != NDCTL_NS_MODE_RAW)) {
4528+ jobj = json_object_new_string(locations[loc]);
4529+ if (jobj)
4530+ json_object_object_add(jndns, "map", jobj);
4531+ }
4532+
4533 if (size < ULLONG_MAX) {
4534 jobj = util_json_object_size(size, flags);
4535 if (jobj)
4536@@ -734,9 +752,8 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns,
4537 json_object_object_add(jndns, "uuid", jobj);
4538
4539 jobj = util_raw_uuid(ndns);
4540- if (!jobj)
4541- goto err;
4542- json_object_object_add(jndns, "raw_uuid", jobj);
4543+ if (jobj)
4544+ json_object_object_add(jndns, "raw_uuid", jobj);
4545 bdev = ndctl_btt_get_block_device(btt);
4546 } else if (pfn) {
4547 ndctl_pfn_get_uuid(pfn, uuid);
4548@@ -746,9 +763,8 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns,
4549 goto err;
4550 json_object_object_add(jndns, "uuid", jobj);
4551 jobj = util_raw_uuid(ndns);
4552- if (!jobj)
4553- goto err;
4554- json_object_object_add(jndns, "raw_uuid", jobj);
4555+ if (jobj)
4556+ json_object_object_add(jndns, "raw_uuid", jobj);
4557 bdev = ndctl_pfn_get_block_device(pfn);
4558 } else if (dax) {
4559 struct daxctl_region *dax_region;
4560@@ -761,9 +777,8 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns,
4561 goto err;
4562 json_object_object_add(jndns, "uuid", jobj);
4563 jobj = util_raw_uuid(ndns);
4564- if (!jobj)
4565- goto err;
4566- json_object_object_add(jndns, "raw_uuid", jobj);
4567+ if (jobj)
4568+ json_object_object_add(jndns, "raw_uuid", jobj);
4569 if ((flags & UTIL_JSON_DAX) && dax_region) {
4570 jobj = util_daxctl_region_to_json(dax_region, NULL,
4571 flags);
4572diff --git a/util/parse-options.c b/util/parse-options.c
4573index 751c091..c781174 100644
4574--- a/util/parse-options.c
4575+++ b/util/parse-options.c
4576@@ -55,6 +55,7 @@ static int get_value(struct parse_opt_ctx_t *p,
4577 {
4578 const char *s, *arg = NULL;
4579 const int unset = flags & OPT_UNSET;
4580+ int err;
4581
4582 if (unset && p->opt)
4583 return opterror(opt, "takes no value", flags);
4584@@ -77,6 +78,7 @@ static int get_value(struct parse_opt_ctx_t *p,
4585 case OPTION_ARGUMENT:
4586 case OPTION_GROUP:
4587 case OPTION_STRING:
4588+ case OPTION_FILENAME:
4589 case OPTION_INTEGER:
4590 case OPTION_UINTEGER:
4591 case OPTION_LONG:
4592@@ -121,6 +123,19 @@ static int get_value(struct parse_opt_ctx_t *p,
4593 return get_arg(p, opt, flags, (const char **)opt->value);
4594 return 0;
4595
4596+ case OPTION_FILENAME:
4597+ err = 0;
4598+ if (unset)
4599+ *(const char **)opt->value = NULL;
4600+ else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
4601+ *(const char **)opt->value = (const char *)opt->defval;
4602+ else
4603+ err = get_arg(p, opt, flags, (const char **)opt->value);
4604+
4605+ if (!err)
4606+ fix_filename(p->prefix, (const char **)opt->value);
4607+ return err;
4608+
4609 case OPTION_CALLBACK:
4610 if (unset)
4611 return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
4612@@ -339,13 +354,14 @@ static void check_typos(const char *arg, const struct option *options)
4613 }
4614 }
4615
4616-void parse_options_start(struct parse_opt_ctx_t *ctx,
4617- int argc, const char **argv, int flags)
4618+void parse_options_start(struct parse_opt_ctx_t *ctx, int argc,
4619+ const char **argv, const char *prefix, int flags)
4620 {
4621 memset(ctx, 0, sizeof(*ctx));
4622 ctx->argc = argc - 1;
4623 ctx->argv = argv + 1;
4624 ctx->out = argv;
4625+ ctx->prefix = prefix;
4626 ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
4627 ctx->flags = flags;
4628 if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
4629@@ -453,8 +469,10 @@ int parse_options_end(struct parse_opt_ctx_t *ctx)
4630 return ctx->cpidx + ctx->argc;
4631 }
4632
4633-int parse_options_subcommand(int argc, const char **argv, const struct option *options,
4634- const char *const subcommands[], const char *usagestr[], int flags)
4635+static int parse_options_subcommand_prefix(int argc, const char **argv,
4636+ const char *prefix, const struct option *options,
4637+ const char *const subcommands[],
4638+ const char *usagestr[], int flags)
4639 {
4640 struct parse_opt_ctx_t ctx;
4641
4642@@ -474,7 +492,7 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
4643 strbuf_release(&buf);
4644 }
4645
4646- parse_options_start(&ctx, argc, argv, flags);
4647+ parse_options_start(&ctx, argc, argv, prefix, flags);
4648 switch (parse_options_step(&ctx, options, usagestr)) {
4649 case PARSE_OPT_HELP:
4650 exit(129);
4651@@ -503,10 +521,26 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
4652 return parse_options_end(&ctx);
4653 }
4654
4655+int parse_options_subcommand(int argc, const char **argv,
4656+ const struct option *options, const char *const subcommands[],
4657+ const char *usagestr[], int flags)
4658+{
4659+ return parse_options_subcommand_prefix(argc, argv, NULL, options,
4660+ subcommands, usagestr, flags);
4661+}
4662+
4663+int parse_options_prefix(int argc, const char **argv, const char *prefix,
4664+ const struct option *options,
4665+ const char * const usagestr[], int flags)
4666+{
4667+ return parse_options_subcommand_prefix(argc, argv, prefix, options,
4668+ NULL, (const char **) usagestr, flags);
4669+}
4670+
4671 int parse_options(int argc, const char **argv, const struct option *options,
4672 const char * const usagestr[], int flags)
4673 {
4674- return parse_options_subcommand(argc, argv, options, NULL,
4675+ return parse_options_subcommand_prefix(argc, argv, NULL, options, NULL,
4676 (const char **) usagestr, flags);
4677 }
4678
4679@@ -557,6 +591,7 @@ static void print_option_help(const struct option *opts, int full)
4680 if (opts->flags & PARSE_OPT_NOARG)
4681 break;
4682 /* FALLTHROUGH */
4683+ case OPTION_FILENAME:
4684 case OPTION_STRING:
4685 if (opts->argh) {
4686 if (opts->flags & PARSE_OPT_OPTARG)
4687diff --git a/util/parse-options.h b/util/parse-options.h
4688index 6fd6b24..fc5015a 100644
4689--- a/util/parse-options.h
4690+++ b/util/parse-options.h
4691@@ -38,6 +38,7 @@ enum parse_opt_type {
4692 OPTION_CALLBACK,
4693 OPTION_U64,
4694 OPTION_UINTEGER,
4695+ OPTION_FILENAME,
4696 };
4697
4698 enum parse_opt_flags {
4699@@ -135,6 +136,7 @@ struct option {
4700 #define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
4701 #define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
4702 #define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) }
4703+#define OPT_FILENAME(s, l, v, a, h) { .type = OPTION_FILENAME, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) }
4704 #define OPT_DATE(s, l, v, h) \
4705 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
4706 #define OPT_CALLBACK(s, l, v, a, h, f) \
4707@@ -156,6 +158,10 @@ extern int parse_options(int argc, const char **argv,
4708 const struct option *options,
4709 const char * const usagestr[], int flags);
4710
4711+extern int parse_options_prefix(int argc, const char **argv,
4712+ const char *prefix, const struct option *options,
4713+ const char * const usagestr[], int flags);
4714+
4715 extern int parse_options_subcommand(int argc, const char **argv,
4716 const struct option *options,
4717 const char *const subcommands[],
4718@@ -185,6 +191,7 @@ struct parse_opt_ctx_t {
4719 int argc, cpidx;
4720 const char *opt;
4721 int flags;
4722+ const char *prefix;
4723 };
4724
4725 extern int parse_options_usage(const char * const *usagestr,
4726@@ -192,8 +199,8 @@ extern int parse_options_usage(const char * const *usagestr,
4727 const char *optstr,
4728 bool short_opt);
4729
4730-extern void parse_options_start(struct parse_opt_ctx_t *ctx,
4731- int argc, const char **argv, int flags);
4732+extern void parse_options_start(struct parse_opt_ctx_t *ctx, int argc,
4733+ const char **argv, const char *prefix, int flags);
4734
4735 extern int parse_options_step(struct parse_opt_ctx_t *ctx,
4736 const struct option *options,
4737diff --git a/util/util.h b/util/util.h
4738index 162aade..001707e 100644
4739--- a/util/util.h
4740+++ b/util/util.h
4741@@ -79,6 +79,11 @@ static inline const char *skip_prefix(const char *str, const char *prefix)
4742 return strncmp(str, prefix, len) ? NULL : str + len;
4743 }
4744
4745+static inline int is_absolute_path(const char *path)
4746+{
4747+ return path[0] == '/';
4748+}
4749+
4750 void usage(const char *err) NORETURN;
4751 void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
4752 int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
4753@@ -87,5 +92,7 @@ void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
4754 char *xstrdup(const char *str);
4755 void *xrealloc(void *ptr, size_t size);
4756 int prefixcmp(const char *str, const char *prefix);
4757+char *prefix_filename(const char *pfx, const char *arg);
4758+void fix_filename(const char *prefix, const char **file);
4759
4760 #endif /* __UTIL_H__ */

Subscribers

People subscribed via source and target branches