DDPTCTL(8)

πŸ“¦
version 0.97 Β· 2 versions
  • 0.97 Β· debian bookworm, debian trixie, fedora 43, fedora 44, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking (latest)
  • 0.95 Β· ubuntu jammy
, in debian bookworm, debian trixie, fedora 43, fedora 44, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking

okay so bestie, welcome to ddptctl(8) πŸ’– β€” this is the page from the DDPT manual, and she is a helper/auxiliary utility for ddpt. Grab a strawberry πŸ“ and let's get into it.

✨ NAME ✨

ddptctl β€” helper/auxiliary utility for ddpt


🌈 SYNOPSIS 🌈

       ddptctl [--abort] [--all_toks] [--block] [--del_tkn] [--flexible]
       [--help] [--immed] [--info] [--list_id=LID] [--oir=OIR] [--poll]
       [--pt=GL] [--readonly] [--prefer_rcs] [--receive] [--rtf=RTF]
       [--rtype=RTYPE] [--size] [--timeout=ITO[,CMD]] [--verbose] [--version]
       [--wut=SL] [DEVICE]

πŸ¦‹ DESCRIPTION πŸ¦‹

So this utility is a helper/auxiliary for the ddpt utility, which copies data between or within SCSI devices (logical units). And the way that ddpt's command line syntax is modelled on that of the POSIX dd command? Cute. But this utility has a more standard Unix command line syntax with both short and long variants of each option. Versatile queen πŸ‘‘.

The T10 committee defines a family of SCSI commands for offloaded copy. The central (but not the only) command is EXTENDED COPY, often shortened to XCOPY or xcopy. There are now two generations of xcopy: the older one is given the suffix "LID1" and the newer one: "LID4". There is a subset of XCOPY(LID4) that supports disk to disk copies and is based on the SBC-3 commands: POPULATE TOKEN (PT) and WRITE USING TOKEN (WUT). ODX is a market name that has become associated with this subset. This utility can issue PT, WUT and related commands, read the Third Party Copy VPD page and perform several other housekeeping tasks. She does it all, no cap πŸ’….

The xcopy family of commands are described in the SPC-4,5 and SBC-3,4 documents found at https://www.t10.org 🌐.

Apart from PT and WUT, other command abbreviations used below are RRTI for the RECEIVE ROD TOKEN INFORMATION command and RCS for the RECEIVE COPY STATUS(LID4) command. Not me dropping abbreviations like they're nothing 😭 β€” iykyk.

πŸ’… OPTIONS πŸ’…

ok so before we even get into it, one lil house rule bestie: arguments to long options are mandatory for short options as well. so if the long version wants a value, the short version wants that same value. no shortcuts, no exceptions. πŸ™ˆ


  • -A, --abort β€” this one fires off the COPY OPERATION ABORT command, using the LID you handed over in --list_id=LID. if you didn't give --list_id=LID, it just uses its default LID, which is 257. and if there's an xcopy operation actively going on on this I-T nexus (translation: it was issued by this machine to any LU sharing the same target) using that LID, then boom β€” the copy gets aborted. heads up tho: there's a sense key (COPY ABORTED) that means some but not all of the data got copied because of this. so yeah, it's giving partial. 😭
  • -a, --all_toks β€” sends the REPORT ALL ROD TOKENS SCSI command to DEVICE and decodes whatever comes back. lowkey important note: an ODX implementation is not required to support this command. so don't come for it if it says no. πŸ’€
  • -B, --block β€” treats DEVICE as a block device when it's checking its --size. the default behaviour of this utility is to treat DEVICE as a SCSI pass-through device instead. pick your fighter. ✨
  • -D, --del_tkn β€” sets the DEL_TKN bit in a WUT command (default: the DEL_TKN bit is clear). since an ODX copy manager deletes the ROD Token once its inactivity time-out hits, you typically don't need this option at all. it can be handy for long-lived ROD Tokens that you're just... done with. 🫢 to delete an unused ROD Token, a degenerate scatter list seems to be acceptable β€” like --wut=0,0 --del_tkn. iconic.
  • -f, --flexible β€” rn this option only affects how sgl_s gets parsed in files that are in hexadecimal and have a leading line with 'HEX' in them. without this option, any such line has to be invoked with 'H@' before the filename β€” in other words, the 'H' in the invocation has to match the HEX in the file. with this option tho, a sgl in a file can be invoked with just '@', and if a line with HEX gets parsed before any LBA,NUM pairs, it switches to hexadecimal mode β€” meaning all the parsed LBA,NUM pairs are assumed to be in hex. slay. πŸ”₯
  • -h, --help β€” spits out the usage message summarizing the command line options, then exits. the classic. πŸŽ€
  • -I, --immed β€” sets the IMMED bit in the PT or WUT command. when you give this, the PT and WUT commands return promptly, before the data transfer is complete β€” and then this utility exits. so you'll want to invoke the utility again with the --poll option, same LID and same DEVICE, to await completion and get the final transfer count. default behaviour of PT and WUT (i.e. without this option) is to wait for completion β€” all data transferred or an error occurs β€” before exiting. patient king behaviour. πŸ‘‘
  • -i, --info β€” when the DEVICE argument is given, it checks its Third Party Copy VPD page and prints out anything it finds. it also checks whether the 3PC bit is set in the standard INQUIRY response. if the DEVICE argument is not given and the --rtf=RTF option is given, then it decodes part of the ROD Token held in the --RTF file. SPC-4 defines some parts of a ROD Token that can be decoded, but it does not require the copy manager to set these fields β€” so many fields may show up as zeros. a --RTF file generated by the ddpt utility may contain multiple ROD Tokens, each optionally followed by an 8 byte "number of bytes represented" integer. they all get decoded, based on --RTF file length, which should either be a multiple of 512 or 520 bytes. πŸ’–
  • -l, --list_id=LID β€” LID is a list identifier, used to associate an originating xcopy command (like PT or WUT) with a follow-up command that retrieves associated info or aborts the operation. T10 requires each active LID to be unique on a given I-T nexus. an I-T nexus is the current machine (more precisely a HBA, if a machine has two or more) plus a specific target which will contain one or more logical units (LUs), of which DEVICE is one. if DEVICE's copy manager feels that rather complex condition hasn't been met, you get an error with sense data that decodes to "operation in progress". rather than try to work out who's doing what elsewhere β€” just try another LID value bestie. the default value for LID is 257. ✨
  • -O, --oir=OIR β€” OIR is the Offset In ROD, a field in the WUT command. it may be used together with the --wut=SL option. its default value is 0, and its units are the logical block size of DEVICE. 🌸
  • -p, --poll β€” sends the RRTI (or RCS) command to the DEVICE using the LID (i.e. from the --list_id=LID option). if a copy status comes back saying the operation is ongoing, then this SCSI command gets sent periodically (as suggested by the previous RRTI (or RCS) command, or every 500 milliseconds) until some other copy status is detected. if --list_id=LID isn't given, a LID of 257 is assumed. if the originating xcopy command was POPULATE TOKEN and the RRTI command says it completed successfully, then the associated ROD Token (returned in the RRTI response) gets written to the RTF file. if the --rtf=RTF option isn't given, then the ROD token gets written to a file called ddptctl_rod_tok.bin in the current directory. πŸ’…
  • -q, --prefer_rcs β€” prefers using the RECEIVE COPY STATUS (RCS) command over the RRTI command, which is the default. you should only do this following a WUT command, since after a PT command the RRTI command is needed to fetch the ROD Token. iykyk. πŸ¦‹
  • -P, --pt=GL β€” sends a POPULATE TOKEN (PT) command with the given gather list. the format of GL lives in the NOTES section. if you use it without the --immed option, then this utility β€” after the PT command finishes successfully β€” will call the RRTI command. when the RRTI command finishes, potentially with a new ROD Token, this utility exits. before that exit, if a new ROD Token is available and the --rtf=RTF option is given, that ROD Token gets written to the RTF file. if --rtf=RTF isn't given, the ROD token goes to a file called ddptctl_rod_tok.bin in the current directory. if the --immed option is given, this utility exits right after the PT command finishes. to complete the operation, invoke it again with the --poll option and the same DEVICE. πŸ”₯
  • -y, --readonly β€” opens the DEVICE read-only (e.g. in Unix, with the O_RDONLY flag). the default is to open it read-write. safety girlie. 🫢
  • -R, --receive β€” sends the RRTI (or RCS) SCSI command to the DEVICE using the LID (i.e. from the --list_id=LID option). if --list_id=LID isn't given, a LID of 257 is assumed. if the originating xcopy command was POPULATE TOKEN and the RRTI command says it completed successfully, then the associated ROD Token (returned in the RRTI response) gets written to the RTF file. if the --rtf=RTF option isn't given, the ROD token gets written to a file called ddptctl_rod_tok.bin in the current directory. ⭐
  • -r, --rtf=RTF β€” where RTF is a file containing an ODX ROD Token, or the name of a file the ROD Token is to be written to. a ROD Token used by ODX is 512 bytes long. if the RTF file was produced by the ddpt utility, it might contain multiple ROD Tokens, each optionally followed by an 8 byte integer containing the "number of bytes represented" by the preceding ROD Token. if an RTF file with multiple ROD Tokens is given to this utility with --wut=SL, then only the first ROD Token is used. if an RTF file is being decoded (i.e. no DEVICE argument given), then all ROD Tokens are decoded. 🌈
  • -t, --rtype=RTYPE β€” where RTYPE is the ROD Type, a field in the PT command (apart from "zero"). the default value (0) means the copy manager (in the DEVICE) decides. RTYPE can be a decimal number, a hex number (prefixed by 0x or with a h appended), or one of "pit-def", "pit-vuln", "pit-pers", "pit-cow", "pit-any" or "zero". the final truncated word can be spelt out (e.g. "pit-vulnerable"). the "pit-" lead-in stands for "point in time" copy. ✨ "zero" is a special case and is not given to a PT command. instead, it causes a special Block Device Zero Token to be created, which can be used with the --wut=SL option to write blocks of zeros to the given DEVICE. cute trick ngl. πŸŽ€
  • -s, --size β€” prints the number of blocks and the size of each block for the given DEVICE. protection information is printed if available. by default it uses the pass-through interface and the READ CAPACITY command to get this info. if the --block option is given, then the block layer in the OS is queried for size info (and protection information is not reported). πŸ‘‘
  • -T, --timeout=ITO[,CMD] β€” where ITO is the inactivity timeout (units: seconds) given to the PT command. the default is 0, in which case the copy manager uses its own default, which is shown in the Third party Copy VPD page. CMD is the SCSI command timeout (units: seconds) applied to SCSI commands issued by this utility; default is 0, which gets translated to 600 seconds for originating xcopy commands (e.g. PT and WUT) and 60 seconds for other commands.
bestie. best not to trigger command timeouts. just don't. 😭
  • -v, --verbose β€” increases the level of verbosity (i.e. debug output). the more you stack it, the more it yaps. πŸ’¬
  • -V, --version β€” prints the version string and then exits. periodt. πŸ’…
  • -w, --wut=SL β€” sends a WRITE USING TOKEN (WUT) command with the given scatter list. the format of SL is in the NOTES section. this option requires the --rtf=RTF option to supply the ROD Token. if used without the --immed option, then after the WUT command finishes successfully this utility calls the RRTI command. when the RRTI command finishes, this utility exits. if the --immed option is given, this utility exits right after the WUT command finishes. to complete the operation, invoke it again with the --poll option and the same DEVICE. πŸ¦‹

πŸ“ NOTES πŸ“ (the fine print, bestie, read it) πŸ“

So the scatter gather list you hand to --pt=GL and --wut=SL? In the simplest case it's literally just a pair of numbers separated by a comma. First number = the starting LBA. Second number = how many blocks to read from or write to that starting LBA (no bigger than 32 bits, ok?). Then you can slap another pair of numbers right after that and boom, that's the second element of your scatter gather list.

Starting LBAs can be in any order you want, but T10 says 🚫 no logical block is allowed to show up more than once in a scatter gather list. Periodt.


Scatter gather lists can live in a file or be piped in from stdin. If it's a file, the file name has to come after an @ character β€” like --pt=@my_sgl.txt. Want it from stdin? That's @- or just -, e.g. --pt=-. And here's the tea β˜•: lists in a file get a looser format and can use spaces and tabs as separators, not just commas. Anything from and including a # on a line is ignored (so go ahead and annotate, queen).

⚠️ Both the PT and WUT commands get issued "as is" β€” no checking of the Third Party Copy VPD page first. So the copy manager may absolutely reject them (with exit status 51: invalid field in parameter list) if the maximum range descriptors field or the maximum token transfer size field get exceeded. Not us being shady, just us being honest. 😭

There's a whole web page chatting about ddptctl and ddpt, XCOPY and ODX at https://sg.danny.cz/sg/ddpt_xcopy_odx.html β€” go read it, iykyk.


πŸšͺ EXIT STATUS πŸšͺ

ddptctl exits with status 0 when it's successful, slay. Any other time? The exit status for this utility is exactly the same as for ddpt. Go peek at the EXIT STATUS section in the ddpt man page, bestie. πŸ’…


✨ EXAMPLES ✨ (the fun part, fr fr)

First, fire off a PT command without the --immed option so RRTI gets called to complete the operation:

# ddptctl --pt=0x0,10k,20k,5k --rtf=aa.rt /dev/sdb
PT completes with a transfer count of 15360 [0x3c00]

That transfer count (10k + 5k == 15360) is telling you the operation was successful and the ROD Token is chillin' in the aa.rt file. πŸŽ€ Now take that ROD Token and use it to write to the same locations on /dev/sdc:

# ddptctl --rtf=aa.rt --wut=0x0,10k,20k,5k /dev/sdc
WUT completes with a transfer count of 15360 [0x3c00]

So the copy was successful. We ate and left no crumbs. πŸ”₯ Now let's take a closer look at the ROD token:

# ddptctl --info --rtf=aa.rt
Decoding information from ROD Token:
  ROD type: point in time copy - default [0x800000]
  Copy manager ROD Token identifier: 0x520000710000000c
  Creator Logical Unit descriptor:
    Peripheral Device type: 0x0
    Relative initiator port identifier: 0x0
    designator_type: NAA,  code_set: Binary
    associated with the addressed logical unit
      0x60002ac0000000000000000c00009502
  Number of bytes represented: 0 [0x0]
  Device type specific data (for disk) has block size of 0; unlikely so skip
  Target device descriptor: unexpected designator type [0x0]

T10 does not require implementations to supply much of the above (only the ROD type and the token length), so expect to see some empty fields. It's giving minimalist. πŸ™ˆ


Wanna see info about /dev/sdb that's relevant to ODX? Try:

# ddptctl --info /dev/sdb
  /dev/sdb [readcap]: num_blks=209715200 [0xc800000], blk_size=512, 107 GB
3PC (third party copy) bit set in standard INQUIRY response
 Third Party Copy VPD page:
 Block Device ROD Token Limits:
  Maximum Range Descriptors: 8
  Maximum Inactivity Timeout: 60 seconds
  Default Inactivity Timeout: 30 seconds
  Maximum Token Transfer Size: 524288
  Optimal Transfer Count: 524288

That maximum token transfer size β€” 524288 blocks, each 512 bytes, which gives you 256 MB β€” is the largest size a ROD Token created by /dev/sdb can hold. So use that number, and show the --immed option on the destination:

# ddptctl --pt=0x0,0x80000 --rtf=aa.rt /dev/sdb
PT completes with a transfer count of 524288 [0x80000]

# ddptctl --rtf=aa.rt --wut=0x0,0x80000 --immed /dev/sdc
Started ODX Write Using Token command in immediate mode.
User may need --list_id=257 on following invocation with --receive or
--poll for completion

# ddptctl --poll --rtf=aa.rt /dev/sdc
RRTI for Write using token: Operation completed without errors
  transfer count of 524288 [0x80000]

To copy larger amounts and/or with a larger number of scatter gather elements (than 8 "range descriptors"), use one of the four ODX variants in the ddpt utility. Go off. πŸ‘‘


πŸ‘‘ AUTHORS πŸ‘‘

Written by Douglas Gilbert. (The blueprint. The moment. The icon.) πŸ’œ


πŸ› REPORTING BUGS πŸ›

Report bugs to <dgilbert at interlog dot com>. Be nice about it, they're doing the lord's work.


Copyright Β© 2014-2021 Douglas Gilbert

This software is distributed under a FreeBSD license. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. (Yes bestie, that's in all caps in the original too β€” they were yelling. Respect. 😀)


🌈 SEE ALSO 🌈


ddpt-0.97, April 2021 β€” that's the version and date this whole DDPTCTL(8) page shipped with. Now go copy some blocks, gorgeous. πŸ¦‹πŸ’–βœ¨

πŸ“¦ where this page comes from