| GENERAL CONSIDERATIONS |
| ====================== |
| |
| SCST has almost full features implementation of T10-PI standard |
| supporting all protection modes. The only missing feature is Application |
| Tag mode page. A patch implementing it is welcome. |
| |
| SCST T10-PI implementation has 2 modes of operations: |
| |
| 1. Computing. In this mode no protection information (PI) is stored. It |
| only checked upon arrival (WRITEs) and calculated from the data upon |
| sending (READs). Goal of this mode to provide protection against uplink, |
| i.e. path to initiator, corruptions. |
| |
| 2. Storing. In this mode PI is stored either in a file/device as simple |
| array with 8 bytes entries, or inside block device using block integrity |
| extensions. In this mode full end-to-end protection could be |
| implemented. |
| |
| In both "computing" and "storing" modes PI can be checked on any stages |
| of commands processing: |
| |
| 1. Target HW |
| |
| 2. SCST |
| |
| 3. Backend HW, if it supports block integrity extensions. |
| |
| Any of them or all can be independently enabled or disabled depending |
| from level of performance overhead and required protection. For |
| instance, the target HW stage is the cheapest from performance |
| perspective, but doesn't protect against corruptions or misdirections on |
| PCI bus between the target HW and system. Another example, if backend HW |
| supports T10-PI, no checks on other stages are generally needed, but can |
| be used to localize place where corruption happened. Checking on each |
| stage to be able to localize corruption place is the recommended by T10 |
| way of processing. |
| |
| |
| USER INTERFACE |
| ============== |
| |
| Currently only scst_vdisk handler supports T10-PI. |
| |
| See in the main README description of SCST sysfs attributes: |
| dif_capabilities, dif_checks_failed, dif_mode, dif_type, |
| dif_static_app_tag and dif_filename. |
| |
| Examples: |
| --------- |
| |
| dif_mode=tgt, dif_type=1 - TGT level only check, type 1 |
| |
| dif_mode=scst, dif_type=1, dif_static_app_tag=0x4149 - |
| SCST level only check, type 1, static app tag 0x4149 |
| |
| dif_mode=scst|dev_store, dif_type=1, dif_filename=/var/lib/scst/dif_tags/rd1_dif.dif - |
| SCST level only check and storing PI data in the file |
| |
| dif_mode=scst, dif_type=2 - SCST level only check, type 2 (32-byte commands) |
| |
| dif_mode=tag|scst|dev_check|dev_store, dif_type=1 - all levels check |
| storing tags using block integrity extensions, type 1 |
| |
| |
| INTERFACE BETWEEN SCST AND TARGET DRIVERS |
| ========================================= |
| |
| To support T10-PI struct scst_tgt_template has several new fields: |
| supported_dif_block_sizes, dif_supported, hw_dif_type1_supported, |
| hw_dif_type2_supported, hw_dif_type3_supported, hw_dif_ip_supported, |
| hw_dif_same_sg_layout_required. See their description in their comments |
| in scst.h. |
| |
| A READ-direction workflow from a target driver perspective should look |
| like: |
| |
| 1. No extra actions until xmit_response() stage* |
| |
| 2. On xmit_response() stage call scst_cmd_get_dif_sg(cmd)**. If returned |
| value is NULL, no further PI actions are needed. |
| |
| 3. Otherwise, call scst_get_read_dif_tgt_actions(cmd) to find out what |
| PI actions are needed. The return value has encoded 2 types of actions: |
| action itself and tags checks. |
| |
| Possible actions, which could be extracted by using scst_get_dif_action(), |
| are: |
| |
| - SCST_DIF_ACTION_STRIP - check, then strip the protection info, if it |
| is OK |
| |
| - SCST_DIF_ACTION_INSERT - insert the protection info |
| |
| - SCST_DIF_ACTION_PASS_CHECK - check the protection info, then pass it |
| to the initiator |
| |
| - SCST_DIF_ACTION_PASS - then pass the protection information to the |
| initiator without checking |
| |
| Possible tags checks, which could be extracted by using |
| scst_get_dif_checks() are: |
| |
| - SCST_DIF_CHECK_GUARD_TAG - check the guard tags |
| |
| - SCST_DIF_CHECK_REF_TAG - check the reference tags |
| |
| - SCST_DIF_CHECK_APP_TAG - check the application tags comparing them to |
| the static tag set by dif_static_app_tag attribute |
| |
| 4. Perform the requested PI actions and transfer PI from the returned |
| dif_sg together with the regular data**. |
| |
| |
| A WRITE-direction workflow from a target driver perspective should look |
| like: |
| |
| 1. No extra actions until rdy_to_xfer() stage* |
| |
| 2. On rdy_to_xfer() stage call scst_cmd_get_dif_sg(cmd)**. If returned |
| value is NULL, no further PI actions are needed. |
| |
| 3. Otherwise, call scst_get_write_dif_tgt_actions(cmd) to find out what |
| PI actions are needed. |
| |
| 4. Perform the requested PI actions and transfer PI to the returned |
| dif_sg together with regular data**. |
| |
| |
| (*) If the target driver uses custom data buffer, on this stage it must |
| together with data sg by scst_cmd_set_tgt_dif_sg() function also set the |
| corresponding PI sg. |
| |
| (**) The PI SG returned by scst_cmd_get_dif_sg() does not have the |
| corresponding SG-segments counter, because it is strictly bound to |
| number of blocks in the data SG. |
| |
| |
| You can find full external SCST T10-PI interface if you look in scst.h |
| functions with "_dif_" string in their name. They are well documented in |
| comments near them. |