linux/include/scsi/osd_initiator.h
<<
>>
Prefs
   1/*
   2 * osd_initiator.h - OSD initiator API definition
   3 *
   4 * Copyright (C) 2008 Panasas Inc.  All rights reserved.
   5 *
   6 * Authors:
   7 *   Boaz Harrosh <bharrosh@panasas.com>
   8 *   Benny Halevy <bhalevy@panasas.com>
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2
  12 *
  13 */
  14#ifndef __OSD_INITIATOR_H__
  15#define __OSD_INITIATOR_H__
  16
  17#include "osd_protocol.h"
  18#include "osd_types.h"
  19
  20#include <linux/blkdev.h>
  21#include <scsi/scsi_device.h>
  22
  23/* Note: "NI" in comments below means "Not Implemented yet" */
  24
  25/* Configure of code:
  26 * #undef if you *don't* want OSD v1 support in runtime.
  27 * If #defined the initiator will dynamically configure to encode OSD v1
  28 * CDB's if the target is detected to be OSD v1 only.
  29 * OSD v2 only commands, options, and attributes will be ignored if target
  30 * is v1 only.
  31 * If #defined will result in bigger/slower code (OK Slower maybe not)
  32 * Q: Should this be CONFIG_SCSI_OSD_VER1_SUPPORT and set from Kconfig?
  33 */
  34#define OSD_VER1_SUPPORT y
  35
  36enum osd_std_version {
  37        OSD_VER_NONE = 0,
  38        OSD_VER1 = 1,
  39        OSD_VER2 = 2,
  40};
  41
  42/*
  43 * Object-based Storage Device.
  44 * This object represents an OSD device.
  45 * It is not a full linux device in any way. It is only
  46 * a place to hang resources associated with a Linux
  47 * request Q and some default properties.
  48 */
  49struct osd_dev {
  50        struct scsi_device *scsi_device;
  51        unsigned def_timeout;
  52
  53#ifdef OSD_VER1_SUPPORT
  54        enum osd_std_version version;
  55#endif
  56};
  57
  58/* Unique Identification of an OSD device */
  59struct osd_dev_info {
  60        unsigned systemid_len;
  61        u8 systemid[OSD_SYSTEMID_LEN];
  62        unsigned osdname_len;
  63        u8 *osdname;
  64};
  65
  66/* Retrieve/return osd_dev(s) for use by Kernel clients
  67 * Use IS_ERR/ERR_PTR on returned "osd_dev *".
  68 */
  69struct osd_dev *osduld_path_lookup(const char *dev_name);
  70struct osd_dev *osduld_info_lookup(const struct osd_dev_info *odi);
  71void osduld_put_device(struct osd_dev *od);
  72
  73const struct osd_dev_info *osduld_device_info(struct osd_dev *od);
  74bool osduld_device_same(struct osd_dev *od, const struct osd_dev_info *odi);
  75
  76/* Add/remove test ioctls from external modules */
  77typedef int (do_test_fn)(struct osd_dev *od, unsigned cmd, unsigned long arg);
  78int osduld_register_test(unsigned ioctl, do_test_fn *do_test);
  79void osduld_unregister_test(unsigned ioctl);
  80
  81/* These are called by uld at probe time */
  82void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
  83void osd_dev_fini(struct osd_dev *od);
  84
  85/**
  86 * osd_auto_detect_ver - Detect the OSD version, return Unique Identification
  87 *
  88 * @od:     OSD target lun handle
  89 * @caps:   Capabilities authorizing OSD root read attributes access
  90 * @odi:    Retrieved information uniquely identifying the osd target lun
  91 *          Note: odi->osdname must be kfreed by caller.
  92 *
  93 * Auto detects the OSD version of the OSD target and sets the @od
  94 * accordingly. Meanwhile also returns the "system id" and "osd name" root
  95 * attributes which uniquely identify the OSD target. This member is usually
  96 * called by the ULD. ULD users should call osduld_device_info().
  97 * This rutine allocates osd requests and memory at GFP_KERNEL level and might
  98 * sleep.
  99 */
 100int osd_auto_detect_ver(struct osd_dev *od,
 101        void *caps, struct osd_dev_info *odi);
 102
 103static inline struct request_queue *osd_request_queue(struct osd_dev *od)
 104{
 105        return od->scsi_device->request_queue;
 106}
 107
 108/* we might want to use function vector in the future */
 109static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v)
 110{
 111#ifdef OSD_VER1_SUPPORT
 112        od->version = v;
 113#endif
 114}
 115
 116static inline bool osd_dev_is_ver1(struct osd_dev *od)
 117{
 118#ifdef OSD_VER1_SUPPORT
 119        return od->version == OSD_VER1;
 120#else
 121        return false;
 122#endif
 123}
 124
 125struct osd_request;
 126typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
 127
 128struct osd_request {
 129        struct osd_cdb cdb;
 130        struct osd_data_out_integrity_info out_data_integ;
 131        struct osd_data_in_integrity_info in_data_integ;
 132
 133        struct osd_dev *osd_dev;
 134        struct request *request;
 135
 136        struct _osd_req_data_segment {
 137                void *buff;
 138                unsigned alloc_size; /* 0 here means: don't call kfree */
 139                unsigned total_bytes;
 140        } cdb_cont, set_attr, enc_get_attr, get_attr;
 141
 142        struct _osd_io_info {
 143                struct bio *bio;
 144                u64 total_bytes;
 145                u64 residual;
 146                struct request *req;
 147                struct _osd_req_data_segment *last_seg;
 148                u8 *pad_buff;
 149        } out, in;
 150
 151        gfp_t alloc_flags;
 152        unsigned timeout;
 153        unsigned retries;
 154        unsigned sense_len;
 155        u8 sense[OSD_MAX_SENSE_LEN];
 156        enum osd_attributes_mode attributes_mode;
 157
 158        osd_req_done_fn *async_done;
 159        void *async_private;
 160        int async_error;
 161        int req_errors;
 162};
 163
 164static inline bool osd_req_is_ver1(struct osd_request *or)
 165{
 166        return osd_dev_is_ver1(or->osd_dev);
 167}
 168
 169/*
 170 * How to use the osd library:
 171 *
 172 * osd_start_request
 173 *      Allocates a request.
 174 *
 175 * osd_req_*
 176 *      Call one of, to encode the desired operation.
 177 *
 178 * osd_add_{get,set}_attr
 179 *      Optionally add attributes to the CDB, list or page mode.
 180 *
 181 * osd_finalize_request
 182 *      Computes final data out/in offsets and signs the request,
 183 *      making it ready for execution.
 184 *
 185 * osd_execute_request
 186 *      May be called to execute it through the block layer. Other wise submit
 187 *      the associated block request in some other way.
 188 *
 189 * After execution:
 190 * osd_req_decode_sense
 191 *      Decodes sense information to verify execution results.
 192 *
 193 * osd_req_decode_get_attr
 194 *      Retrieve osd_add_get_attr_list() values if used.
 195 *
 196 * osd_end_request
 197 *      Must be called to deallocate the request.
 198 */
 199
 200/**
 201 * osd_start_request - Allocate and initialize an osd_request
 202 *
 203 * @osd_dev:    OSD device that holds the scsi-device and default values
 204 *              that the request is associated with.
 205 * @gfp:        The allocation flags to use for request allocation, and all
 206 *              subsequent allocations. This will be stored at
 207 *              osd_request->alloc_flags, can be changed by user later
 208 *
 209 * Allocate osd_request and initialize all members to the
 210 * default/initial state.
 211 */
 212struct osd_request *osd_start_request(struct osd_dev *od, gfp_t gfp);
 213
 214enum osd_req_options {
 215        OSD_REQ_FUA = 0x08,     /* Force Unit Access */
 216        OSD_REQ_DPO = 0x10,     /* Disable Page Out */
 217
 218        OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
 219};
 220
 221/**
 222 * osd_finalize_request - Sign request and prepare request for execution
 223 *
 224 * @or:         osd_request to prepare
 225 * @options:    combination of osd_req_options bit flags or 0.
 226 * @cap:        A Pointer to an OSD_CAP_LEN bytes buffer that is received from
 227 *              The security manager as capabilities for this cdb.
 228 * @cap_key:    The cryptographic key used to sign the cdb/data. Can be null
 229 *              if NOSEC is used.
 230 *
 231 * The actual request and bios are only allocated here, so are the get_attr
 232 * buffers that will receive the returned attributes. Copy's @cap to cdb.
 233 * Sign the cdb/data with @cap_key.
 234 */
 235int osd_finalize_request(struct osd_request *or,
 236        u8 options, const void *cap, const u8 *cap_key);
 237
 238/**
 239 * osd_execute_request - Execute the request synchronously through block-layer
 240 *
 241 * @or:         osd_request to Executed
 242 *
 243 * Calls blk_execute_rq to q the command and waits for completion.
 244 */
 245int osd_execute_request(struct osd_request *or);
 246
 247/**
 248 * osd_execute_request_async - Execute the request without waitting.
 249 *
 250 * @or:                      - osd_request to Executed
 251 * @done: (Optional)         - Called at end of execution
 252 * @private:                 - Will be passed to @done function
 253 *
 254 * Calls blk_execute_rq_nowait to queue the command. When execution is done
 255 * optionally calls @done with @private as parameter. @or->async_error will
 256 * have the return code
 257 */
 258int osd_execute_request_async(struct osd_request *or,
 259        osd_req_done_fn *done, void *private);
 260
 261/**
 262 * osd_req_decode_sense_full - Decode sense information after execution.
 263 *
 264 * @or:           - osd_request to examine
 265 * @osi           - Recievs a more detailed error report information (optional).
 266 * @silent        - Do not print to dmsg (Even if enabled)
 267 * @bad_obj_list  - Some commands act on multiple objects. Failed objects will
 268 *                  be received here (optional)
 269 * @max_obj       - Size of @bad_obj_list.
 270 * @bad_attr_list - List of failing attributes (optional)
 271 * @max_attr      - Size of @bad_attr_list.
 272 *
 273 * After execution, osd_request results are analyzed using this function. The
 274 * return code is the final disposition on the error. So it is possible that a
 275 * CHECK_CONDITION was returned from target but this will return NO_ERROR, for
 276 * example on recovered errors. All parameters are optional if caller does
 277 * not need any returned information.
 278 * Note: This function will also dump the error to dmsg according to settings
 279 * of the SCSI_OSD_DPRINT_SENSE Kconfig value. Set @silent if you know the
 280 * command would routinely fail, to not spam the dmsg file.
 281 */
 282
 283/**
 284 * osd_err_priority - osd categorized return codes in ascending severity.
 285 *
 286 * The categories are borrowed from the pnfs_osd_errno enum.
 287 * See comments for translated Linux codes returned by osd_req_decode_sense.
 288 */
 289enum osd_err_priority {
 290        OSD_ERR_PRI_NO_ERROR    = 0,
 291        /* Recoverable, caller should clear_highpage() all pages */
 292        OSD_ERR_PRI_CLEAR_PAGES = 1, /* -EFAULT */
 293        OSD_ERR_PRI_RESOURCE    = 2, /* -ENOMEM */
 294        OSD_ERR_PRI_BAD_CRED    = 3, /* -EINVAL */
 295        OSD_ERR_PRI_NO_ACCESS   = 4, /* -EACCES */
 296        OSD_ERR_PRI_UNREACHABLE = 5, /* any other */
 297        OSD_ERR_PRI_NOT_FOUND   = 6, /* -ENOENT */
 298        OSD_ERR_PRI_NO_SPACE    = 7, /* -ENOSPC */
 299        OSD_ERR_PRI_EIO         = 8, /* -EIO    */
 300};
 301
 302struct osd_sense_info {
 303        enum osd_err_priority osd_err_pri;
 304
 305        int key;                /* one of enum scsi_sense_keys */
 306        int additional_code ;   /* enum osd_additional_sense_codes */
 307        union { /* Sense specific information */
 308                u16 sense_info;
 309                u16 cdb_field_offset;   /* scsi_invalid_field_in_cdb */
 310        };
 311        union { /* Command specific information */
 312                u64 command_info;
 313        };
 314
 315        u32 not_initiated_command_functions; /* osd_command_functions_bits */
 316        u32 completed_command_functions; /* osd_command_functions_bits */
 317        struct osd_obj_id obj;
 318        struct osd_attr attr;
 319};
 320
 321int osd_req_decode_sense_full(struct osd_request *or,
 322        struct osd_sense_info *osi, bool silent,
 323        struct osd_obj_id *bad_obj_list, int max_obj,
 324        struct osd_attr *bad_attr_list, int max_attr);
 325
 326static inline int osd_req_decode_sense(struct osd_request *or,
 327        struct osd_sense_info *osi)
 328{
 329        return osd_req_decode_sense_full(or, osi, false, NULL, 0, NULL, 0);
 330}
 331
 332/**
 333 * osd_end_request - return osd_request to free store
 334 *
 335 * @or:         osd_request to free
 336 *
 337 * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
 338 */
 339void osd_end_request(struct osd_request *or);
 340
 341/*
 342 * CDB Encoding
 343 *
 344 * Note: call only one of the following methods.
 345 */
 346
 347/*
 348 * Device commands
 349 */
 350void osd_req_set_master_seed_xchg(struct osd_request *or, ...);/* NI */
 351void osd_req_set_master_key(struct osd_request *or, ...);/* NI */
 352
 353void osd_req_format(struct osd_request *or, u64 tot_capacity);
 354
 355/* list all partitions
 356 * @list header must be initialized to zero on first run.
 357 *
 358 * Call osd_is_obj_list_done() to find if we got the complete list.
 359 */
 360int osd_req_list_dev_partitions(struct osd_request *or,
 361        osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
 362
 363void osd_req_flush_obsd(struct osd_request *or,
 364        enum osd_options_flush_scope_values);
 365
 366void osd_req_perform_scsi_command(struct osd_request *or,
 367        const u8 *cdb, ...);/* NI */
 368void osd_req_task_management(struct osd_request *or, ...);/* NI */
 369
 370/*
 371 * Partition commands
 372 */
 373void osd_req_create_partition(struct osd_request *or, osd_id partition);
 374void osd_req_remove_partition(struct osd_request *or, osd_id partition);
 375
 376void osd_req_set_partition_key(struct osd_request *or,
 377        osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
 378        u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
 379
 380/* list all collections in the partition
 381 * @list header must be init to zero on first run.
 382 *
 383 * Call osd_is_obj_list_done() to find if we got the complete list.
 384 */
 385int osd_req_list_partition_collections(struct osd_request *or,
 386        osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
 387        unsigned nelem);
 388
 389/* list all objects in the partition
 390 * @list header must be init to zero on first run.
 391 *
 392 * Call osd_is_obj_list_done() to find if we got the complete list.
 393 */
 394int osd_req_list_partition_objects(struct osd_request *or,
 395        osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
 396        unsigned nelem);
 397
 398void osd_req_flush_partition(struct osd_request *or,
 399        osd_id partition, enum osd_options_flush_scope_values);
 400
 401/*
 402 * Collection commands
 403 */
 404void osd_req_create_collection(struct osd_request *or,
 405        const struct osd_obj_id *);/* NI */
 406void osd_req_remove_collection(struct osd_request *or,
 407        const struct osd_obj_id *);/* NI */
 408
 409/* list all objects in the collection */
 410int osd_req_list_collection_objects(struct osd_request *or,
 411        const struct osd_obj_id *, osd_id initial_id,
 412        struct osd_obj_id_list *list, unsigned nelem);
 413
 414/* V2 only filtered list of objects in the collection */
 415void osd_req_query(struct osd_request *or, ...);/* NI */
 416
 417void osd_req_flush_collection(struct osd_request *or,
 418        const struct osd_obj_id *, enum osd_options_flush_scope_values);
 419
 420void osd_req_get_member_attrs(struct osd_request *or, ...);/* V2-only NI */
 421void osd_req_set_member_attrs(struct osd_request *or, ...);/* V2-only NI */
 422
 423/*
 424 * Object commands
 425 */
 426void osd_req_create_object(struct osd_request *or, struct osd_obj_id *);
 427void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *);
 428
 429void osd_req_write(struct osd_request *or,
 430        const struct osd_obj_id *obj, u64 offset, struct bio *bio, u64 len);
 431int osd_req_write_kern(struct osd_request *or,
 432        const struct osd_obj_id *obj, u64 offset, void *buff, u64 len);
 433void osd_req_append(struct osd_request *or,
 434        const struct osd_obj_id *, struct bio *data_out);/* NI */
 435void osd_req_create_write(struct osd_request *or,
 436        const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
 437void osd_req_clear(struct osd_request *or,
 438        const struct osd_obj_id *, u64 offset, u64 len);/* NI */
 439void osd_req_punch(struct osd_request *or,
 440        const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
 441
 442void osd_req_flush_object(struct osd_request *or,
 443        const struct osd_obj_id *, enum osd_options_flush_scope_values,
 444        /*V2*/ u64 offset, /*V2*/ u64 len);
 445
 446void osd_req_read(struct osd_request *or,
 447        const struct osd_obj_id *obj, u64 offset, struct bio *bio, u64 len);
 448int osd_req_read_kern(struct osd_request *or,
 449        const struct osd_obj_id *obj, u64 offset, void *buff, u64 len);
 450
 451/* Scatter/Gather write/read commands */
 452int osd_req_write_sg(struct osd_request *or,
 453        const struct osd_obj_id *obj, struct bio *bio,
 454        const struct osd_sg_entry *sglist, unsigned numentries);
 455int osd_req_read_sg(struct osd_request *or,
 456        const struct osd_obj_id *obj, struct bio *bio,
 457        const struct osd_sg_entry *sglist, unsigned numentries);
 458int osd_req_write_sg_kern(struct osd_request *or,
 459        const struct osd_obj_id *obj, void **buff,
 460        const struct osd_sg_entry *sglist, unsigned numentries);
 461int osd_req_read_sg_kern(struct osd_request *or,
 462        const struct osd_obj_id *obj, void **buff,
 463        const struct osd_sg_entry *sglist, unsigned numentries);
 464
 465/*
 466 * Root/Partition/Collection/Object Attributes commands
 467 */
 468
 469/* get before set */
 470void osd_req_get_attributes(struct osd_request *or, const struct osd_obj_id *);
 471
 472/* set before get */
 473void osd_req_set_attributes(struct osd_request *or, const struct osd_obj_id *);
 474
 475/*
 476 * Attributes appended to most commands
 477 */
 478
 479/* Attributes List mode (or V2 CDB) */
 480  /*
 481   * TODO: In ver2 if at finalize time only one attr was set and no gets,
 482   * then the Attributes CDB mode is used automatically to save IO.
 483   */
 484
 485/* set a list of attributes. */
 486int osd_req_add_set_attr_list(struct osd_request *or,
 487        const struct osd_attr *, unsigned nelem);
 488
 489/* get a list of attributes */
 490int osd_req_add_get_attr_list(struct osd_request *or,
 491        const struct osd_attr *, unsigned nelem);
 492
 493/*
 494 * Attributes list decoding
 495 * Must be called after osd_request.request was executed
 496 * It is called in a loop to decode the returned get_attr
 497 * (see osd_add_get_attr)
 498 */
 499int osd_req_decode_get_attr_list(struct osd_request *or,
 500        struct osd_attr *, int *nelem, void **iterator);
 501
 502/* Attributes Page mode */
 503
 504/*
 505 * Read an attribute page and optionally set one attribute
 506 *
 507 * Retrieves the attribute page directly to a user buffer.
 508 * @attr_page_data shall stay valid until end of execution.
 509 * See osd_attributes.h for common page structures
 510 */
 511int osd_req_add_get_attr_page(struct osd_request *or,
 512        u32 page_id, void *attr_page_data, unsigned max_page_len,
 513        const struct osd_attr *set_one);
 514
 515#endif /* __OSD_LIB_H__ */
 516