Inspect XCOPY Capability and Status with sg_copy_results
Before you ask an array to run an XCOPY, sg_copy_results tells you whether it even supports the facility. It queries a SCSI device's Extended Copy information, checks an active copy by list identifier, and keeps decoding separate from execution throughout, all without starting a copy. It uses the installed sg3-utils package version 1.46-3ubuntu4; the executable reports sg_copy_results: version: 1.23 20180625.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes for a read-only inspection. You need a Linux shell, sg3-utils, and a SCSI generic device path such as /dev/sg3 from your storage documentation. Some modern arrays support XCOPY; ordinary disks and USB bridges usually do not. These examples send SCSI commands to the named device but never start, stop or cancel a copy, though a maintenance window is still worth using since querying a production array has its own change controls.
1. Confirm the installed command
Check the package and binary before trusting a command copied from another host. Both checks are ordinary and need no elevated privileges:
$ dpkg-query -W -f='${Package} ${Version}\n' sg3-utils
sg3-utils 1.46-3ubuntu4
$ command -v sg_copy_results
/usr/bin/sg_copy_results
$ sg_copy_results --version
sg_copy_results: version: 1.23 20180625
Checkpoint
The command must be present, and its help should show the same four service-action selectors used below:
$ sg_copy_results --help
Usage: sg_copy_results [--failed|--params|--receive|--status] ... DEVICE
The installed syntax accepts long options and their short forms. Keep the option spelling from this host's help handy in case a later package changes it.
2. Identify the device path
Use the SCSI generic device that actually represents the target array or disk, not a guessed block-device name. If you already have a path from your storage inventory, assign it as a quoted shell variable:
$ DEVICE='/dev/sg3'
$ test -e "$DEVICE" && printf 'using %s\n' "$DEVICE"
using /dev/sg3
Replace /dev/sg3 with a real path on your host. Do not assume /dev/sg3 is safe just because it exists: SCSI generic numbering can shift after a rescan or reboot. Check the device identity with your normal inventory or an approved SCSI inspection tool before sending the query.
Most installations require permission to open the device. If the command reports a permission failure, rerun the same query with whatever privilege your host policy permits:
$ sudo sg_copy_results --params --readonly "$DEVICE"
sudo is not a fix for an unsupported command, only for access. Use the least privilege that gets the job done.
3. Query operating parameters first
Operating parameters are the useful starting point: they describe whether the target exposes XCOPY at all, and which descriptor limits it reports. --params is also the default, but spelling it out makes a runbook easier to review later:
$ sg_copy_results --params --readonly "$DEVICE"
Receive copy results (report operating parameters):
Supports no list identifier: no
Maximum target descriptor count: 2
Maximum segment descriptor count: 1
Maximum descriptor list length: 92 bytes
Maximum segment length: 33553920 bytes
Inline data not supported
Held data limit: 0 bytes
Maximum stream device transfer size: 0 bytes
Total concurrent copies: 0
Maximum concurrent copies: 255
Data segment granularity: 512 bytes
Inline data granularity: 1 bytes
Held data granularity: 1 bytes
Implemented descriptor list:
Segment descriptor 0x02: Copy from block device to block device
Target descriptor 0xe4: Identification descriptor
Your values will be device-specific. Treat this as capability data, not a promise that an arbitrary sg_xcopy request will succeed. A zero concurrent-copy value and an unsupported descriptor are useful constraints here, not an invitation to guess a different descriptor format.
Checkpoint
Record the complete output with the device identity and date. If the device returns a SCSI error or says the command is unsupported, stop and investigate the array's XCOPY support rather than retrying repeatedly.
4. Check the status of a copy
When an XCOPY operation has a list identifier, select the COPY STATUS service action with --status. The identifier defaults to zero, so always pass it explicitly when one is known:
$ LIST_ID='7'
$ sg_copy_results --status --list_id="$LIST_ID" --readonly "$DEVICE"
Receive copy results (report copy status):
... device-specific status fields ...
Exact fields and wording come from the target's own response; do not treat the ellipsis above as literal output. If your copy manager gave you a different identifier, use that instead of 7, since the default of zero is not a discovery mechanism.
--readonly opens the device with the Unix read-only flag. A sensible default for an inspection run, but it does not turn an unsupported or badly addressed SCSI command into a harmless local file read, so confirm the target path before running it.
5. Request failure details when status points to an error
For a failed segment, use --failed with the same list identifier:
$ sg_copy_results --failed --list_id="$LIST_ID" --readonly "$DEVICE"
Receive copy results (report failed segment details):
... device-specific sense and segment data ...
The response is target-specific and can include copy-target sense information when available. Preserve it alongside the original status response. A non-zero exit status means the utility did not complete successfully; the manpage points to sg3_utils(8) for the general exit-status and error conventions. Capture standard error along with standard output when handing the result to a storage vendor.
6. Request held data only when the target supports it
--receive selects RECEIVE DATA for the list identifier. The manpage says this is only meaningful when the relevant segment descriptors support held data, and that decoding this service action is not implemented by sg_copy_results at all. Treat that as a hard boundary, not a format you can safely eyeball:
$ sg_copy_results --receive --list_id="$LIST_ID" --readonly "$DEVICE"
Receive copy results (receive data):
... response or device-specific error ...
Run this only when the operating-parameters response and the XCOPY implementation documentation justify it. It does not retrieve arbitrary file contents, and this utility does not decode what comes back. Need the raw response for vendor analysis? Add --hex and save it to a controlled diagnostic file:
$ sg_copy_results --status --list_id="$LIST_ID" --hex --readonly "$DEVICE" \
> "xcopy-status-${LIST_ID}.hex"
$ test -s "xcopy-status-${LIST_ID}.hex" && printf 'saved diagnostic response\n'
saved diagnostic response
Diagnostic output may contain device or workload details, so protect it under your storage support policy and remove it through your normal records-retention process once it's no longer needed.
7. Tune the response length only for a reason
The allocation length defaults to 520 bytes. Use --xfer_len=BTL when you know the response needs a different maximum, keeping the value below 10000:
$ sg_copy_results --params --xfer_len=1024 --readonly "$DEVICE"
Receive copy results (report operating parameters):
... response is limited to at most 1024 bytes ...
A larger allocation length does not make the device return more than it actually supports, while a smaller value can truncate a response. Start with the default and change it only when device documentation or a captured response gives you a reason to. Use --verbose for debugging command details, not as a substitute for interpreting the target's SCSI response.
Done means
- You confirmed the local package, binary and utility version.
- You verified the SCSI generic path against device inventory.
- You queried operating parameters before attempting status or failure-detail requests.
- You passed the real XCOPY list identifier instead of relying on the default zero.
- You used
--readonlyand the least privilege needed to open the device. - You preserved non-zero errors and diagnostic output without claiming a failed query changed copy state.
- You did not treat RECEIVE DATA as decoded file content: this utility does not implement that decoding.