All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [RFC 00/14] open-osd: OSD Initiator library for Linux
       [not found] <48876009.8010701@panasas.com>
@ 2008-07-24 17:30 ` Boaz Harrosh
  2008-07-24 17:40   ` [RFC 01/14] libosd: OSDv1 Headers Boaz Harrosh
                     ` (13 more replies)
  2008-11-04 16:09   ` Boaz Harrosh
                   ` (2 subsequent siblings)
  3 siblings, 14 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 17:30 UTC (permalink / raw)
  To: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig


Submitted for review and discussion, an in-kernel OSD initiator
library. Its main users are planned to be various OSD based file
systems and most importantly the pNFS-Objects Layout Driver.
 
To try out and run the library please visit
http://open-osd.org and follow the instructions there.

The submitted patchset is also available via git at:
   git://git.open-osd.org/open-osd.git osd-dev
   http://git.open-osd.org/gitweb.cgi?p=open-osd.git;a=shortlog;h=osd-dev

Or a compact out-of-tree repository that includes sources 
and some extras:
   git://git.open-osd.org/osd-lib.git master
   http://git.open-osd.org/gitweb.cgi?p=osd-lib.git;a=summary

The submitted patches adds public header files to include/scsi/
for use by other subsystems. The source files and private headers 
are put at a new drivers/scsi/osd/ directory, with the privilege of
a separate Makefile and Kconfig.

here is the list of patches:

[PATCH 01/14] libosd: OSDv1 Headers
[PATCH 02/14] libosd: OSDv1 preliminary implementation
  Most basic, but usable library module (libosd.ko) including Makefile

[PATCH 03/14] osd_uld: OSD scsi ULD
[PATCH 04/14] osd_ktests: Add basic OSD tests
  The ULD and testing framework are orthogonal to the osd
  initiator library.  They are included in this patchset 
  mainly as a reference example for using the library
  and are not necessary candidates for inclusion into
  the kernel (although it will be very nice to have them
  there for everybody's benefit).  However, with out an OSD ULD,
  kernel users of the OSD initiator library (e.g. the pnfs-obj
  layout driver, or an OSD-based file system) will require
  an exported API function from the sg driver to be able to
  hook-up with the respective scsi_device.

[PATCH 05/14] libosd: attributes Support
[PATCH 06/14] osd_ktests: Test Attribute lists
  At this point there is enough functionality to be able to port IBM's OSDFS 
  project from sourceforge, to our initiator.
 
[PATCH 07/14] libosd: OSD Security processing stubs
[PATCH 08/14] libosd: Add Flush and List-objects support
[PATCH 09/14] libosd: Not implemented commands
[PATCH 10/14] libosd: OSD version 2 Support
[PATCH 11/14] osd_ktests: OSDv2 auto detection
  Misc additions and OSD2 support.

[PATCH 12/14] osd: Kconfig file for in-tree builds
[PATCH 13/14] osd: Documentation for OSD library
[PATCH 14/14] scsi: Add osd library to build system
  Up to the last patch it was only compilable from out-of-tree builds.
  Here a Kconfig is added and if enabled will be built from the Kernel
  Main Makefile.
 
Mostly missing from this body of work is the user-mode API and OSD 
functionality. We believe there are possible solutions for that, but this
is out of scope for this review. We would like to focus on the In-Kernel
API and users for now.

We invite everybody to comment, ask questions, and review the submitted
work and help us make it better, so it can be accepted into the Kernel.

Thanks
open-osd team



^ permalink raw reply	[flat|nested] 183+ messages in thread

* [RFC 01/14] libosd: OSDv1 Headers
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
@ 2008-07-24 17:40   ` Boaz Harrosh
  2008-07-24 17:45   ` [RFC 02/14] libosd: OSDv1 preliminary implementation Boaz Harrosh
                     ` (12 subsequent siblings)
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 17:40 UTC (permalink / raw)
  To: open-osd development
  Cc: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig, FUJITA Tomonori, linux-scsi


Headers only patch.

osd_protocol.h
	Contains a C-fied definition of the T10 OSD standard
osd_types.h
	Contains CPU order common used types
osd_initiator.h
	API definition of the osd_initiator library
osd_sec.h
	Contains High level API for the security manager.

[Note that checkpatch spews errors on things that are valid in this context
and will not be fixed]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 include/scsi/osd_initiator.h |  311 ++++++++++++++++++++++++++
 include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_sec.h       |   45 ++++
 include/scsi/osd_types.h     |   40 ++++
 4 files changed, 893 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_initiator.h
 create mode 100644 include/scsi/osd_protocol.h
 create mode 100644 include/scsi/osd_sec.h
 create mode 100644 include/scsi/osd_types.h

diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
new file mode 100644
index 0000000..a647c51
--- /dev/null
+++ b/include/scsi/osd_initiator.h
@@ -0,0 +1,311 @@
+/*
+ * osd_initiator.h - OSD initiator API definition
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_INITIATOR_H__
+#define __OSD_INITIATOR_H__
+
+#include <linux/blkdev.h>
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/* Note: "NI" in comments below means "Not Implemented yet" */
+
+/*
+ * Object-based Storage Device.
+ * This object represents an OSD device.
+ * It is not a full linux device in any way. It is only
+ * a place to hang resources associated with a Linux
+ * request Q and some default properties.
+ */
+struct osd_dev {
+	struct scsi_device *scsi_dev;
+	unsigned def_timeout;
+};
+
+void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
+void osd_dev_fini(struct osd_dev *);
+
+struct osd_request {
+	struct osd_cdb cdb;
+	struct osd_data_out_integrity_info out_data_integ;
+	struct osd_data_in_integrity_info in_data_integ;
+
+	struct osd_dev *osd_dev;
+	struct request *request;
+
+	struct _osd_req_data_segment {
+		void *buff;
+		unsigned alloc_size; /* 0 here means not allocated by us */
+		unsigned total_bytes;
+	} set_attr, enc_get_attr, get_attr;
+
+	struct _osd_io_info {
+		struct bio *bio;
+		u64 total_bytes;
+		struct request *req;
+		struct _osd_req_data_segment *last_seg;
+		u8 *pad_buff;
+	} out, in;
+
+	gfp_t alloc_flags;
+	unsigned timeout;
+	unsigned retries;
+	u8 sense[OSD_MAX_SENSE_LEN];
+	enum osd_attributes_mode attributes_mode;
+};
+
+/**
+ * How to use the osd library:
+ *
+ * osd_start_request
+ *	Allocates a request.
+ *
+ * osd_req_*
+ *	Call one of, to encode the desired operation.
+ *
+ * osd_add_{get,set}_attr
+ *	Optionally add attributes to the CDB, list or page mode.
+ *
+ * osd_finalize_request
+ *	Computes final data out/in offsets and signs the request,
+ *	making it ready for execution.
+ *
+ * osd_execute_request
+ *	May be called to execute it through the block layer. Other wise submit
+ *	the associated block request in some other way.
+ *
+ * After execution:
+ * osd_req_decode_sense
+ *	Decodes sense information to verify execution results.
+ *
+ * osd_req_decode_get_attr
+ *	Retrieve osd_add_get_attr_list() values if used.
+ *
+ * osd_end_request
+ *	Must be called to deallocate the request.
+ */
+
+/**
+ * osd_start_request - Allocate and initialize an osd_request
+ *
+ * @osd_dev:    OSD device that holds the scsi-device and default values
+ *              that the request is associated with.
+ * @gfp:        The allocation flags to use for request allocation, and all
+ *              subsequent allocations. This will be stored at
+ *              osd_request->alloc_flags, can be changed by user later
+ *
+ * Allocate osd_request and initialize all members to the
+ * default/initial state.
+ */
+struct osd_request *osd_start_request(struct osd_dev *, gfp_t gfp);
+
+enum osd_req_options {
+	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
+	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
+
+	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
+};
+
+/**
+ * osd_finalize_request - Sign request and prepare request for execution
+ *
+ * @or:		osd_request to prepare
+ * @options:	combination of osd_req_options bit flags or 0.
+ * @cap	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
+ *              The security manager as capabilities for this cdb.
+ * @cap_key	The cryptographic key used to sign the cdb/data. Can be null
+ *              if NOSEC is used.
+ *
+ * The actual request and bios are only allocated here, so are the get_attr
+ * buffers that will receive the returned attributes. Copy's @cap to cdb.
+ * Sign the cdb/data with @cap_key.
+ */
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key);
+
+/**
+ * osd_execute_request - Execute the request synchronously through
+ *                       the block-layer
+ * @or:		osd_request to Executed
+ *
+ * Calls blk_execute_rq to q the command and waits for completion.
+ */
+int osd_execute_request(struct osd_request *or);
+
+/**
+ * osd_end_request - return osd_request to free store
+ *
+ * @or:		osd_request to free
+ *
+ * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
+ */
+void osd_end_request(struct osd_request *or);
+
+/*
+ * CDB Encoding
+ *
+ * Note: call only one of the following methods.
+ */
+
+/*
+ * Device commands
+ */
+void osd_req_set_master_seed_xchg(struct osd_request *, ...);/* NI */
+void osd_req_set_master_key(struct osd_request *, ...);/* NI */
+
+void osd_req_format(struct osd_request *, u64 tot_capacity);
+
+/* list all partitions
+ * @list header must be initialized to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_dev_partitions(struct osd_request *,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
+
+void osd_req_flush_obsd(struct osd_request *,
+	enum osd_options_flush_scope_values);
+
+void osd_req_perform_scsi_command(struct osd_request *,
+	const u8 *cdb, ...);/* NI */
+void osd_req_task_management(struct osd_request *, ...);/* NI */
+
+/*
+ * Partition commands
+ */
+void osd_req_create_partition(struct osd_request *, osd_id partition);
+void osd_req_remove_partition(struct osd_request *, osd_id partition);
+
+void osd_req_set_partition_key(struct osd_request *,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
+
+/* list all collections in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_collections(struct osd_request *,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+/* list all objects in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_objects(struct osd_request *,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+void osd_req_flush_partition(struct osd_request *,
+	osd_id partition, enum osd_options_flush_scope_values);
+
+/*
+ * Collection commands
+ */
+void osd_req_create_collection(struct osd_request *,
+	const struct osd_obj_id *);/* NI */
+void osd_req_remove_collection(struct osd_request *,
+	const struct osd_obj_id *);/* NI */
+
+/* list all objects in the collection */
+int osd_req_list_collection_objects(struct osd_request *,
+	const struct osd_obj_id *, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem);
+
+/* V2 only filtered list of objects in the collection */
+void osd_req_query(struct osd_request *, ...);/* NI */
+
+void osd_req_flush_collection(struct osd_request *,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values);
+
+void osd_req_get_member_attrs(struct osd_request *, ...);/* V2-only NI */
+void osd_req_set_member_attrs(struct osd_request *, ...);/* V2-only NI */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *, struct osd_obj_id *);
+void osd_req_remove_object(struct osd_request *, struct osd_obj_id *);
+
+void osd_req_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);
+void osd_req_append(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out);/* NI */
+void osd_req_create_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
+void osd_req_clear(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
+void osd_req_punch(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
+
+void osd_req_flush_object(struct osd_request *,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values,
+	/*V2*/ u64 offset, /*V2*/ u64 len);
+
+void osd_req_read(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_in, u64 offset);
+
+/*
+ * Root/Partition/Collection/Object Attributes commands
+ */
+
+/* get before set */
+void osd_req_get_attributes(struct osd_request *, const struct osd_obj_id *);
+
+/* set before get */
+void osd_req_set_attributes(struct osd_request *, const struct osd_obj_id *);
+
+/*
+ * Attributes appended to most commands
+ */
+
+/* Attributes List mode (or V2 CDB) */
+  /*
+   * TODO: In ver2 if at finalize time only one attr was set and no gets,
+   * then the Attributes CDB mode is used automatically to save IO.
+   */
+
+/* set a list of attributes. */
+int osd_req_add_set_attr_list(struct osd_request *,
+	const struct osd_attr *, unsigned nelem);
+
+/* get a list of attributes */
+int osd_req_add_get_attr_list(struct osd_request *,
+	const struct osd_attr *, unsigned nelem);
+
+/*
+ * Attributes list decoding
+ * Must be called after osd_request.request was executed
+ * It is called in a loop to decode the returned get_attr
+ * (see osd_add_get_attr)
+ */
+int osd_req_decode_get_attr_list(struct osd_request *,
+	struct osd_attr *, int *nelem, void **iterator);
+
+/* Attributes Page mode */
+
+/*
+ * Read an attribute page and optionally set one attribute
+ *
+ * Retrieves the attribute page directly to a user buffer.
+ * @attr_page_data shall stay valid until end of execution.
+ * See osd_attributes.h for common page structures
+ */
+int osd_req_add_get_attr_page(struct osd_request *,
+	u32 page_id, void *attr_page_data, unsigned max_page_len,
+	const struct osd_attr *set_one);
+
+#endif /* __OSD_LIB_H__ */
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
new file mode 100644
index 0000000..77a74a3
--- /dev/null
+++ b/include/scsi/osd_protocol.h
@@ -0,0 +1,497 @@
+/*
+ * osd_protocol.h - OSD T10 standard C definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_PROTOCOL_H__
+#define __OSD_PROTOCOL_H__
+
+#include <linux/types.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+enum {
+	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
+	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
+	OSDv1_CAP_LEN = 80,
+	/* Latest supported version */
+	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
+	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
+	OSD_CAP_LEN = OSDv1_CAP_LEN,
+
+	OSD_SYSTEMID_LEN = 20,
+	OSD_CRYPTO_KEYID_SIZE = 20,
+	OSD_CRYPTO_SEED_SIZE = 4,
+	OSD_CRYPTO_NONCE_SIZE = 12,
+	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
+
+	OSD_PARTITION_FIRST_ID = 0x10000,
+	OSD_OBJECT_FIRST_ID = 0x10000,
+};
+
+/* (osd-r10 5.2.4)
+ * osd2r03: 5.2.3 Caching control bits
+ */
+enum osd_options_byte {
+	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
+	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
+};
+
+/*
+ * osd2r03: 5.2.5 Isolation.
+ * First 3 bits, V2-only.
+ * Also for attr 110h "default isolation method" at Root Information page
+ */
+enum osd_options_byte_isolation {
+	OSD_ISOLATION_DEFAULT = 0,
+	OSD_ISOLATION_NONE = 1,
+	OSD_ISOLATION_STRICT = 2,
+	OSD_ISOLATION_RANGE = 4,
+	OSD_ISOLATION_FUNCTIONAL = 5,
+	OSD_ISOLATION_VENDOR = 7,
+};
+
+/* (osd-r10: 6.7)
+ * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
+ */
+enum osd_options_flush_scope_values {
+	OSD_CDB_FLUSH_ALL = 0,
+	OSD_CDB_FLUSH_ATTR_ONLY = 1,
+
+	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
+	/* V2-only */
+	OSD_CDB_FLUSH_ALL_RANGE = 2,
+};
+
+/* osd2r03: 5.2.10 Timestamps control */
+enum {
+	OSD_CDB_NORMAL_TIMESTAMPS = 0,
+	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
+};
+
+/* (osd-r10: 5.2.2.1)
+ * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
+ *	2 bits at second nibble of command_specific_options byte
+ */
+enum osd_attributes_mode {
+	/* V2-only */
+	OSD_CDB_SET_ONE_ATTR = 0x10,
+
+	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
+	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
+
+	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
+};
+
+/* (osd-r10: 4.12.5)
+ * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
+ *	byte offset = mantissa * (2^(exponent+8))
+ *	struct {
+ *		unsigned mantissa: 28;
+ *		int exponent: 04;
+ *	}
+ */
+typedef __be32 __bitwise osd_cdb_offset;
+
+enum {
+	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
+	OSD_OFFSET_MAX_BITS = 28,
+
+	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MAX_SHIFT = 16,
+};
+
+/* Return the smallest allowed encoded offset that contains @offset.
+ *
+ * The actual encoded offset returned is @offset + *padding.
+ * (up to max_shift, non-inclusive)
+ */
+osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
+	int min_shift, int max_shift);
+
+/* Minimum alignment is 256 bytes
+ * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
+ * which is 8 to 23 but IBM code restricts it to 16, so be it.
+ */
+static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
+/* osd2r03: 5.2.1 Overview */
+struct osd_cdb_head {
+	struct scsi_varlen_cdb_hdr varlen_cdb;
+/*10*/	u8		options;
+	u8		command_specific_options;
+	u8		timestamp_control;
+/*13*/	u8		reserved1[3];
+/*16*/	__be64		partition;
+/*24*/	__be64		object;
+/*32*/	union { /* V1 vs V2 alignment differences */
+		struct __osdv1_cdb_addr_len {
+/*32*/			__be32 		list_identifier;/* Rarely used */
+/*36*/			__be64		length;
+/*44*/			__be64		start_address;
+		} __packed v1;
+	};
+/*52*/	union { /* selected attributes mode Page/List/Single */
+		struct osd_attributes_page_mode {
+/*52*/			__be32		get_attr_page;
+/*56*/			__be32		get_attr_alloc_length;
+/*60*/			osd_cdb_offset	get_attr_offset;
+
+/*64*/			__be32		set_attr_page;
+/*68*/			__be32		set_attr_id;
+/*72*/			__be32		set_attr_length;
+/*76*/			osd_cdb_offset	set_attr_offset;
+		} __packed attrs_page;
+
+		struct osd_attributes_list_mode {
+/*52*/			__be32		get_attr_desc_bytes;
+/*56*/			osd_cdb_offset	get_attr_desc_offset;
+
+/*60*/			__be32		get_attr_alloc_length;
+/*64*/			osd_cdb_offset	get_attr_offset;
+
+/*68*/			__be32		set_attr_bytes;
+/*72*/			osd_cdb_offset	set_attr_offset;
+			__be32 not_used;
+		} __packed attrs_list;
+
+		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
+		struct osd_attributes_cdb_mode {
+/*52*/			__be32		set_attr_page;
+/*56*/			__be32		set_attr_id;
+/*60*/			__be16		set_attr_len;
+/*62*/			u8		set_attr_val[80-62];
+		} __packed attrs_cdb;
+/*52*/		u8 get_set_attributes_parameters[80-52];
+	};
+} __packed;
+/*80*/
+
+/*160 v1*/
+struct osd_security_parameters {
+/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*192*/osd_cdb_offset	data_in_integrity_check_offset;
+/*196*/osd_cdb_offset	data_out_integrity_check_offset;
+} __packed;
+/*200 v1*/
+
+struct osdv1_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSDv1_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
+struct osd_cdb {
+	union {
+		struct osdv1_cdb v1;
+		u8 buff[OSD_TOTAL_CDB_LEN];
+	};
+} __packed;
+
+static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
+{
+	return (struct osd_cdb_head *)ocdb->buff;
+}
+
+/* define both version actions
+ * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
+ */
+#define OSD_ACT___(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
+
+/* V2 only actions */
+#define OSD_ACT_V2(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
+
+#define OSD_ACT_V1_V2(Name, Num1, Num2) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
+
+enum osd_service_actions {
+	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
+	OSD_ACT___(FORMAT_OSD,			0x01)
+	OSD_ACT___(CREATE,			0x02)
+	OSD_ACT___(LIST,			0x03)
+	OSD_ACT_V2(PUNCH,			0x04)
+	OSD_ACT___(READ,			0x05)
+	OSD_ACT___(WRITE,			0x06)
+	OSD_ACT___(APPEND,			0x07)
+	OSD_ACT___(FLUSH,			0x08)
+	OSD_ACT_V2(CLEAR,			0x09)
+	OSD_ACT___(REMOVE,			0x0A)
+	OSD_ACT___(CREATE_PARTITION,		0x0B)
+	OSD_ACT___(REMOVE_PARTITION,		0x0C)
+	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
+	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
+	OSD_ACT___(CREATE_AND_WRITE,		0x12)
+	OSD_ACT___(CREATE_COLLECTION,		0x15)
+	OSD_ACT___(REMOVE_COLLECTION,		0x16)
+	OSD_ACT___(LIST_COLLECTION,		0x17)
+	OSD_ACT___(SET_KEY,			0x18)
+	OSD_ACT___(SET_MASTER_KEY,		0x19)
+	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
+	OSD_ACT___(FLUSH_PARTITION,		0x1B)
+	OSD_ACT___(FLUSH_OSD,			0x1C)
+
+	OSD_ACT_V2(QUERY,			0x20)
+	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
+	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
+	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
+	OSD_ACT_V2(READ_MAP,			0x31)
+
+	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
+	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
+	/* 0x8F80 to 0x8FFF are Vendor specific */
+};
+
+/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
+struct osd_attributes_list_attrid {
+	__be32 page;
+	__be32 attr_id;
+} __packed;
+
+/*
+ * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
+ *                  for setting attributes
+ */
+struct osd_attributes_list_element {
+	__be32 page;
+	__be32 attr_id;
+	__be16 attr_bytes;
+	u8 attr_val[0];
+} __packed;
+
+enum {
+	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+};
+
+enum {
+	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
+	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
+};
+
+static inline unsigned osdv1_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
+}
+
+/*
+ * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
+ */
+enum osd_attr_list_types {
+	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
+	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
+	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
+	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
+};
+
+/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
+struct osd_attributes_list_multi_header {
+	__be64 object_id;
+	u8 object_type; /* object_type enum below */
+	u8 reserved[5];
+	__be16 list_bytes;
+	/* followed by struct osd_attributes_list_element's */
+};
+
+struct osdv1_attributes_list_header {
+	u8 type;	/* low 4-bit only */
+	u8 pad;
+	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
+{
+	return be16_to_cpu(h->list_bytes);
+}
+
+/* (osd-r10 6.13)
+ * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
+ *	for root_lstchg below
+ */
+enum {
+	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
+	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
+};
+
+/*
+ * osd2r03: 6.15.2 LIST command parameter data
+ * (Also for LIST COLLECTION)
+ */
+struct osd_obj_id_list {
+	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
+	__be64 continuation_id;
+	__be32 list_identifier;
+	u8 pad[3];
+	u8 root_lstchg;
+	__be64 object_ids[0];
+} __packed;
+
+static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
+	bool *is_changed)
+{
+	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
+	return 0 != list->continuation_id;
+}
+
+/*
+ * osd2r03: 4.12.4.5 The ALLDATA security method
+ */
+struct osd_data_out_integrity_info {
+	__be64 data_bytes;
+	__be64 set_attributes_bytes;
+	__be64 get_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_data_in_integrity_info {
+	__be64 data_bytes;
+	__be64 retrieved_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_timestamp {
+	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
+} __packed;
+/* FIXME: define helper functions to convert to/from osd time format */
+
+/*
+ * Capability & Security definitions
+ * osd2r03: 4.11.2.2 Capability format
+ * osd2r03: 5.2.8 Security parameters
+ */
+
+struct osd_key_identifier {
+	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+} __packed;
+
+/* for osd_capability.format */
+enum {
+	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
+	OSD_SEC_CAP_FORMAT_VER1 = 1,
+	OSD_SEC_CAP_FORMAT_VER2 = 2,
+};
+
+/* security_method */
+enum {
+	OSD_SEC_NOSEC = 0,
+	OSD_SEC_CAPKEY = 1,
+	OSD_SEC_CMDRSP = 2,
+	OSD_SEC_ALLDATA = 3,
+};
+
+enum object_type {
+	OSD_SEC_OBJ_ROOT = 0x1,
+	OSD_SEC_OBJ_PARTITION = 0x2,
+	OSD_SEC_OBJ_COLLECTION = 0x40,
+	OSD_SEC_OBJ_USER = 0x80,
+};
+
+enum osd_capability_bit_masks {
+	OSD_SEC_CAP_APPEND	= (1 << 0),
+	OSD_SEC_CAP_OBJ_MGMT	= (1 << 1),
+	OSD_SEC_CAP_REMOVE	= (1 << 2),
+	OSD_SEC_CAP_CREATE	= (1 << 3),
+	OSD_SEC_CAP_SET_ATTR	= (1 << 4),
+	OSD_SEC_CAP_GET_ATTR	= (1 << 5),
+	OSD_SEC_CAP_WRITE	= (1 << 6),
+	OSD_SEC_CAP_READ	= (1 << 7),
+
+	OSD_SEC_CAP_NONE1	= (1 << 8),
+	OSD_SEC_CAP_NONE2	= (1 << 9),
+	OSD_SEC_CAP_NONE3	= (1 << 10),
+	OSD_SEC_CAP_QUERY	= (1 << 11), /*v2 only*/
+	OSD_SEC_CAP_M_OBJECT	= (1 << 12), /*v2 only*/
+	OSD_SEC_CAP_POL_SEC	= (1 << 13),
+	OSD_SEC_CAP_GLOBAL	= (1 << 14),
+	OSD_SEC_CAP_DEV_MGMT	= (1 << 15),
+};
+
+/* for object_descriptor_type (hi nibble used) */
+enum {
+	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
+	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
+	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
+	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
+};
+
+/* (osd-r10:4.9.2.2)
+ * osd2r03:4.11.2.2 Capability format
+ */
+struct osd_capability_head {
+	u8 format; /* low nibble */
+	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
+	u8 security_method;
+	u8 reserved1;
+/*04*/	struct osd_timestamp expiration_time;
+/*10*/	u8 audit[30-10];
+/*30*/	u8 discriminator[42-30];
+/*42*/	struct osd_timestamp object_created_time;
+/*48*/	u8 object_type;
+	u8 permissions_bit_mask[54-49];
+/*54*/	u8 reserved2;
+/*55*/	u8 object_descriptor_type; /* high nibble */
+} __packed;
+
+/*56 v1*/
+struct osdv1_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 policy_access_tag;
+/*60*/			__be64 allowed_partition_id;
+/*68*/			__be64 allowed_object_id;
+/*76*/			__be32 reserved;
+		} __packed obj_desc;
+
+		u8 object_descriptor[80-56];/*24*/
+	};
+} __packed;
+/*80 v1*/
+
+struct osd_capability {
+	struct osd_capability_head h;
+	struct osdv1_cap_object_descriptor od;
+} __packed;
+
+/**
+ * osd_sec_set_caps - set cap-bits into the capabilities header
+ *
+ * @cap:	The osd_capability_head to set cap bits to.
+ * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
+ *
+ * permissions_bit_mask is unaligned use below to set into caps
+ * in a version independent way
+ */
+static inline void osd_sec_set_caps(struct osd_capability_head *cap,
+	u16 bit_mask)
+{
+	/*
+	 *Note: The bits above are defined LE order this is because this way
+	 *      they can grow in the future to more then 16, and still retain
+	 *      there constant values.
+	 */
+	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
+}
+
+#endif /* ndef __OSD_PROTOCOL_H__ */
diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h
new file mode 100644
index 0000000..4c09fee
--- /dev/null
+++ b/include/scsi/osd_sec.h
@@ -0,0 +1,45 @@
+/*
+ * osd_sec.h - OSD security manager API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_SEC_H__
+#define __OSD_SEC_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/*
+ * Contains types and constants of osd capabilities and security
+ * encoding/decoding.
+ * API is trying to keep security abstract so initiator of an object
+ * based pNFS client knows as little as possible about security and
+ * capabilities. It is the Server's osd-initiator place to know more.
+ * Also can be used by osd-target.
+ */
+void osd_sec_encode_caps(void *caps, ...);/* NI */
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1);
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_params);
+
+/* Conditionally sign the CDB according to security setting in ocdb
+ * with cap_key */
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key);
+
+/* Unconditionally sign the BIO data with cap_key.
+ * Check for osd_is_sec_alldata() was done prior to calling this. */
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key);
+
+/* Version independent copy of caps into the cdb */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps);
+
+#endif /* ndef __OSD_SEC_H__ */
diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h
new file mode 100644
index 0000000..ea5372d
--- /dev/null
+++ b/include/scsi/osd_types.h
@@ -0,0 +1,40 @@
+/*
+ * osd_types.h - Types and constants which are not part of the protocol.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Contains types and constants that are implementation specific and are
+ * used by more than one part of the osd library.
+ *     (Eg initiator/target/security_manager/...)
+ */
+#ifndef __OSD_TYPES_H__
+#define __OSD_TYPES_H__
+
+struct osd_systemid {
+	u8 data[OSD_SYSTEMID_LEN];
+};
+
+typedef u64 __bitwise osd_id;
+
+struct osd_obj_id {
+	osd_id partition;
+	osd_id id;
+};
+
+static const struct __weak osd_obj_id osd_root_object = {0, 0};
+
+struct osd_attr {
+	u32 page;
+	u32 attr_id;
+	u16 len;		/* byte count of operand */
+	void *val_ptr;		/* in network order */
+};
+
+#endif /* ndef __OSD_TYPES_H__ */
-- 
1.5.6.rc1.5.gadf6


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 02/14] libosd: OSDv1 preliminary implementation
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
  2008-07-24 17:40   ` [RFC 01/14] libosd: OSDv1 Headers Boaz Harrosh
@ 2008-07-24 17:45   ` Boaz Harrosh
  2008-07-24 17:47   ` [RFC 03/14] osd_uld: OSD scsi ULD Boaz Harrosh
                     ` (11 subsequent siblings)
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 17:45 UTC (permalink / raw)
  To: open-osd development
  Cc: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig, FUJITA Tomonori, linux-scsi


Implementation of the most basic OSD functionality and infrastructure.
Mainly Format, Create/Remove Partition, Create/Remove Object, and read/write.

- Add Makefile to compile libosd.ko
- osd_initiator.c Implementation file for osd_initiator.h and osd_sec.h APIs
- osd_debug - Some kprintf macro definitions

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Makefile        |   44 ++++
 drivers/scsi/osd/osd_debug.h     |   27 +++
 drivers/scsi/osd/osd_initiator.c |  419 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 490 insertions(+), 0 deletions(-)
 create mode 100755 drivers/scsi/osd/Makefile
 create mode 100644 drivers/scsi/osd/osd_debug.h
 create mode 100644 drivers/scsi/osd/osd_initiator.c

diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile
new file mode 100755
index 0000000..8ff2283
--- /dev/null
+++ b/drivers/scsi/osd/Makefile
@@ -0,0 +1,44 @@
+#
+# Makefile for the OSD modules (both in and out of tree)
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+
+in_tree ?= 1
+
+# libosd.ko - the OSD initiator Module
+ifeq ($(in_tree),0)
+CONFIG_SCSI_OSD_INITIATOR=m
+EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_DEBUG -DCONFIG_SCSI_OSD_INITIATOR_MODULE \
+	-I$(M)/../../../include
+endif
+libosd-objs := osd_initiator.o
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
+
+# Everything beyond this point is used to call the kernel Makefile in case of
+# an out-of-tree build
+
+# Kbuild verbosity
+V ?= 0
+
+# allow users to override these
+# e.g. to compile for a kernel that you aren't currently running
+KERNELRELEASE ?= $(shell uname -r)
+KSRC ?= /lib/modules/$(KERNELRELEASE)/build
+KBUILD_OUTPUT ?=
+
+# this is the basic Kbuild out-of-tree invocation, with the M= option
+KBUILD_BASE = +$(MAKE) -C $(KSRC) M=`pwd` KBUILD_OUTPUT=$(KBUILD_OUTPUT) $(KARCH) V=$(V)
+
+all:
+	$(KBUILD_BASE) in_tree=0 modules
+
+clean:
+	$(KBUILD_BASE) in_tree=0 clean
diff --git a/drivers/scsi/osd/osd_debug.h b/drivers/scsi/osd/osd_debug.h
new file mode 100644
index 0000000..0bc65fa
--- /dev/null
+++ b/drivers/scsi/osd/osd_debug.h
@@ -0,0 +1,27 @@
+/*
+ * osd_debug.h - Some kprintf macros
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_DEBUG_H__
+#define __OSD_DEBUG_H__
+
+#define OSD_ERR(fmt, a...) printk(KERN_ERR "osd: " fmt, ##a)
+#define OSD_INFO(fmt, a...) printk(KERN_NOTICE "osd: " fmt, ##a)
+
+#ifdef CONFIG_SCSI_OSD_DEBUG
+#define OSD_DEBUG(fmt, a...) \
+	printk(KERN_NOTICE "osd @%s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define OSD_DEBUG(fmt, a...) do {} while (0)
+#endif
+
+#endif /* ndef __OSD_DEBUG_H__ */
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
new file mode 100644
index 0000000..a1daded
--- /dev/null
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -0,0 +1,419 @@
+/*
+ * osd_initiator - Main body of the osd initiator library.
+ *
+ * Note: The file does not contain the advanced security functionality which
+ * is only needed by the security_manager's initiators.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+#include <scsi/scsi_device.h>
+
+#include "osd_debug.h"
+
+enum { OSD_REQ_RETRIES = 1 };
+
+#ifdef CONFIG_SCSI_OSD_INITIATOR_MODULE
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd initiator library libosd.ko");
+MODULE_LICENSE("GPL");
+#endif
+
+static inline void build_test(void)
+{
+	/* structures were not packed */
+	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
+}
+
+static unsigned _osd_req_cdb_len(struct osd_request *or)
+{
+	return OSDv1_TOTAL_CDB_LEN;
+}
+
+void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
+{
+	/* FIXME: Take the device reference */
+
+	memset(osdd, 0, sizeof(*osdd));
+	osdd->scsi_dev = scsi_dev;
+	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+	/* TODO: Allocate pools for osd_request attributes ... */
+}
+EXPORT_SYMBOL(osd_dev_init);
+
+void osd_dev_fini(struct osd_dev *osdd)
+{
+	/* TODO: De-allocate pools */
+
+	/* FIXME: Release the device reference */
+	osdd->scsi_dev = NULL;
+}
+EXPORT_SYMBOL(osd_dev_fini);
+
+struct osd_request *_osd_request_alloc(gfp_t gfp)
+{
+	struct osd_request *or;
+
+	/* TODO: Use mempool with one saved request */
+	or = kzalloc(sizeof(*or), gfp);
+	return or;
+}
+
+void _osd_request_free(struct osd_request *or)
+{
+	kfree(or);
+}
+
+struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp)
+{
+	struct osd_request *or;
+
+	or = _osd_request_alloc(gfp);
+	if (!or)
+		return NULL;
+
+	or->osd_dev = dev;
+	or->alloc_flags = gfp;
+	or->timeout = dev->def_timeout;
+	or->retries = OSD_REQ_RETRIES;
+
+	return or;
+}
+EXPORT_SYMBOL(osd_start_request);
+
+/*
+ * If osd_finalize_request() was called but the request was not executed through
+ * the block layer, then we must release BIOs.
+ */
+static void _abort_unexecuted_bios(struct request *rq)
+{
+	struct bio *bio;
+
+	while ((bio = rq->bio) != NULL) {
+		rq->bio = bio->bi_next;
+		bio_endio(bio, 0);
+	}
+}
+
+void osd_end_request(struct osd_request *or)
+{
+	struct request *rq = or->request;
+
+	if (rq) {
+		if (rq->next_rq) {
+			_abort_unexecuted_bios(rq->next_rq);
+			blk_put_request(rq->next_rq);
+		}
+
+		_abort_unexecuted_bios(rq);
+		blk_put_request(rq);
+	}
+	_osd_request_free(or);
+}
+EXPORT_SYMBOL(osd_end_request);
+
+int osd_execute_request(struct osd_request *or)
+{
+	return blk_execute_rq(or->request->q, NULL, or->request, 0);
+}
+EXPORT_SYMBOL(osd_execute_request);
+
+/*
+ * Common to all OSD commands
+ */
+
+static void _osdv1_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv1_cdb *ocdb = &or->cdb.v1;
+
+	/*
+	 * For speed, the commands
+	 *	OSD_ACT_PERFORM_SCSI_COMMAND	, V1 0x8F7E, V2 0x8F7C
+	 *	OSD_ACT_SCSI_TASK_MANAGEMENT	, V1 0x8F7F, V2 0x8F7D
+	 * are not supported here. Should pass zero and set after the call
+	 */
+	act &= __constant_cpu_to_be16(~0x0080); /* V1 action code */
+
+	OSD_DEBUG("OSDv1 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v1.length = cpu_to_be64(len);
+	ocdb->h.v1.start_address = cpu_to_be64(offset);
+}
+
+static void _osd_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	_osdv1_req_encode_common(or, act, obj, offset, len);
+}
+
+/*
+ * Device commands
+ */
+void osd_req_format(struct osd_request *or, u64 tot_capacity)
+{
+	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
+				tot_capacity);
+}
+EXPORT_SYMBOL(osd_req_format);
+
+/*
+ * Partition commands
+ */
+static void _osd_req_encode_partition(struct osd_request *or,
+	__be16 act, osd_id partition)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	_osd_req_encode_common(or, act, &par, 0, 0);
+}
+
+void osd_req_create_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_CREATE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_create_partition);
+
+void osd_req_remove_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_REMOVE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_remove_partition);
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_CREATE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_create_object);
+
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_REMOVE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_remove_object);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, bio->bi_size);
+	WARN_ON(or->out.bio || or->out.total_bytes);
+	bio->bi_rw |= (1 << BIO_RW);
+	or->out.bio = bio;
+	or->out.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_write);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_READ, obj, offset, bio->bi_size);
+	WARN_ON(or->in.bio || or->in.total_bytes);
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_read);
+
+/*
+ * osd_finalize_request and helpers
+ */
+
+static int _init_blk_request(struct osd_request *or,
+	bool has_in, bool has_out)
+{
+	gfp_t flags = or->alloc_flags;
+	struct scsi_device *scsi_dev = or->osd_dev->scsi_dev;
+	struct request_queue *q = scsi_dev->request_queue;
+	struct request *req;
+	int ret = -ENOMEM;
+
+	req = blk_get_request(q, has_out, flags);
+	if (!req)
+		goto out;
+
+	or->request = req;
+	req->cmd_type = REQ_TYPE_BLOCK_PC;
+	req->timeout = or->timeout;
+	req->retries = or->retries;
+	req->sense = or->sense;
+	req->sense_len = 0;
+
+	if (has_out) {
+		or->out.req = req;
+		if (has_in) {
+			/* allocate bidi request */
+			req = blk_get_request(q, READ, flags);
+			if (!req) {
+				OSD_DEBUG("blk_get_request for bidi failed\n");
+				goto out;
+			}
+			req->cmd_type = REQ_TYPE_BLOCK_PC;
+			or->in.req = or->request->next_rq = req;
+		}
+	} else if(has_in)
+		or->in.req = req;
+
+	ret = 0;
+out:
+	OSD_DEBUG("or=%p has_in=%d has_out=%d => %d, %p\n",
+			or, has_in, has_out, ret, or->request);
+	return ret;
+}
+
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	bool has_in, has_out;
+	int ret;
+
+	if (options & OSD_REQ_FUA)
+		cdbh->options |= OSD_CDB_FUA;
+
+	if (options & OSD_REQ_DPO)
+		cdbh->options |= OSD_CDB_DPO;
+
+	if (options & OSD_REQ_BYPASS_TIMESTAMPS)
+		cdbh->timestamp_control = OSD_CDB_BYPASS_TIMESTAMPS;
+
+	osd_set_caps(&or->cdb, cap);
+
+	has_in = or->in.bio || or->get_attr.total_bytes;
+	has_out = or->out.bio || or->set_attr.total_bytes ||
+		or->enc_get_attr.total_bytes;
+
+	ret = _init_blk_request(or, has_in, has_out);
+	if (ret)
+		return ret;
+
+	if (or->out.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->out.req,
+					or->out.bio);
+		if (ret)
+			return ret;
+		OSD_DEBUG("out bytes=%llu (bytes_req=%u)\n",
+			or->out.total_bytes, or->out.req->data_len);
+	}
+	if (or->in.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->in.req, or->in.bio);
+		if (ret)
+			return ret;
+		OSD_DEBUG("in bytes=%llu (bytes_req=%u)\n",
+			or->in.total_bytes, or->in.req->data_len);
+	}
+
+	if (!or->attributes_mode)
+		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+	cdbh->command_specific_options |= or->attributes_mode;
+
+	or->request->cmd = or->cdb.buff;
+	or->request->cmd_len = _osd_req_cdb_len(or);
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_finalize_request);
+
+/*
+ * Implementation of osd_sec.h API
+ * TODO: Move to a separate osd_sec.c file at a later stage.
+ */
+
+enum { OSD_SEC_CAP_V1_ALL_CAPS =
+	OSD_SEC_CAP_APPEND | OSD_SEC_CAP_OBJ_MGMT | OSD_SEC_CAP_REMOVE   |
+	OSD_SEC_CAP_CREATE | OSD_SEC_CAP_SET_ATTR | OSD_SEC_CAP_GET_ATTR |
+	OSD_SEC_CAP_WRITE  | OSD_SEC_CAP_READ     | OSD_SEC_CAP_POL_SEC  |
+	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
+};
+
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
+{
+	struct osd_capability *cap = caps;
+	u8 type;
+	u8 descriptor_type;
+
+	if (likely(obj->id)) {
+		if (unlikely(is_collection)) {
+			type = OSD_SEC_OBJ_COLLECTION;
+			descriptor_type = is_v1 ? OSD_SEC_OBJ_DESC_OBJ :
+						  OSD_SEC_OBJ_DESC_COL;
+		} else {
+			type = OSD_SEC_OBJ_USER;
+			descriptor_type = OSD_SEC_OBJ_DESC_OBJ;
+		}
+		WARN_ON(!obj->partition);
+	} else {
+		type = obj->partition ? OSD_SEC_OBJ_PARTITION :
+					OSD_SEC_OBJ_ROOT;
+		descriptor_type = OSD_SEC_OBJ_DESC_PAR;
+	}
+
+	memset(cap, 0, sizeof(*cap));
+
+	cap->h.format = OSD_SEC_CAP_FORMAT_VER1;
+	cap->h.integrity_algorithm__key_version = 0; /* MAKE_BYTE(0, 0); */
+	cap->h.security_method = OSD_SEC_NOSEC;
+/*	cap->expiration_time;
+	cap->AUDIT[30-10];
+	cap->discriminator[42-30];
+	cap->object_created_time; */
+	cap->h.object_type = type;
+	osd_sec_set_caps(&cap->h, OSD_SEC_CAP_V1_ALL_CAPS);
+	cap->h.object_descriptor_type = descriptor_type;
+	cap->od.obj_desc.policy_access_tag = 0;
+	cap->od.obj_desc.allowed_partition_id = cpu_to_be64(obj->partition);
+	cap->od.obj_desc.allowed_object_id = cpu_to_be64(obj->id);
+}
+EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
+
+void osd_set_caps(struct osd_cdb *cdb, const void *caps)
+{
+	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+}
-- 
1.5.6.rc1.5.gadf6



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 03/14] osd_uld: OSD scsi ULD
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
  2008-07-24 17:40   ` [RFC 01/14] libosd: OSDv1 Headers Boaz Harrosh
  2008-07-24 17:45   ` [RFC 02/14] libosd: OSDv1 preliminary implementation Boaz Harrosh
@ 2008-07-24 17:47   ` Boaz Harrosh
  2008-07-27 21:16     ` James Bottomley
  2008-07-24 17:49   ` [RFC 04/14] osd_ktests: Add basic OSD tests Boaz Harrosh
                     ` (10 subsequent siblings)
  13 siblings, 1 reply; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 17:47 UTC (permalink / raw)
  To: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig


Add a Linux driver module that registers as a SCSI ULD and probes for OSD type
SCSI devices.

When an OSD-type SCSI device is found a character device is created in the form
of /dev/osdX - where X goes from 0 up to hard coded 64.
The Major character device number used is *232*, which is free (as of Linux
v2.6.27). The same Major was used by the old IBM initiator project.

TODO: How to dynamically allocate a Major and have a /dev/osdX entry linked
to it? Do I need/should reserve the minor range in advance, if not how?

A single ioctl is currently supported that will invoke an in-kernel test on
the specified OSD device (lun).

osd_test: Also included is the bare bones user-mode program - osd_test - that
will open a given osd device and issue the test ioctl to kernel.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Makefile     |   10 ++
 drivers/scsi/osd/osd_ktests.h |   31 ++++
 drivers/scsi/osd/osd_test.c   |   74 +++++++++
 drivers/scsi/osd/osd_uld.c    |  331 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 446 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_ktests.h
 create mode 100644 drivers/scsi/osd/osd_test.c
 create mode 100644 drivers/scsi/osd/osd_uld.c

diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile
index 8ff2283..f89135d 100755
--- a/drivers/scsi/osd/Makefile
+++ b/drivers/scsi/osd/Makefile
@@ -22,6 +22,13 @@ endif
 libosd-objs := osd_initiator.o
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
 
+# osd.ko - SCSI ULD and char-device for testing
+ifeq ($(in_tree),0)
+CONFIG_SCSI_OSD_ULD=m
+endif
+osd-objs := osd_uld.o
+obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
+
 # Everything beyond this point is used to call the kernel Makefile in case of
 # an out-of-tree build
 
@@ -42,3 +49,6 @@ all:
 
 clean:
 	$(KBUILD_BASE) in_tree=0 clean
+
+osd_test: osd_test.o
+	$(CC) -o $@ $<
diff --git a/drivers/scsi/osd/osd_ktests.h b/drivers/scsi/osd/osd_ktests.h
new file mode 100644
index 0000000..b57ca86
--- /dev/null
+++ b/drivers/scsi/osd/osd_ktests.h
@@ -0,0 +1,31 @@
+/*
+ * osd_ktests.h - Define the ktests.c API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_KTESTS_H__
+#define __OSD_KTESTS_H__
+
+/* Tests from osd_ktests.c */
+/* TODO: Only one simple test for now. Later I will add a test definition
+ *	structure that will define what tests to preform and with some
+ *	parametrization, so concurrent tests could be run on same OSD lun
+ *	without stepping on each other. (E.g. Format called when other tests
+ *	are in progress)
+ */
+
+enum { OSD_TEST_ALL = 17 };
+
+#ifdef __KERNEL__
+extern int do_test_17(struct scsi_device *osd_dev);
+#endif /* __KERNEL__ */
+
+#endif /*ndef __OSD_KTESTS_H__*/
diff --git a/drivers/scsi/osd/osd_test.c b/drivers/scsi/osd/osd_test.c
new file mode 100644
index 0000000..dc74865
--- /dev/null
+++ b/drivers/scsi/osd/osd_test.c
@@ -0,0 +1,74 @@
+/*
+ * osd_test.c - A user-mode program that calls into the osd ULD
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "osd_ktests.h"
+
+void usage(void)
+{
+	printf("usage: osd_test /dev/osdX testNo\n");
+}
+
+int main(int argc, char *argv[])
+{
+	int osd_file, ret;
+
+	if (argc <= 1) {
+		usage();
+		return -2;
+	}
+
+	osd_file = open(argv[1], O_RDWR);
+	if (osd_file < 0) {
+		printf("Error opening <%s>\n", argv[1]);
+		return -3;
+	}
+
+	ret = ioctl(osd_file, OSD_TEST_ALL, 0);
+	if (ret) {
+		printf("ioctl 17 returned %d\n", ret);
+		return ret;
+	}
+
+	close(osd_file);
+	return 0;
+}
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
new file mode 100644
index 0000000..37797d4
--- /dev/null
+++ b/drivers/scsi/osd/osd_uld.c
@@ -0,0 +1,331 @@
+/*
+ * osd_uld.c - OSD Upper Layer Driver
+ *
+ * A Linux driver module that registers as a SCSI ULD and probes
+ * for OSD type SCSI devices.
+ * Currently only used for tests. Does not export any useful
+ * user-mode API.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+
+/* FIXME: #include <scsi/scsi.h> move below to scsi.h when
+ * submitting upstream
+ */
+#define TYPE_OSD            0x11
+
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_ioctl.h>
+
+/* FIXME: #include <linux/major.h> move below to major.h when
+ * submitting upstream
+ */
+#define SCSI_OSD_MAJOR 232
+#define SCSI_OSD_MAX_MINOR 64
+
+#include "osd_ktests.h"
+#include "osd_debug.h"
+
+static const char osd_name[] = "osd";
+static const char *osd_version_string = "open-osd 0.0.6";
+const char osd_symlink[] = "scsi_osd";
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SCSI_OSD_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_OSD);
+
+/*
+ * Device operations
+ */
+
+struct osd_uld_device {
+	int minor;
+	struct cdev cdev;
+	struct scsi_device *scsi_dev;
+	struct gendisk *disk;
+	struct device *class_member;
+};
+
+static int osd_uld_open(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *osd_dev = container_of(inode->i_cdev,
+					struct osd_uld_device, cdev);
+
+	/* cache osd_dev on file handle */
+	file->private_data = osd_dev;
+	OSD_DEBUG("osd_uld_open %p\n", osd_dev);
+	return 0;
+}
+
+static int osd_uld_release(struct inode *inode, struct file *file)
+{
+	OSD_DEBUG("osd_uld_release %p\n", file->private_data);
+	file->private_data = NULL;
+	return 0;
+}
+
+static long osd_uld_ioctl(struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	struct osd_uld_device *osd_dev = file->private_data;
+	int ret;
+
+	switch (cmd) {
+	case OSD_TEST_ALL:
+		OSD_DEBUG("Kernel test %d: osd_dev=%p\n", cmd, osd_dev);
+		/* TODO: Add some tests code here */
+		ret = 0;
+		break;
+	default:
+		OSD_ERR("Unknown osd_uld_ioctl %d\n", cmd);
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+/*
+ * Driver operation
+ */
+
+static const struct file_operations osd_fops = {
+	.owner          = THIS_MODULE,
+	.open           = osd_uld_open,
+	.release        = osd_uld_release,
+	.unlocked_ioctl = osd_uld_ioctl,
+};
+
+static struct class *osd_sysfs_class;
+static DEFINE_IDA(osd_minor_ida);
+
+static int osd_probe(struct device *dev)
+{
+	struct scsi_device *scsi_dev = to_scsi_device(dev);
+	struct gendisk *disk;
+	struct osd_uld_device *osd_dev;
+	int minor;
+	int error;
+
+	if (scsi_dev->type != TYPE_OSD)
+		return -ENODEV;
+
+	do {
+		if (!ida_pre_get(&osd_minor_ida, GFP_KERNEL))
+			return -ENODEV;
+
+		error = ida_get_new(&osd_minor_ida, &minor);
+	} while (error == -EAGAIN);
+
+	if (error)
+		return error;
+	if (minor >= SCSI_OSD_MAX_MINOR) {
+		error = -EBUSY;
+		goto err_retract_minor;
+	}
+
+	error = -ENOMEM;
+	osd_dev = kzalloc(sizeof(*osd_dev), GFP_KERNEL);
+	if (NULL == osd_dev)
+		goto err_retract_minor;
+
+	dev_set_drvdata(dev, osd_dev);
+	osd_dev->minor = minor;
+	osd_dev->scsi_dev = scsi_dev;
+
+	/* allocate a disk and set it up */
+	/* FIXME: do we need this since sg has already done that */
+	disk = alloc_disk(1);
+	if (!disk) {
+		OSD_ERR("alloc_disk failed\n");
+		goto err_free_osd;
+	}
+	disk->major = SCSI_OSD_MAJOR;
+	disk->first_minor = osd_dev->minor;
+	sprintf(disk->disk_name, "osd%d", osd_dev->minor);
+	osd_dev->disk = disk;
+
+	OSD_DEBUG("start SCSI_IOCTL_TEST_UNIT_READY %p %p %p\n",
+			osd_dev, scsi_dev, scsi_dev->request_queue);
+
+	/* FIXME: this should go away eventually */
+	error = scsi_test_unit_ready(scsi_dev, 10*HZ, 5, NULL);
+	if (error)
+		OSD_ERR("warning: scsi_test_unit_ready failed\n");
+
+	/* init the char-device for communication with user-mode */
+	cdev_init(&osd_dev->cdev, &osd_fops);
+	osd_dev->cdev.owner = THIS_MODULE;
+	error = cdev_add(&osd_dev->cdev,
+			 MKDEV(SCSI_OSD_MAJOR, osd_dev->minor), 1);
+	if (error) {
+		OSD_ERR("cdev_add failed\n");
+		goto err_put_disk;
+	}
+
+	/* class_member */
+	osd_dev->class_member = device_create(osd_sysfs_class, dev,
+		MKDEV(SCSI_OSD_MAJOR, osd_dev->minor), "%s", disk->disk_name);
+	if (IS_ERR(osd_dev->class_member)) {
+		OSD_ERR("class_device_create failed\n");
+		error = PTR_ERR(osd_dev->class_member);
+		goto err_put_cdev;
+	}
+
+	dev_set_drvdata(osd_dev->class_member, osd_dev);
+	error = sysfs_create_link(&scsi_dev->sdev_gendev.kobj,
+				  &osd_dev->class_member->kobj, osd_symlink);
+	if (error)
+		OSD_ERR("warning: unable to make symlink\n");
+
+	OSD_INFO("osd_probe %s\n", disk->disk_name);
+	return 0;
+
+err_put_cdev:
+	cdev_del(&osd_dev->cdev);
+err_put_disk:
+	put_disk(disk);
+err_free_osd:
+	dev_set_drvdata(dev, NULL);
+	kfree(osd_dev);
+	scsi_device_put(scsi_dev);
+err_retract_minor:
+	ida_remove(&osd_minor_ida, minor);
+	return error;
+}
+
+static int osd_remove(struct device *dev)
+{
+	struct scsi_device *scsi_dev = to_scsi_device(dev);
+	struct osd_uld_device *osd_dev = dev_get_drvdata(dev);
+
+	if (!osd_dev || (osd_dev->scsi_dev != scsi_dev)) {
+		OSD_ERR("Half cooked osd-device %p,%p || %p!=%p",
+			dev, osd_dev, osd_dev ? osd_dev->scsi_dev : NULL,
+			scsi_dev);
+	}
+
+	OSD_INFO("osd_remove %s\n",
+		 osd_dev->disk ? osd_dev->disk->disk_name : NULL);
+
+	sysfs_remove_link(&scsi_dev->sdev_gendev.kobj, osd_symlink);
+
+	if (osd_dev->class_member)
+		device_destroy(osd_sysfs_class,
+			       MKDEV(SCSI_OSD_MAJOR, osd_dev->minor));
+	if (osd_dev->cdev.owner)
+		cdev_del(&osd_dev->cdev);
+	if (osd_dev->disk)
+		put_disk(osd_dev->disk);
+
+	ida_remove(&osd_minor_ida, osd_dev->minor);
+	kfree(osd_dev);
+	return 0;
+}
+
+/*
+ * Global driver registration
+ */
+static struct scsi_driver osd_driver = {
+	.owner			= THIS_MODULE,
+	.gendrv = {
+		.name		= osd_name,
+		.probe		= osd_probe,
+		.remove		= osd_remove,
+	}
+};
+
+static int __init osd_uld_init(void)
+{
+	int err;
+
+	osd_sysfs_class = class_create(THIS_MODULE, osd_symlink);
+	if (IS_ERR(osd_sysfs_class)) {
+		OSD_ERR("Unable to register sysfs class => %ld\n",
+			PTR_ERR(osd_sysfs_class));
+		return PTR_ERR(osd_sysfs_class);
+	}
+
+	err = register_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0),
+				     SCSI_OSD_MAX_MINOR, osd_name);
+	if (err) {
+		OSD_ERR("Unable to register major %d for osd ULD => %d\n",
+			SCSI_OSD_MAJOR, err);
+		goto err_out;
+	}
+
+	err = scsi_register_driver(&osd_driver.gendrv);
+	if (err) {
+		OSD_ERR("scsi_register_driver failed => %d\n", err);
+		goto err_out_chrdev;
+	}
+
+/* TODO: Add osd_specific sysfs nodes here
+	err = osd_create_sysfs_files(&osd_driver.gendrv);
+	if (err)
+		goto err_out_scsidrv; */
+
+	OSD_INFO("LOADED %s\n", osd_version_string);
+	return 0;
+
+/* err_out_scsidrv:
+	scsi_unregister_driver(&osd_driver.gendrv); */
+err_out_chrdev:
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+err_out:
+	class_destroy(osd_sysfs_class);
+	return err;
+}
+
+static void __exit osd_uld_exit(void)
+{
+/*	TODO: Remove osd_specific sysfs nodes
+	osd_remove_sysfs_files(&osd_driver.gendrv);*/
+
+	scsi_unregister_driver(&osd_driver.gendrv);
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+	class_destroy(osd_sysfs_class);
+	OSD_INFO("UNLOADED %s\n", osd_version_string);
+}
+
+module_init(osd_uld_init);
+module_exit(osd_uld_exit);
-- 
1.5.6.rc1.5.gadf6



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 04/14] osd_ktests: Add basic OSD tests
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
                     ` (2 preceding siblings ...)
  2008-07-24 17:47   ` [RFC 03/14] osd_uld: OSD scsi ULD Boaz Harrosh
@ 2008-07-24 17:49   ` Boaz Harrosh
  2008-07-24 17:51   ` [RFC 05/14] libosd: attributes Support Boaz Harrosh
                     ` (9 subsequent siblings)
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 17:49 UTC (permalink / raw)
  To: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig


Currently testing what is implemented in the osd_initiator library. That is -
format, create/remove partition, create/remove object, read and write to
objects.

This test passes against the IBM-OSD-SIM OSDv1 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Makefile     |    2 +-
 drivers/scsi/osd/osd_ktests.c |  332 +++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/osd/osd_uld.c    |    3 +-
 3 files changed, 334 insertions(+), 3 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_ktests.c

diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile
index f89135d..9edafc4 100755
--- a/drivers/scsi/osd/Makefile
+++ b/drivers/scsi/osd/Makefile
@@ -26,7 +26,7 @@ obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
 ifeq ($(in_tree),0)
 CONFIG_SCSI_OSD_ULD=m
 endif
-osd-objs := osd_uld.o
+osd-objs := osd_uld.o osd_ktests.o
 obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
 
 # Everything beyond this point is used to call the kernel Makefile in case of
diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
new file mode 100644
index 0000000..98dd67d
--- /dev/null
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -0,0 +1,332 @@
+/*
+ * osd_ktests.c - An osd_initiator library in-kernel test suite
+ *              called by the osd_uld module
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+#include "osd_debug.h"
+
+#include <linux/vmalloc.h>
+#include <scsi/scsi_device.h>
+
+enum {
+	K = 1024,
+	M = 1024 * K,
+	G = 1024 * M,
+};
+
+const u64 format_total_capacity = 128 * M;
+const osd_id first_par_id = 0x17171717L;
+const osd_id first_obj_id = 0x18181818L;
+const unsigned BUFF_SIZE = PAGE_SIZE;
+
+const int num_partitions = 1;
+const int num_objects = 2; /* per partition */
+
+int test_exec(struct osd_request *or, void *caps, const struct osd_obj_id *obj)
+{
+	int ret;
+
+	osd_sec_init_nosec_doall_caps(caps, obj, false, true);
+	ret = osd_finalize_request(or, 0, caps, NULL);
+	if (ret)
+		return ret;
+
+	ret = osd_execute_request(or);
+	/* osd_req_decode_sense(or, ret); */
+	return ret;
+}
+
+#define KTEST_START_REQ(osd_dev, or) do { \
+	or = osd_start_request(osd_dev, GFP_KERNEL); \
+	if (!or) { \
+		OSD_ERR("Error @%s:%d: osd_start_request", __func__,\
+			__LINE__); \
+		return -ENOMEM; \
+	} \
+} while (0)
+
+#define KTEST_EXEC_END(or, obj, g_caps, msg) do { \
+	ret = test_exec(or, g_caps, obj); \
+	osd_end_request(or); \
+	if (ret) { \
+		OSD_ERR("Error executing "msg" => %d\n", ret); \
+		return ret; \
+	} \
+	OSD_DEBUG(msg "\n"); \
+} while (0)
+
+int ktest_format(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+
+	KTEST_START_REQ(osd_dev, or);
+	osd_req_format(or, format_total_capacity);
+	KTEST_EXEC_END(or, &osd_root_object, g_caps, "format");
+	return 0;
+}
+
+int ktest_creat_par(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p;
+
+	for (p = 0; p < num_partitions; p++) {
+		struct osd_obj_id par = {
+			.partition = first_par_id + p,
+			.id = 0
+		};
+
+		KTEST_START_REQ(osd_dev, or);
+		osd_req_create_partition(or, par.partition);
+		KTEST_EXEC_END(or, &par, g_caps, "create_partition");
+	}
+
+	return 0;
+}
+
+int ktest_creat_obj(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			osd_req_create_object(or, &obj);
+			KTEST_EXEC_END(or, &obj, g_caps, "create_object");
+		}
+
+	return 0;
+}
+
+int ktest_write_obj(struct osd_dev *osd_dev, void *write_buff)
+{
+	struct request_queue *req_q = osd_dev->scsi_dev->request_queue;
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o; u64 offset = 0;
+	struct bio *write_bio;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			write_bio = bio_map_kern(req_q, write_buff,
+						 BUFF_SIZE, GFP_KERNEL);
+			if (!write_bio) {
+				OSD_ERR("!!! Failed to allocate write BIO\n");
+				return -ENOMEM;
+			}
+
+			osd_req_write(or, &obj, write_bio, offset);
+			KTEST_EXEC_END(or, &obj, g_caps, "write");
+			write_bio = NULL; /* released by scsi_midlayer */
+			offset += BUFF_SIZE;
+		}
+
+	return 0;
+}
+
+int ktest_read_obj(struct osd_dev *osd_dev, void *write_buff, void *read_buff)
+{
+	struct request_queue *req_q = osd_dev->scsi_dev->request_queue;
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o; u64 offset = 0;
+	struct bio *read_bio;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			read_bio = bio_map_kern(req_q, read_buff,
+						BUFF_SIZE, GFP_KERNEL);
+			if (!read_bio) {
+				OSD_ERR("!!! Failed to allocate read BIO\n");
+				return -ENOMEM;
+			}
+
+			osd_req_read(or, &obj, read_bio, offset);
+			KTEST_EXEC_END(or, &obj, g_caps, "read");
+			read_bio = NULL;
+			if (memcmp(read_buff, write_buff, BUFF_SIZE))
+				OSD_ERR("!!! Read did not compare");
+			offset += BUFF_SIZE;
+		}
+
+	return 0;
+}
+
+int ktest_remove_obj(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			osd_req_remove_object(or, &obj);
+			KTEST_EXEC_END(or, &obj, g_caps, "remove_object");
+		}
+
+	return 0;
+}
+
+int ktest_remove_par(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p;
+
+	for (p = 0; p < num_partitions; p++) {
+		struct osd_obj_id par = {
+			.partition = first_par_id + p,
+			.id = 0
+		};
+
+		KTEST_START_REQ(osd_dev, or);
+		osd_req_remove_partition(or, par.partition);
+		KTEST_EXEC_END(or, &par, g_caps, "remove_partition");
+	}
+
+	return 0;
+}
+
+int do_test_17(struct scsi_device *scsi_dev)
+{
+	struct osd_dev osd_dev;
+	void *write_buff = NULL;
+	void *read_buff = NULL;
+	int ret = -ENOMEM, i;
+
+	osd_dev_init(&osd_dev, scsi_dev);
+
+/* osd_format */
+	if (ktest_format(&osd_dev))
+		goto dev_fini;
+
+/* create some partition */
+	if (ktest_creat_par(&osd_dev))
+		goto dev_fini;
+/* list partition see if they're all there */
+/* create some objects on some partitions */
+	if (ktest_creat_obj(&osd_dev))
+		goto dev_fini;
+
+/* Alloc some buffers and bios */
+/*	write_buff = kmalloc(BUFF_SIZE, or->alloc_flags);*/
+/*	read_buff = kmalloc(BUFF_SIZE, or->alloc_flags);*/
+	write_buff = (void *)__get_free_page(GFP_KERNEL);
+	read_buff = (void *)__get_free_page(GFP_KERNEL);
+	if (!write_buff || !read_buff) {
+		OSD_ERR("!!! Failed to allocate memory for test\n");
+		goto dev_fini;
+	}
+	for (i = 0; i < BUFF_SIZE / 4; i++)
+		((int *)write_buff)[i] = i;
+	OSD_DEBUG("allocate buffers\n");
+
+/* write to objects */
+	ret = ktest_write_obj(&osd_dev, write_buff);
+	if (ret)
+		goto dev_fini;
+
+/* read from objects and compare to write */
+	ret = ktest_read_obj(&osd_dev, write_buff, read_buff);
+	if (ret)
+		goto dev_fini;
+
+/* List all objects */
+
+/* Write with get_attr */
+/* Write with set_attr */
+/* Write with set_attr + get_attr */
+/* Read with set_attr */
+/* Read with get_attr */
+/* Read with get_attr + set_attr */
+/* remove objects */
+	ret = ktest_remove_obj(&osd_dev);
+	if (ret)
+		goto dev_fini;
+
+/* remove partitions */
+	ret = ktest_remove_par(&osd_dev);
+	if (ret)
+		goto dev_fini;
+
+/* good and done */
+	OSD_INFO("test17: All good and done\n");
+dev_fini:
+	if (read_buff)
+		free_page((ulong)read_buff);
+	if (write_buff)
+		free_page((ulong)write_buff);
+
+	osd_dev_fini(&osd_dev);
+	return ret;
+}
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 37797d4..d7a0ca1 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -114,8 +114,7 @@ static long osd_uld_ioctl(struct file *file, unsigned int cmd,
 	switch (cmd) {
 	case OSD_TEST_ALL:
 		OSD_DEBUG("Kernel test %d: osd_dev=%p\n", cmd, osd_dev);
-		/* TODO: Add some tests code here */
-		ret = 0;
+		ret = do_test_17(osd_dev->scsi_dev);
 		break;
 	default:
 		OSD_ERR("Unknown osd_uld_ioctl %d\n", cmd);
-- 
1.5.6.rc1.5.gadf6



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 05/14] libosd: attributes Support
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
                     ` (3 preceding siblings ...)
  2008-07-24 17:49   ` [RFC 04/14] osd_ktests: Add basic OSD tests Boaz Harrosh
@ 2008-07-24 17:51   ` Boaz Harrosh
  2008-07-24 17:53   ` [RFC 06/14] osd_ktests: Test Attribute lists Boaz Harrosh
                     ` (8 subsequent siblings)
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 17:51 UTC (permalink / raw)
  To: open-osd development
  Cc: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig, FUJITA Tomonori, linux-scsi


Support for both List-Mode and Page-Mode osd attributes. One of these operations
may be added to most other operations.

Define the OSD standard's attribute pages constants and structures
(osd_attributes.h)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  569 ++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_attributes.h    |  322 +++++++++++++++++++++
 2 files changed, 891 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_attributes.h

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index a1daded..f10f21e 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -65,6 +65,50 @@ static unsigned _osd_req_cdb_len(struct osd_request *or)
 	return OSDv1_TOTAL_CDB_LEN;
 }
 
+static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
+{
+	return osdv1_attr_list_elem_size(len);
+}
+
+static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
+{
+	return osdv1_list_size(list_head);
+}
+
+static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
+{
+	return sizeof(struct osdv1_attributes_list_header);
+}
+
+static void _osd_req_set_alist_type(struct osd_request *or,
+	void *list, int list_type)
+{
+	struct osdv1_attributes_list_header *attr_list = list;
+
+	memset(attr_list, 0, sizeof(*attr_list));
+	attr_list->type = list_type;
+}
+
+static bool _osd_req_is_alist_type(struct osd_request *or,
+	void *list, int list_type)
+{
+	if (!list)
+		return false;
+
+	if (1) {
+		struct osdv1_attributes_list_header *attr_list = list;
+
+		return attr_list->type == list_type;
+	}
+}
+
+static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
+	u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
 {
 	/* FIXME: Take the device reference */
@@ -130,10 +174,25 @@ static void _abort_unexecuted_bios(struct request *rq)
 	}
 }
 
+static void _osd_free_seg(struct osd_request *or,
+	struct _osd_req_data_segment *seg)
+{
+	if (!seg->buff || !seg->alloc_size)
+		return;
+
+	kfree(seg->buff);
+	seg->buff = NULL;
+	seg->alloc_size = 0;
+}
+
 void osd_end_request(struct osd_request *or)
 {
 	struct request *rq = or->request;
 
+	_osd_free_seg(or, &or->set_attr);
+	_osd_free_seg(or, &or->enc_get_attr);
+	_osd_free_seg(or, &or->get_attr);
+
 	if (rq) {
 		if (rq->next_rq) {
 			_abort_unexecuted_bios(rq->next_rq);
@@ -153,6 +212,54 @@ int osd_execute_request(struct osd_request *or)
 }
 EXPORT_SYMBOL(osd_execute_request);
 
+u8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+u8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+
+static int _osd_realloc_seg(struct osd_request *or,
+	struct _osd_req_data_segment *seg, unsigned max_bytes)
+{
+	void *buff;
+
+	if (seg->alloc_size >= max_bytes)
+		return 0;
+
+	buff = krealloc(seg->buff, max_bytes, or->alloc_flags);
+	if (!buff) {
+		OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes,
+			seg->alloc_size);
+		return -ENOMEM;
+	}
+
+	memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size);
+	seg->buff = buff;
+	seg->alloc_size = max_bytes;
+	return 0;
+}
+
+static int _alloc_set_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem, unsigned add_bytes)
+{
+	unsigned total_bytes = add_bytes;
+
+	for (; nelem; --nelem, ++oa)
+		total_bytes += _osd_req_alist_elem_size(or, oa->len);
+
+	OSD_DEBUG("total_bytes=%d\n", total_bytes);
+	return _osd_realloc_seg(or, &or->set_attr, total_bytes);
+}
+
+static int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes)
+{
+	OSD_DEBUG("total_bytes=%d\n", max_bytes);
+	return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes);
+}
+
+static int _alloc_get_attr_list(struct osd_request *or)
+{
+	OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes);
+	return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes);
+}
+
 /*
  * Common to all OSD commands
  */
@@ -261,6 +368,409 @@ void osd_req_read(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_read);
 
+void osd_req_get_attributes(struct osd_request *or,
+	const struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_get_attributes);
+
+void osd_req_set_attributes(struct osd_request *or,
+	const struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_set_attributes);
+
+/*
+ * Attributes List-mode
+ */
+
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem)
+{
+	unsigned total_bytes = or->set_attr.total_bytes;
+	void *attr_last;
+	int ret;
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+	if (!total_bytes) { /* first-time: allocate and put list header */
+		total_bytes = _osd_req_sizeof_alist_header(or);
+		ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+		if (ret)
+			return ret;
+		_osd_req_set_alist_type(or, or->set_attr.buff,
+					OSD_ATTR_LIST_SET_RETRIEVE);
+	}
+	attr_last = or->set_attr.buff + total_bytes;
+
+	for (; nelem; --nelem) {
+		struct osd_attributes_list_element *attr;
+		unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
+
+		total_bytes += elem_size;
+		if (unlikely(or->set_attr.alloc_size < total_bytes)) {
+			or->set_attr.total_bytes = total_bytes - elem_size;
+			ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+			if (ret)
+				return ret;
+			attr_last =
+				or->set_attr.buff + or->set_attr.total_bytes;
+		}
+
+		attr = attr_last;
+		attr->page = cpu_to_be32(oa->page);
+		attr->attr_id = cpu_to_be32(oa->attr_id);
+		attr->attr_bytes = cpu_to_be16(oa->len);
+		memcpy(attr->attr_val, oa->val_ptr, oa->len);
+
+		attr_last += elem_size;
+		++oa;
+	}
+
+	or->set_attr.total_bytes = total_bytes;
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_set_attr_list);
+
+static int _append_map_kern(struct request *req,
+	void *buff, unsigned len, gfp_t flags)
+{
+	struct bio *bio;
+	int ret;
+
+	bio = bio_map_kern(req->q, buff, len, flags);
+	if (IS_ERR(bio)) {
+		OSD_ERR("Failed bio_map_kern(%p, %d) => %ld\n", buff, len,
+			PTR_ERR(bio));
+		return PTR_ERR(bio);
+	}
+	ret = blk_rq_append_bio(req->q, req, bio);
+	if (ret) {
+		OSD_ERR("Failed blk_rq_append_bio(%p) => %d\n", bio, ret);
+		bio_put(bio);
+	}
+	return ret;
+}
+
+static int _req_append_segment(struct osd_request *or,
+	int padding, struct _osd_req_data_segment *seg,
+	struct _osd_req_data_segment *last_seg, struct _osd_io_info *io)
+{
+	void *pad_buff;
+	int ret;
+
+	if (padding) {
+		/* check if we can just add it to last buffer */
+		if (last_seg &&
+		    (padding <= last_seg->alloc_size - last_seg->total_bytes))
+			pad_buff = last_seg->buff + last_seg->total_bytes;
+		else
+			pad_buff = io->pad_buff;
+
+		ret = _append_map_kern(io->req, pad_buff, padding,
+				       or->alloc_flags);
+		if (ret)
+			return ret;
+		io->total_bytes += padding;
+	}
+
+	ret = _append_map_kern(io->req, seg->buff, seg->total_bytes,
+			       or->alloc_flags);
+	if (ret)
+		return ret;
+
+	io->total_bytes += seg->total_bytes;
+	OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff,
+		  seg->total_bytes);
+	return 0;
+}
+
+static int _osd_req_finalize_set_attr_list(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	int padding;
+	int ret;
+
+	if (!or->set_attr.total_bytes) {
+		cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED;
+		return 0;
+	}
+
+	cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes);
+	cdbh->attrs_list.set_attr_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &padding);
+
+	ret = _req_append_segment(or, padding, &or->set_attr,
+				  or->out.last_seg, &or->out);
+	if (ret)
+		return ret;
+
+	or->out.last_seg = &or->set_attr;
+	return 0;
+}
+
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem)
+{
+	unsigned total_bytes = or->enc_get_attr.total_bytes;
+	void *attr_last;
+	int ret;
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+	/* first time calc data-in list header size */
+	if (!or->get_attr.total_bytes)
+		or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or);
+
+	/* calc data-out info */
+	if (!total_bytes) { /* first-time: allocate and put list header */
+		unsigned max_bytes;
+
+		total_bytes = _osd_req_sizeof_alist_header(or);
+		max_bytes = total_bytes +
+			nelem * sizeof(struct osd_attributes_list_attrid);
+		ret = _alloc_get_attr_desc(or, max_bytes);
+		if (ret)
+			return ret;
+
+		_osd_req_set_alist_type(or, or->enc_get_attr.buff,
+					OSD_ATTR_LIST_GET);
+	}
+	attr_last = or->enc_get_attr.buff + total_bytes;
+
+	for (; nelem; --nelem) {
+		struct osd_attributes_list_attrid *attrid;
+		const unsigned cur_size = sizeof(*attrid);
+
+		total_bytes += cur_size;
+		if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) {
+			or->enc_get_attr.total_bytes = total_bytes - cur_size;
+			ret = _alloc_get_attr_desc(or,
+					total_bytes + nelem * sizeof(*attrid));
+			if (ret)
+				return ret;
+			attr_last = or->enc_get_attr.buff +
+				or->enc_get_attr.total_bytes;
+		}
+
+		attrid = attr_last;
+		attrid->page = cpu_to_be32(oa->page);
+		attrid->attr_id = cpu_to_be32(oa->attr_id);
+
+		attr_last += cur_size;
+
+		/* calc data-in size */
+		or->get_attr.total_bytes +=
+			_osd_req_alist_elem_size(or, oa->len);
+		++oa;
+	}
+
+	or->enc_get_attr.total_bytes = total_bytes;
+
+	OSD_DEBUG(
+	       "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n",
+	       or->get_attr.total_bytes,
+	       or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or),
+	       or->enc_get_attr.total_bytes,
+	       (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or))
+			/ sizeof(struct osd_attributes_list_attrid));
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_list);
+
+static int _osd_req_finalize_get_attr_list(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	unsigned out_padding;
+	unsigned in_padding;
+	int ret;
+
+	if (!or->enc_get_attr.total_bytes) {
+		cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED;
+		cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED;
+		return 0;
+	}
+
+	ret = _alloc_get_attr_list(or);
+	if (ret)
+		return ret;
+
+	/* The out-going buffer info update */
+	OSD_DEBUG("out-going\n");
+	cdbh->attrs_list.get_attr_desc_bytes =
+		cpu_to_be32(or->enc_get_attr.total_bytes);
+
+	cdbh->attrs_list.get_attr_desc_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+	ret = _req_append_segment(or, out_padding, &or->enc_get_attr,
+				  or->out.last_seg, &or->out);
+	if (ret)
+		return ret;
+	or->out.last_seg = &or->enc_get_attr;
+
+	/* The incoming buffer info update */
+	OSD_DEBUG("in-coming\n");
+	cdbh->attrs_list.get_attr_alloc_length =
+		cpu_to_be32(or->get_attr.total_bytes);
+
+	cdbh->attrs_list.get_attr_offset =
+		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+				  &or->in);
+	if (ret)
+		return ret;
+	or->in.last_seg = &or->get_attr;
+
+	return 0;
+}
+
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *oa, int *nelem, void **iterator)
+{
+	unsigned cur_bytes, returned_bytes, n;
+	const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or);
+	void *cur_p;
+
+	if (!_osd_req_is_alist_type(or, or->get_attr.buff,
+				    OSD_ATTR_LIST_SET_RETRIEVE)) {
+		oa->page = 0;
+		oa->attr_id = 0;
+		oa->val_ptr = NULL;
+		oa->len = 0;
+		*iterator = NULL;
+		return 0;
+	}
+
+	if (*iterator) {
+		BUG_ON((*iterator < or->get_attr.buff) ||
+		     (or->get_attr.buff + or->get_attr.alloc_size < *iterator));
+		cur_p = *iterator;
+		cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list;
+		returned_bytes = or->get_attr.total_bytes;
+	} else { /* first time decode the list header */
+		cur_bytes = sizeof_attr_list;
+		returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) +
+					sizeof_attr_list;
+
+		cur_p = or->get_attr.buff + sizeof_attr_list;
+
+		if (returned_bytes > or->get_attr.alloc_size) {
+			OSD_DEBUG("target report: space was not big enough! "
+				  "Allocate=%u Needed=%u\n",
+				  or->get_attr.alloc_size,
+				  returned_bytes + sizeof_attr_list);
+
+			returned_bytes =
+				or->get_attr.alloc_size - sizeof_attr_list;
+		}
+		or->get_attr.total_bytes = returned_bytes;
+	}
+
+	for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
+		struct osd_attributes_list_element *attr = cur_p;
+		unsigned inc;
+
+		oa->len = be16_to_cpu(attr->attr_bytes);
+		inc = _osd_req_alist_elem_size(or, oa->len);
+		OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n",
+			  oa->len, inc, cur_bytes);
+		cur_bytes += inc;
+		if (cur_bytes > returned_bytes) {
+			OSD_ERR("BAD FOOD from target. list not valid!"
+				"c=%d r=%d n=%d\n",
+				cur_bytes, returned_bytes, n);
+			oa->val_ptr = NULL;
+			break;
+		}
+
+		oa->page = be32_to_cpu(attr->page);
+		oa->attr_id = be32_to_cpu(attr->attr_id);
+		oa->val_ptr = attr->attr_val;
+
+		cur_p += inc;
+		++oa;
+	}
+
+	*iterator = (returned_bytes - cur_bytes) ? cur_p : NULL;
+	*nelem = n;
+	return returned_bytes - cur_bytes;
+}
+EXPORT_SYMBOL(osd_req_decode_get_attr_list);
+
+/*
+ * Attributes Page-mode
+ */
+
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attar_page, unsigned max_page_len,
+	const struct osd_attr *set_one_attr)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE;
+
+	or->get_attr.buff = attar_page;
+	or->get_attr.total_bytes = max_page_len;
+
+	or->set_attr.buff = set_one_attr->val_ptr;
+	or->set_attr.total_bytes = set_one_attr->len;
+
+	cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id);
+	cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len);
+	/* ocdb->attrs_page.get_attr_offset; */
+
+	cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->page);
+	cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id);
+	cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len);
+	/* ocdb->attrs_page.set_attr_offset; */
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_page);
+
+int _osd_req_finalize_attr_page(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	int in_padding, out_padding;
+	int ret;
+
+	/* returned page */
+	cdbh->attrs_page.get_attr_offset =
+		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+				  &or->in);
+	if (ret)
+		return ret;
+
+	/* set one value */
+	cdbh->attrs_page.set_attr_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+	ret = _req_append_segment(or, out_padding, &or->enc_get_attr, NULL,
+				  &or->out);
+	return ret;
+}
+
 /*
  * osd_finalize_request and helpers
  */
@@ -349,9 +859,27 @@ int osd_finalize_request(struct osd_request *or,
 			or->in.total_bytes, or->in.req->data_len);
 	}
 
+	or->out.pad_buff = sg_out_pad_buffer;
+	or->in.pad_buff = sg_in_pad_buffer;
+
 	if (!or->attributes_mode)
 		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
 	cdbh->command_specific_options |= or->attributes_mode;
+	if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+		ret = _osd_req_finalize_attr_page(or);
+	} else {
+		/* TODO: I think that for the GET_ATTR command these 2 should
+		 * be reversed to keep them in execution order (for embeded
+		 * targets with low memory footprint)
+		 */
+		ret = _osd_req_finalize_set_attr_list(or);
+		if (ret)
+			return ret;
+
+		ret = _osd_req_finalize_get_attr_list(or);
+		if (ret)
+			return ret;
+	}
 
 	or->request->cmd = or->cdb.buff;
 	or->request->cmd_len = _osd_req_cdb_len(or);
@@ -417,3 +945,44 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 {
 	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
 }
+
+/*
+ * Declared in osd_protocol.h
+ * 4.12.5 Data-In and Data-Out buffer offsets
+ * byte offset = mantissa * (2^(exponent+8))
+ * Returns the smallest allowed encoded offset that contains given @offset
+ * The actual encoded offset returned is @offset + *@padding.
+ */
+osd_cdb_offset __osd_encode_offset(
+	u64 offset, unsigned *padding, int min_shift, int max_shift)
+{
+	u64 try_offset = -1, mod, align;
+	osd_cdb_offset be32_offset;
+	int shift;
+
+	*padding = 0;
+	if (!offset)
+		return 0;
+
+	for (shift = min_shift; shift < max_shift; ++shift) {
+		try_offset = offset >> shift;
+		if (try_offset < (1 << OSD_OFFSET_MAX_BITS))
+			break;
+	}
+
+	BUG_ON(shift == max_shift);
+
+	align = 1 << shift;
+	mod = offset & (align - 1);
+	if (mod) {
+		*padding = align - mod;
+		try_offset += 1;
+	}
+
+	try_offset |= ((shift - 8) & 0xf) << 28;
+	be32_offset = cpu_to_be32((u32)try_offset);
+
+	OSD_DEBUG("offset=%lld mantissa=%lld exp=%d encoded=%x pad=%d\n",
+		 offset, try_offset & 0x0FFFFFFF, shift, be32_offset, *padding);
+	return be32_offset;
+}
diff --git a/include/scsi/osd_attributes.h b/include/scsi/osd_attributes.h
new file mode 100644
index 0000000..697a693
--- /dev/null
+++ b/include/scsi/osd_attributes.h
@@ -0,0 +1,322 @@
+#ifndef __OSD_ATTRIBUTES_H__
+#define __OSD_ATTRIBUTES_H__
+
+#include "osd_protocol.h"
+
+/*
+ * Contains types and constants that define attribute pages and attribute
+ * numbers and their data types.
+ */
+
+/* osd-r10 4.7.3 Attributes pages */
+enum {
+	OSD_APAGE_OBJECT_FIRST		= 0x0,
+	OSD_APAGE_OBJECT_DIRECTORY	= 0,
+	OSD_APAGE_OBJECT_INFORMATION	= 1,
+	OSD_APAGE_OBJECT_QUOTAS		= 2,
+	OSD_APAGE_OBJECT_TIMESTAMP	= 3,
+	OSD_APAGE_OBJECT_COLLECTIONS	= 4,
+	OSD_APAGE_OBJECT_SECURITY	= 5,
+	OSD_APAGE_OBJECT_LAST		= 0x2fffffff,
+
+	OSD_APAGE_PARTITION_FIRST	= 0x30000000,
+	OSD_APAGE_PARTITION_DIRECTORY	= OSD_APAGE_PARTITION_FIRST + 0,
+	OSD_APAGE_PARTITION_INFORMATION = OSD_APAGE_PARTITION_FIRST + 1,
+	OSD_APAGE_PARTITION_QUOTAS	= OSD_APAGE_PARTITION_FIRST + 2,
+	OSD_APAGE_PARTITION_TIMESTAMP	= OSD_APAGE_PARTITION_FIRST + 3,
+	OSD_APAGE_PARTITION_SECURITY	= OSD_APAGE_PARTITION_FIRST + 5,
+	OSD_APAGE_PARTITION_LAST	= 0x5FFFFFFF,
+
+	OSD_APAGE_COLLECTION_FIRST	= 0x60000000,
+	OSD_APAGE_COLLECTION_DIRECTORY	= OSD_APAGE_COLLECTION_FIRST + 0,
+	OSD_APAGE_COLLECTION_INFORMATION = OSD_APAGE_COLLECTION_FIRST + 1,
+	OSD_APAGE_COLLECTION_TIMESTAMP	= OSD_APAGE_COLLECTION_FIRST + 3,
+	OSD_APAGE_COLLECTION_SECURITY	= OSD_APAGE_COLLECTION_FIRST + 5,
+	OSD_APAGE_COLLECTION_LAST	= 0x8FFFFFFF,
+
+	OSD_APAGE_ROOT_FIRST		= 0x90000000,
+	OSD_APAGE_ROOT_DIRECTORY	= OSD_APAGE_ROOT_FIRST + 0,
+	OSD_APAGE_ROOT_INFORMATION	= OSD_APAGE_ROOT_FIRST + 1,
+	OSD_APAGE_ROOT_QUOTAS		= OSD_APAGE_ROOT_FIRST + 2,
+	OSD_APAGE_ROOT_TIMESTAMP	= OSD_APAGE_ROOT_FIRST + 3,
+	OSD_APAGE_ROOT_SECURITY		= OSD_APAGE_ROOT_FIRST + 5,
+	OSD_APAGE_ROOT_LAST		= 0xBFFFFFFF,
+
+	OSD_APAGE_RESERVED_TYPE_FIRST	= 0xC0000000,
+	OSD_APAGE_RESERVED_TYPE_LAST	= 0xEFFFFFFF,
+
+	OSD_APAGE_COMMON_FIRST		= 0xF0000000,
+	OSD_APAGE_COMMON_LAST		= 0xFFFFFFFE,
+
+	OSD_APAGE_REQUEST_ALL		= 0xFFFFFFFF,
+};
+
+/* subcategories of attr pages within each range above */
+enum {
+	OSD_APAGE_STD_FIRST		= 0x0,
+	OSD_APAGE_STD_DIRECTORY		= 0,
+	OSD_APAGE_STD_INFORMATION	= 1,
+	OSD_APAGE_STD_QUOTAS		= 2,
+	OSD_APAGE_STD_TIMESTAMP		= 3,
+	OSD_APAGE_STD_COLLECTIONS	= 4,
+	OSD_APAGE_STD_POLICY_SECURITY	= 5,
+	OSD_APAGE_STD_LAST		= 0x0000007F,
+
+	OSD_APAGE_RESERVED_FIRST	= 0x00000080,
+	OSD_APAGE_RESERVED_LAST		= 0x00007FFF,
+
+	OSD_APAGE_OTHER_STD_FIRST	= 0x00008000,
+	OSD_APAGE_OTHER_STD_LAST	= 0x0000EFFF,
+
+	OSD_APAGE_PUBLIC_FIRST		= 0x0000F000,
+	OSD_APAGE_PUBLIC_LAST		= 0x0000FFFF,
+
+	OSD_APAGE_APP_DEFINED_FIRST	= 0x00010000,
+	OSD_APAGE_APP_DEFINED_LAST	= 0x1FFFFFFF,
+
+	OSD_APAGE_VENDOR_SPECIFIC_FIRST	= 0x20000000,
+	OSD_APAGE_VENDOR_SPECIFIC_LAST	= 0x2FFFFFFF,
+};
+
+enum {
+	OSD_ATTR_PAGE_IDENTIFICATION = 0, /* in all pages 40 bytes */
+};
+
+struct page_identification {
+	u8 vendor_identification[8];
+	u8 page_identification[32];
+}  __packed;
+
+struct osd_attr_page_header {
+	__be32 page_number;
+	__be32 page_length;
+} __packed;
+
+/* 7.1.2.8 Root Information attributes page (OSD_APAGE_ROOT_INFORMATION) */
+enum {
+	OSD_ATTR_RI_OSD_SYSTEM_ID            = 0x3,   /* 20       */
+	OSD_ATTR_RI_VENDOR_IDENTIFICATION    = 0x4,   /* 8        */
+	OSD_ATTR_RI_PRODUCT_IDENTIFICATION   = 0x5,   /* 16       */
+	OSD_ATTR_RI_PRODUCT_MODEL            = 0x6,   /* 32       */
+	OSD_ATTR_RI_PRODUCT_REVISION_LEVEL   = 0x7,   /* 4        */
+	OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER    = 0x8,   /* variable */
+	OSD_ATTR_RI_OSD_NAME                 = 0x9,   /* variable */
+	OSD_ATTR_RI_TOTAL_CAPACITY           = 0x80,  /* 8        */
+	OSD_ATTR_RI_USED_CAPACITY            = 0x81,  /* 8        */
+	OSD_ATTR_RI_NUMBER_OF_PARTITIONS     = 0xC0,  /* 8        */
+	OSD_ATTR_RI_CLOCK                    = 0x100, /* 6        */
+};
+/* Root_Information_attributes_page does not have a get_page structure */
+
+/* 7.1.2.9 Partition Information attributes page
+ * (OSD_APAGE_PARTITION_INFORMATION)
+ */
+enum {
+	OSD_ATTR_PI_PARTITION_ID            = 0x1,     /* 8        */
+	OSD_ATTR_PI_USERNAME                = 0x9,     /* variable */
+	OSD_ATTR_PI_USED_CAPACITY           = 0x81,    /* 8        */
+	OSD_ATTR_PI_NUMBER_OF_OBJECTS       = 0xC1,    /* 8        */
+};
+/* Partition Information attributes page does not have a get_page structure */
+
+/* 7.1.2.10 Collection Information attributes page
+ * (OSD_APAGE_COLLECTION_INFORMATION)
+ */
+enum {
+	OSD_ATTR_CI_PARTITION_ID           = 0x1,       /* 8        */
+	OSD_ATTR_CI_COLLECTION_OBJECT_ID   = 0x2,       /* 8        */
+	OSD_ATTR_CI_USERNAME               = 0x9,       /* variable */
+	OSD_ATTR_CI_USED_CAPACITY          = 0x81,      /* 8        */
+};
+/* Collection Information attributes page does not have a get_page structure */
+
+/* 7.1.2.11 User Object Information attributes page
+ * (OSD_APAGE_OBJECT_INFORMATION)
+ */
+enum {
+	OSD_ATTR_OI_PARTITION_ID         = 0x1,       /* 8        */
+	OSD_ATTR_OI_OBJECT_ID            = 0x2,       /* 8        */
+	OSD_ATTR_OI_USERNAME             = 0x9,       /* variable */
+	OSD_ATTR_OI_USED_CAPACITY        = 0x81,      /* 8        */
+	OSD_ATTR_OI_LOGICAL_LENGTH       = 0x82,      /* 8        */
+};
+/* Object Information attributes page does not have a get_page structure */
+
+/* 7.1.2.12 Root Quotas attributes page (OSD_APAGE_ROOT_QUOTAS) */
+enum {
+	OSD_ATTR_RQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH     = 0x1,      /* 8  */
+	OSD_ATTR_RQ_PARTITION_CAPACITY_QUOTA               = 0x10001,  /* 8  */
+	OSD_ATTR_RQ_PARTITION_OBJECT_COUNT                 = 0x10002,  /* 8  */
+	OSD_ATTR_RQ_PARTITION_COLLECTIONS_PER_USER_OBJECT  = 0x10081,  /* 4  */
+	OSD_ATTR_RQ_PARTITION_COUNT                        = 0x20002,  /* 8  */
+};
+
+struct Root_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+2, size=0x24 */
+	__be64 default_maximum_user_object_length;
+	__be64 partition_capacity_quota;
+	__be64 partition_object_count;
+	__be64 partition_collections_per_user_object;
+	__be64 partition_count;
+}  __packed;
+
+/* 7.1.2.13 Partition Quotas attributes page (OSD_APAGE_PARTITION_QUOTAS)*/
+enum {
+	OSD_ATTR_PQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH  = 0x1,        /* 8 */
+	OSD_ATTR_PQ_CAPACITY_QUOTA                      = 0x10001,    /* 8 */
+	OSD_ATTR_PQ_OBJECT_COUNT                        = 0x10002,    /* 8 */
+	OSD_ATTR_PQ_COLLECTIONS_PER_USER_OBJECT         = 0x10081,    /* 4 */
+};
+
+struct Partition_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=P+2, size=0x1C */
+	__be64 default_maximum_user_object_length;
+	__be64 capacity_quota;
+	__be64 object_count;
+	__be64 collections_per_user_object;
+}  __packed;
+
+/* 7.1.2.14 User Object Quotas attributes page (OSD_APAGE_OBJECT_QUOTAS) */
+enum {
+	OSD_ATTR_OQ_MAXIMUM_LENGTH  = 0x1,        /* 8 */
+};
+
+struct Object_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=U+2, size=0x8 */
+	__be64 maximum_length;
+}  __packed;
+
+/* 7.1.2.15 Root Timestamps attributes page (OSD_APAGE_ROOT_TIMESTAMP) */
+enum {
+	OSD_ATTR_RT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_RT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_RT_TIMESTAMP_BYPASS          = 0xFFFFFFFE, /* 1 */
+};
+
+struct root_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+3, size=0xD */
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	u8 timestamp_bypass;
+}  __packed;
+
+/* 7.1.2.16 Partition Timestamps attributes page
+ * (OSD_APAGE_PARTITION_TIMESTAMP)
+ */
+enum {
+	OSD_ATTR_PT_CREATED_TIME              = 0x1,        /* 6 */
+	OSD_ATTR_PT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_PT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_PT_DATA_ACCESSED_TIME        = 0x4,        /* 6 */
+	OSD_ATTR_PT_DATA_MODIFIED_TIME        = 0x5,        /* 6 */
+	OSD_ATTR_PT_TIMESTAMP_BYPASS          = 0xFFFFFFFE, /* 1 */
+};
+
+struct partition_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=P+3, size=0x1F */
+	struct osd_timestamp created_time;
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	struct osd_timestamp data_accessed_time;
+	struct osd_timestamp data_modified_time;
+	u8 timestamp_bypass;
+}  __packed;
+
+/* 7.1.2.17/18 Collection/Object Timestamps attributes page
+ * (OSD_APAGE_COLLECTION_TIMESTAMP/OSD_APAGE_OBJECT_TIMESTAMP)
+ */
+enum {
+	OSD_ATTR_OT_CREATED_TIME              = 0x1,        /* 6 */
+	OSD_ATTR_OT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_OT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_OT_DATA_ACCESSED_TIME        = 0x4,        /* 6 */
+	OSD_ATTR_OT_DATA_MODIFIED_TIME        = 0x5,        /* 6 */
+};
+
+/* same for collection */
+struct object_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=C+3/3, size=0x1E */
+	struct osd_timestamp created_time;
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	struct osd_timestamp data_accessed_time;
+	struct osd_timestamp data_modified_time;
+}  __packed;
+
+/* 7.1.2.19 Collections attributes page */
+/* TBD */
+
+/* 7.1.2.20 Root Policy/Security attributes page (OSD_APAGE_ROOT_SECURITY) */
+enum {
+	OSD_ATTR_RS_DEFAULT_SECURITY_METHOD           = 0x1,       /* 1      */
+	OSD_ATTR_RS_OLDEST_VALID_NONCE_LIMIT          = 0x2,       /* 6      */
+	OSD_ATTR_RS_NEWEST_VALID_NONCE_LIMIT          = 0x3,       /* 6      */
+	OSD_ATTR_RS_PARTITION_DEFAULT_SECURITY_METHOD = 0x6,       /* 1      */
+	OSD_ATTR_RS_SUPPORTED_SECURITY_METHODS        = 0x7,       /* 2      */
+	OSD_ATTR_RS_ADJUSTABLE_CLOCK                  = 0x9,       /* 6      */
+	OSD_ATTR_RS_MASTER_KEY_IDENTIFIER             = 0x7FFD,    /* 0 or 7 */
+	OSD_ATTR_RS_ROOT_KEY_IDENTIFIER               = 0x7FFE,    /* 0 or 7 */
+	OSD_ATTR_RS_SUPPORTED_INTEGRITY_ALGORITHM_0   = 0x80000000,/* 1,(x16)*/
+	OSD_ATTR_RS_SUPPORTED_DH_GROUP_0              = 0x80000010,/* 1,(x16)*/
+};
+
+struct root_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+5, size=0x3F */
+	u8 default_security_method;
+	u8 partition_default_security_method;
+	__be16 supported_security_methods;
+	u8 mki_valid_rki_valid;
+	struct osd_timestamp oldest_valid_nonce_limit;
+	struct osd_timestamp newest_valid_nonce_limit;
+	struct osd_timestamp adjustable_clock;
+	u8 master_key_identifier[32-25];
+	u8 root_key_identifier[39-32];
+	u8 supported_integrity_algorithm[16];
+	u8 supported_dh_group[16];
+}  __packed;
+
+/* 7.1.2.21 Partition Policy/Security attributes page
+ * (OSD_APAGE_PARTITION_SECURITY)
+ */
+enum {
+	OSD_ATTR_PS_DEFAULT_SECURITY_METHOD        = 0x1,        /* 1      */
+	OSD_ATTR_PS_OLDEST_VALID_NONCE             = 0x2,        /* 6      */
+	OSD_ATTR_PS_NEWEST_VALID_NONCE             = 0x3,        /* 6      */
+	OSD_ATTR_PS_REQUEST_NONCE_LIST_DEPTH       = 0x4,        /* 2      */
+	OSD_ATTR_PS_FROZEN_WORKING_KEY_BIT_MASK    = 0x5,        /* 2      */
+	OSD_ATTR_PS_PARTITION_KEY_IDENTIFIER       = 0x7FFF,     /* 0 or 7 */
+	OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_FIRST   = 0x8000,     /* 0 or 7 */
+	OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_LAST    = 0x800F,     /* 0 or 7 */
+	OSD_ATTR_PS_POLICY_ACCESS_TAG              = 0x40000001, /* 4      */
+	OSD_ATTR_PS_USER_OBJECT_POLICY_ACCESS_TAG  = 0x40000002, /* 4      */
+};
+
+struct partition_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=p+5, size=0x8f */
+	u8 reserved[3];
+	u8 default_security_method;
+	struct osd_timestamp oldest_valid_nonce;
+	struct osd_timestamp newest_valid_nonce;
+	__be16 request_nonce_list_depth;
+	__be16 frozen_working_key_bit_mask;
+	__be32 policy_access_tag;
+	__be32 user_object_policy_access_tag;
+	u8 pki_valid;
+	__be16 wki_00_0f_vld;
+	struct osd_key_identifier partition_key_identifier;
+	struct osd_key_identifier working_key_identifiers[16];
+}  __packed;
+
+/* 7.1.2.22/23 Collection/Object Policy-Security attributes page
+ * (OSD_APAGE_COLLECTION_SECURITY/OSD_APAGE_OBJECT_SECURITY)
+ */
+enum {
+	OSD_ATTR_OS_POLICY_ACCESS_TAG              = 0x40000001, /* 4      */
+};
+
+struct object_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=C+5/5, size=4 */
+	__be32 policy_access_tag;
+}  __packed;
+
+#endif /*ndef __OSD_ATTRIBUTES_H__*/
-- 
1.5.6.rc1.5.gadf6



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 06/14] osd_ktests: Test Attribute lists
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
                     ` (4 preceding siblings ...)
  2008-07-24 17:51   ` [RFC 05/14] libosd: attributes Support Boaz Harrosh
@ 2008-07-24 17:53   ` Boaz Harrosh
  2008-07-24 17:54   ` [RFC 07/14] libosd: OSD Security processing stubs Boaz Harrosh
                     ` (7 subsequent siblings)
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 17:53 UTC (permalink / raw)
  To: open-osd development
  Cc: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig, FUJITA Tomonori, linux-scsi


Add tests for setting/getting Attribute lists. All combinations of read/write
with set/get attributes are tested. (6 possibilities), So all but data integrity
request structure layouts are attempted.

This test passes against the IBM-OSD-SIM OSDv1 target.
(Except retrival of SYSTEM_ID attribute, which is a bug of the IBM target)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_ktests.c |  220 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 220 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
index 98dd67d..3186fc8 100644
--- a/drivers/scsi/osd/osd_ktests.c
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -39,8 +39,11 @@
  */
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
+#include "scsi/osd_attributes.h"
+
 #include "osd_debug.h"
 
+#include <asm/unaligned.h>
 #include <linux/vmalloc.h>
 #include <scsi/scsi_device.h>
 
@@ -91,6 +94,111 @@ int test_exec(struct osd_request *or, void *caps, const struct osd_obj_id *obj)
 	OSD_DEBUG(msg "\n"); \
 } while (0)
 
+#define ATTR_SDEF(pg, id, l, ptr) \
+	{ .page = pg, .attr_id = id, .len = l, .val_ptr = ptr }
+
+#define ATTR_DEF(pg, id, l) ATTR_SDEF(pg, id, l, NULL)
+
+#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
+
+int ktest_read_system_info(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	char g_caps[OSD_CAP_LEN];
+	struct osd_attr get_attrs[] = {
+		ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/),
+		ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/),
+		ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6),
+		/* IBM-OSD-SIM Has a bug with this one put it last */
+		ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20),
+	};
+	void *iter = NULL, *pFirst;
+	int nelem = ARRAY_SIZE(get_attrs), a = 0;
+	int ret;
+
+	KTEST_START_REQ(osd_dev, or);
+
+	/* get attrs */
+	osd_req_get_attributes(or, &osd_root_object);
+	osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs));
+
+	ret = test_exec(or, g_caps, &osd_root_object);
+	if (ret) {
+		OSD_ERR("Failed to detect %s => %d\n", "OSD1", ret);
+		goto out;
+	}
+
+	osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+	OSD_INFO("Detected %s device\n",
+		"OSD1");
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_VENDOR_IDENTIFICATION [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_IDENTIFICATION [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_MODEL [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_REVISION_LEVEL [%u]\n",
+		get_unaligned_be32(pFirst));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_OSD_NAME(%d) [%x,%x,%x,%x,%x,%x,%x,%x]\n",
+		get_attrs[a].len,
+		((char *)pFirst)[0], ((char *)pFirst)[1],
+		((char *)pFirst)[2], ((char *)pFirst)[3],
+		((char *)pFirst)[4], ((char *)pFirst)[5],
+		((char *)pFirst)[6], ((char *)pFirst)[7]
+	);
+	a++;
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_TOTAL_CAPACITY [0x%llx]\n",
+		get_unaligned_be64(pFirst));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_USED_CAPACITY [0x%llx]\n",
+		get_unaligned_be64(pFirst));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_NUMBER_OF_PARTITIONS [%lld]\n",
+		get_unaligned_be64(pFirst));
+
+	/* FIXME: Where are the time utilities */
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_CLOCK [HEX%x%x%x%x%x%x]\n",
+		((char *)pFirst)[0], ((char *)pFirst)[1],
+		((char *)pFirst)[2], ((char *)pFirst)[3],
+		((char *)pFirst)[4], ((char *)pFirst)[5]);
+
+	if (a < nelem) { /* Might not have it */
+		pFirst = get_attrs[a++].val_ptr;
+		OSD_INFO("OSD_ATTR_RI_OSD_SYSTEM_ID [%s]\n",
+			(char *)pFirst);
+	}
+out:
+	osd_end_request(or);
+	return ret;
+}
+
 int ktest_format(struct osd_dev *osd_dev)
 {
 	struct osd_request *or;
@@ -257,6 +365,91 @@ int ktest_remove_par(struct osd_dev *osd_dev)
 	return 0;
 }
 
+int ktest_write_read_attr(struct osd_dev *osd_dev, void *buff,
+	bool doread, bool doset, bool doget)
+{
+	struct request_queue *req_q = osd_dev->scsi_dev->request_queue;
+	struct osd_request *or;
+	char g_caps[OSD_CAP_LEN];
+	int ret;
+	struct bio *bio;
+	char *domsg;
+	/* set attrs */
+	static char name[] = "ktest_write_read_attr";
+	__be64 max_len = cpu_to_be64(0x80000000L);
+	struct osd_obj_id obj = {
+		.partition = first_par_id,
+		.id = first_obj_id,
+	};
+	struct osd_attr set_attrs[] = {
+		ATTR_SDEF(OSD_APAGE_OBJECT_QUOTAS, OSD_ATTR_OQ_MAXIMUM_LENGTH,
+			sizeof(max_len), &max_len),
+		ATTR_SDEF(OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_USERNAME,
+			sizeof(name), name),
+	};
+	struct osd_attr get_attrs[] = {
+		ATTR_DEF(OSD_APAGE_OBJECT_INFORMATION,
+			OSD_ATTR_OI_USED_CAPACITY, sizeof(__be64)),
+		ATTR_DEF(OSD_APAGE_OBJECT_INFORMATION,
+			OSD_ATTR_OI_LOGICAL_LENGTH, sizeof(__be64)),
+	};
+
+	KTEST_START_REQ(osd_dev, or);
+	bio = bio_map_kern(req_q, buff, BUFF_SIZE, GFP_KERNEL);
+	if (!bio) {
+		OSD_ERR("!!! Failed to allocate BIO\n");
+		return -ENOMEM;
+	}
+
+	if (doread) {
+		osd_req_read(or, &obj, bio, 0);
+		domsg = "Read-with-attr";
+	} else {
+		osd_req_write(or, &obj, bio, 0);
+		domsg = "Write-with-attr";
+	}
+
+	if (doset)
+		osd_req_add_set_attr_list(or, set_attrs, 2);
+	if (doget)
+		osd_req_add_get_attr_list(or, get_attrs, 2);
+
+/*	KTEST_EXEC_END(or, &obj, "");*/
+	ret = test_exec(or, g_caps, &obj);
+	if (!ret && doget) {
+		void *iter = NULL, *pFirst, *pSec;
+		int nelem = 2;
+		u64 capacity_len = ~0;
+		u64 logical_len = ~0;
+
+		osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+		/*FIXME: Std does not guaranty order of return attrs */
+		pFirst = get_attrs[0].val_ptr;
+		if (pFirst)
+			capacity_len = get_unaligned_be64(pFirst);
+		else
+			OSD_ERR("failed to read capacity_used\n");
+		pSec = get_attrs[1].val_ptr;
+		if (pSec)
+			logical_len = get_unaligned_be64(pSec);
+		else
+			OSD_ERR("failed to read logical_length\n");
+		OSD_INFO("%s capacity=%llu len=%llu\n",
+			domsg, capacity_len, logical_len);
+	}
+
+	osd_end_request(or);
+	if (ret) {
+		OSD_ERR("!!! Error executing %s => %d doset=%d doget=%d\n",
+			domsg, ret, doset, doget);
+		return ret;
+	}
+	OSD_DEBUG("%s\n", domsg);
+
+	return 0;
+}
+
 int do_test_17(struct scsi_device *scsi_dev)
 {
 	struct osd_dev osd_dev;
@@ -266,6 +459,9 @@ int do_test_17(struct scsi_device *scsi_dev)
 
 	osd_dev_init(&osd_dev, scsi_dev);
 
+	if (ktest_read_system_info(&osd_dev))
+		goto dev_fini;
+
 /* osd_format */
 	if (ktest_format(&osd_dev))
 		goto dev_fini;
@@ -304,11 +500,35 @@ int do_test_17(struct scsi_device *scsi_dev)
 /* List all objects */
 
 /* Write with get_attr */
+	ret = ktest_write_read_attr(&osd_dev, write_buff, false, false, true);
+	if (ret)
+		goto dev_fini;
+
 /* Write with set_attr */
+	ret = ktest_write_read_attr(&osd_dev, write_buff, false, true, false);
+	if (ret)
+		goto dev_fini;
+
 /* Write with set_attr + get_attr */
+	ret = ktest_write_read_attr(&osd_dev, write_buff, false, true, true);
+	if (ret)
+		goto dev_fini;
+
 /* Read with set_attr */
+	ret = ktest_write_read_attr(&osd_dev, write_buff, true, true, false);
+	if (ret)
+		goto dev_fini;
+
 /* Read with get_attr */
+	ret = ktest_write_read_attr(&osd_dev, write_buff, true, false, true);
+	if (ret)
+		goto dev_fini;
+
 /* Read with get_attr + set_attr */
+	ret = ktest_write_read_attr(&osd_dev, write_buff, true, true, true);
+	if (ret)
+		goto dev_fini;
+
 /* remove objects */
 	ret = ktest_remove_obj(&osd_dev);
 	if (ret)
-- 
1.5.6.rc1.5.gadf6



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 07/14] libosd: OSD Security processing stubs
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
                     ` (5 preceding siblings ...)
  2008-07-24 17:53   ` [RFC 06/14] osd_ktests: Test Attribute lists Boaz Harrosh
@ 2008-07-24 17:54   ` Boaz Harrosh
  2008-07-24 17:55   ` [RFC 08/14] libosd: Add Flush and List-objects support Boaz Harrosh
                     ` (6 subsequent siblings)
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 17:54 UTC (permalink / raw)
  To: open-osd development
  Cc: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig, FUJITA Tomonori, linux-scsi


Layout the signing of OSD's CDB and all-data security modes. The actual
code for signing the data and CDB is missing, but the code flow and the extra
buffer segments are all in place.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   85 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 85 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index f10f21e..10e3ac0 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -109,6 +109,14 @@ static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
 }
 
+static struct osd_security_parameters *
+_osd_req_sec_params(struct osd_request *or)
+{
+	struct osd_cdb *ocdb = &or->cdb;
+
+	return &ocdb->v1.sec_params;
+}
+
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
 {
 	/* FIXME: Take the device reference */
@@ -771,6 +779,64 @@ int _osd_req_finalize_attr_page(struct osd_request *or)
 	return ret;
 }
 
+int _osd_req_finalize_data_integrity(struct osd_request *or,
+	bool has_in, bool has_out, const u8 *cap_key)
+{
+	struct osd_security_parameters *sec_parms = _osd_req_sec_params(or);
+	int ret;
+
+	if (!osd_is_sec_alldata(sec_parms))
+		return 0;
+
+	if (has_out) {
+		struct _osd_req_data_segment seg = {
+			.buff = &or->out_data_integ,
+			.total_bytes = sizeof(or->out_data_integ),
+		};
+		int pad;
+
+		or->out_data_integ.data_bytes = cpu_to_be64(
+			or->out.bio ? or->out.bio->bi_size : 0);
+		or->out_data_integ.set_attributes_bytes = cpu_to_be64(
+			or->set_attr.total_bytes);
+		or->out_data_integ.get_attributes_bytes = cpu_to_be64(
+			or->enc_get_attr.total_bytes);
+
+		sec_parms->data_out_integrity_check_offset =
+			osd_req_encode_offset(or, or->out.total_bytes, &pad);
+
+		ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
+					  &or->out);
+		if (ret)
+			return ret;
+		or->out.last_seg = NULL;
+
+		/* they are now all chained to request sign them all together */
+		osd_sec_sign_data(&or->out_data_integ, or->out.req->bio,
+				  cap_key);
+	}
+
+	if (has_in) {
+		struct _osd_req_data_segment seg = {
+			.buff = &or->in_data_integ,
+			.total_bytes = sizeof(or->in_data_integ),
+		};
+		int pad;
+
+		sec_parms->data_in_integrity_check_offset =
+			osd_req_encode_offset(or, or->in.total_bytes, &pad);
+
+		ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
+					  &or->in);
+		if (ret)
+			return ret;
+
+		or->in.last_seg = NULL;
+	}
+
+	return 0;
+}
+
 /*
  * osd_finalize_request and helpers
  */
@@ -881,6 +947,12 @@ int osd_finalize_request(struct osd_request *or,
 			return ret;
 	}
 
+	ret = _osd_req_finalize_data_integrity(or, has_in, has_out, cap_key);
+	if (ret)
+		return ret;
+
+	osd_sec_sign_cdb(&or->cdb, cap_key);
+
 	or->request->cmd = or->cdb.buff;
 	or->request->cmd_len = _osd_req_cdb_len(or);
 
@@ -946,6 +1018,19 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
 }
 
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms)
+{
+	return false;
+}
+
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key)
+{
+}
+
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key)
+{
+}
+
 /*
  * Declared in osd_protocol.h
  * 4.12.5 Data-In and Data-Out buffer offsets
-- 
1.5.6.rc1.5.gadf6



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 08/14] libosd: Add Flush and List-objects support
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
                     ` (6 preceding siblings ...)
  2008-07-24 17:54   ` [RFC 07/14] libosd: OSD Security processing stubs Boaz Harrosh
@ 2008-07-24 17:55   ` Boaz Harrosh
  2008-07-24 17:57   ` [RFC 09/14] libosd: Not implemented commands Boaz Harrosh
                     ` (5 subsequent siblings)
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 17:55 UTC (permalink / raw)
  To: open-osd development
  Cc: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig, FUJITA Tomonori, linux-scsi


Add support for the various List-objects commands. List-partitions-in-device,
List-collections-in-partition, List-objects-in-partition,
List-objects-in-collection. All these support partial listing and continuation.

Add support for the different Flush commands and options.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  124 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 124 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 10e3ac0..d7f3688 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -102,6 +102,16 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
 	}
 }
 
+/* This is for List-objects not Attributes-Lists */
+static void _osd_req_encode_olist(struct osd_request *or,
+	struct osd_obj_id_list *list)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+	cdbh->v1.list_identifier = list->list_identifier;
+	cdbh->v1.start_address = list->continuation_id;
+}
+
 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 	u64 offset, unsigned *padding)
 {
@@ -313,6 +323,29 @@ void osd_req_format(struct osd_request *or, u64 tot_capacity)
 }
 EXPORT_SYMBOL(osd_req_format);
 
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem)
+{
+	return osd_req_list_partition_objects(or, 0, initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_dev_partitions);
+
+static void _osd_req_encode_flush(struct osd_request *or,
+	enum osd_options_flush_scope_values op)
+{
+	struct osd_cdb_head *ocdb = osd_cdb_head(&or->cdb);
+
+	ocdb->command_specific_options = op;
+}
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH_OSD, &osd_root_object, 0, 0);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_obsd);
+
 /*
  * Partition commands
  */
@@ -339,6 +372,88 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition)
 }
 EXPORT_SYMBOL(osd_req_remove_partition);
 
+static int _osd_req_list_objects(struct osd_request *or,
+	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem)
+{
+	struct request_queue *q = or->osd_dev->scsi_dev->request_queue;
+	u64 len = nelem * sizeof(osd_id) + sizeof(*list);
+	struct bio *bio;
+
+	_osd_req_encode_common(or, action, obj, (u64)initial_id, len);
+
+	if (list->list_identifier)
+		_osd_req_encode_olist(or, list);
+
+	WARN_ON(or->in.bio);
+	bio = bio_map_kern(q, list, len, or->alloc_flags);
+	if (!bio) {
+		OSD_ERR("!!! Failed to allocate list_objects BIO\n");
+		return -ENOMEM;
+	}
+
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+	return 0;
+}
+
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	return osd_req_list_collection_objects(or, &par, initial_id, list,
+					       nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_collections);
+
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	return _osd_req_list_objects(or, OSD_ACT_LIST, &par, initial_id, list,
+				     nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_objects);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_partition(or, OSD_ACT_FLUSH_PARTITION, partition);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_partition);
+
+/*
+ * Collection commands
+ */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *obj, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem)
+{
+	return _osd_req_list_objects(or, OSD_ACT_LIST_COLLECTION, obj,
+				     initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_collection_objects);
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH_PARTITION, obj, 0, 0);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_collection);
+
 /*
  * Object commands
  */
@@ -365,6 +480,15 @@ void osd_req_write(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_write);
 
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
+	/*V2*/ u64 offset, /*V2*/ u64 len)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_object);
+
 void osd_req_read(struct osd_request *or,
 	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
 {
-- 
1.5.6.rc1.5.gadf6



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 09/14] libosd: Not implemented commands
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
                     ` (7 preceding siblings ...)
  2008-07-24 17:55   ` [RFC 08/14] libosd: Add Flush and List-objects support Boaz Harrosh
@ 2008-07-24 17:57   ` Boaz Harrosh
  2008-07-24 17:58   ` [RFC 10/14] libosd: OSD version 2 Support Boaz Harrosh
                     ` (4 subsequent siblings)
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 17:57 UTC (permalink / raw)
  To: open-osd development
  Cc: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig, FUJITA Tomonori, linux-scsi


Some commands declared in header are not yet implemented. Put them
as stubs in .c file, just so they take their place in the file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   35 +++++++++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index d7f3688..e0216e0 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -316,6 +316,9 @@ static void _osd_req_encode_common(struct osd_request *or,
 /*
  * Device commands
  */
+/*TODO: void osd_req_set_master_seed_xchg(struct osd_request *, ...); */
+/*TODO: void osd_req_set_master_key(struct osd_request *, ...); */
+
 void osd_req_format(struct osd_request *or, u64 tot_capacity)
 {
 	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
@@ -346,6 +349,10 @@ void osd_req_flush_obsd(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_flush_obsd);
 
+/*TODO: void osd_req_perform_scsi_command(struct osd_request *,
+	const u8 *cdb, ...); */
+/*TODO: void osd_req_task_management(struct osd_request *, ...); */
+
 /*
  * Partition commands
  */
@@ -372,6 +379,10 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition)
 }
 EXPORT_SYMBOL(osd_req_remove_partition);
 
+/*TODO: void osd_req_set_partition_key(struct osd_request *,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]); */
+
 static int _osd_req_list_objects(struct osd_request *or,
 	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
 	struct osd_obj_id_list *list, unsigned nelem)
@@ -437,6 +448,11 @@ EXPORT_SYMBOL(osd_req_flush_partition);
 /*
  * Collection commands
  */
+/*TODO: void osd_req_create_collection(struct osd_request *,
+	const struct osd_obj_id *); */
+/*TODO: void osd_req_remove_collection(struct osd_request *,
+	const struct osd_obj_id *); */
+
 int osd_req_list_collection_objects(struct osd_request *or,
 	const struct osd_obj_id *obj, osd_id initial_id,
 	struct osd_obj_id_list *list, unsigned nelem)
@@ -446,6 +462,8 @@ int osd_req_list_collection_objects(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_list_collection_objects);
 
+/*TODO: void query(struct osd_request *, ...); V2 */
+
 void osd_req_flush_collection(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
 {
@@ -454,6 +472,9 @@ void osd_req_flush_collection(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_flush_collection);
 
+/*TODO: void get_member_attrs(struct osd_request *, ...); V2 */
+/*TODO: void set_member_attrs(struct osd_request *, ...); V2 */
+
 /*
  * Object commands
  */
@@ -469,6 +490,11 @@ void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
 }
 EXPORT_SYMBOL(osd_req_remove_object);
 
+
+/*TODO: void osd_req_create_multi(struct osd_request *or,
+	struct osd_obj_id *first, struct osd_obj_id_list *list, unsigned nelem);
+*/
+
 void osd_req_write(struct osd_request *or,
 	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
 {
@@ -480,6 +506,15 @@ void osd_req_write(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_write);
 
+/*TODO: void osd_req_append(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out); */
+/*TODO: void osd_req_create_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset); */
+/*TODO: void osd_req_clear(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len); */
+/*TODO: void osd_req_punch(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len); V2 */
+
 void osd_req_flush_object(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
 	/*V2*/ u64 offset, /*V2*/ u64 len)
-- 
1.5.6.rc1.5.gadf6



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 10/14] libosd: OSD version 2 Support
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
                     ` (8 preceding siblings ...)
  2008-07-24 17:57   ` [RFC 09/14] libosd: Not implemented commands Boaz Harrosh
@ 2008-07-24 17:58   ` Boaz Harrosh
  2008-07-24 17:59   ` [RFC 11/14] osd_ktests: OSDv2 auto detection Boaz Harrosh
                     ` (3 subsequent siblings)
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 17:58 UTC (permalink / raw)
  To: open-osd development
  Cc: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig, FUJITA Tomonori, linux-scsi


Add support for OSD2 at run time. It is now possible to run with
both OSDv1 and OSDv2 targets at the same time. The actual detection
should be preformed by the security manager, as the version is encoded
in the capability structure. See the osd_ktests patch for how to easily
detect a target version in runtime. (All you need is issue a first command,
then if it fails call osd_dev_set_ver(OSD_VER1) and issue the command
again)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   94 ++++++++++++++++++++++++++++++++------
 include/scsi/osd_initiator.h     |   39 ++++++++++++++++
 include/scsi/osd_protocol.h      |   86 +++++++++++++++++++++++++++++++++--
 3 files changed, 201 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index e0216e0..3003456 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -57,36 +57,50 @@ static inline void build_test(void)
 {
 	/* structures were not packed */
 	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
 	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
 }
 
 static unsigned _osd_req_cdb_len(struct osd_request *or)
 {
-	return OSDv1_TOTAL_CDB_LEN;
+	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
 }
 
 static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
 {
-	return osdv1_attr_list_elem_size(len);
+	return osd_req_is_ver1(or) ?
+		osdv1_attr_list_elem_size(len) :
+		osdv2_attr_list_elem_size(len);
 }
 
 static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
 {
-	return osdv1_list_size(list_head);
+	return osd_req_is_ver1(or) ?
+		osdv1_list_size(list_head) :
+		osdv2_list_size(list_head);
 }
 
 static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
 {
-	return sizeof(struct osdv1_attributes_list_header);
+	return osd_req_is_ver1(or) ?
+		sizeof(struct osdv1_attributes_list_header) :
+		sizeof(struct osdv2_attributes_list_header);
 }
 
 static void _osd_req_set_alist_type(struct osd_request *or,
 	void *list, int list_type)
 {
-	struct osdv1_attributes_list_header *attr_list = list;
+	if (osd_req_is_ver1(or)) {
+		struct osdv1_attributes_list_header *attr_list = list;
+
+		memset(attr_list, 0, sizeof(*attr_list));
+		attr_list->type = list_type;
+	} else {
+		struct osdv2_attributes_list_header *attr_list = list;
 
-	memset(attr_list, 0, sizeof(*attr_list));
-	attr_list->type = list_type;
+		memset(attr_list, 0, sizeof(*attr_list));
+		attr_list->type = list_type;
+	}
 }
 
 static bool _osd_req_is_alist_type(struct osd_request *or,
@@ -95,10 +109,14 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
 	if (!list)
 		return false;
 
-	if (1) {
+	if (osd_req_is_ver1(or)) {
 		struct osdv1_attributes_list_header *attr_list = list;
 
 		return attr_list->type == list_type;
+	} else {
+		struct osdv2_attributes_list_header *attr_list = list;
+
+		return attr_list->type == list_type;
 	}
 }
 
@@ -108,15 +126,22 @@ static void _osd_req_encode_olist(struct osd_request *or,
 {
 	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
 
-	cdbh->v1.list_identifier = list->list_identifier;
-	cdbh->v1.start_address = list->continuation_id;
+	if (osd_req_is_ver1(or)) {
+		cdbh->v1.list_identifier = list->list_identifier;
+		cdbh->v1.start_address = list->continuation_id;
+	} else {
+		cdbh->v2.list_identifier = list->list_identifier;
+		cdbh->v2.start_address = list->continuation_id;
+	}
 }
 
 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 	u64 offset, unsigned *padding)
 {
 	return __osd_encode_offset(offset, padding,
-				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+			osd_req_is_ver1(or) ?
+				OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT,
+			OSD_OFFSET_MAX_SHIFT);
 }
 
 static struct osd_security_parameters *
@@ -124,7 +149,10 @@ _osd_req_sec_params(struct osd_request *or)
 {
 	struct osd_cdb *ocdb = &or->cdb;
 
-	return &ocdb->v1.sec_params;
+	if (osd_req_is_ver1(or))
+		return &ocdb->v1.sec_params;
+	else
+		return &ocdb->v2.sec_params;
 }
 
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
@@ -134,6 +162,9 @@ void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
 	memset(osdd, 0, sizeof(*osdd));
 	osdd->scsi_dev = scsi_dev;
 	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+#ifdef OSD_VER1_SUPPORT
+	osdd->version = OSD_VER2;
+#endif
 	/* TODO: Allocate pools for osd_request attributes ... */
 }
 EXPORT_SYMBOL(osd_dev_init);
@@ -307,10 +338,30 @@ static void _osdv1_req_encode_common(struct osd_request *or,
 	ocdb->h.v1.start_address = cpu_to_be64(offset);
 }
 
+static void _osdv2_req_encode_common(struct osd_request *or,
+	 __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv2_cdb *ocdb = &or->cdb.v2;
+
+	OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v2.length = cpu_to_be64(len);
+	ocdb->h.v2.start_address = cpu_to_be64(offset);
+}
+
 static void _osd_req_encode_common(struct osd_request *or,
 	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
 {
-	_osdv1_req_encode_common(or, act, obj, offset, len);
+	if (osd_req_is_ver1(or))
+		_osdv1_req_encode_common(or, act, obj, offset, len);
+	else
+		_osdv2_req_encode_common(or, act, obj, offset, len);
 }
 
 /*
@@ -519,6 +570,12 @@ void osd_req_flush_object(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
 	/*V2*/ u64 offset, /*V2*/ u64 len)
 {
+	if (unlikely(osd_req_is_ver1(or) && (offset || len))) {
+		OSD_DEBUG("OSD Ver1 flush on specific range ignored\n");
+		offset = 0;
+		len = 0;
+	}
+
 	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
 	_osd_req_encode_flush(or, op);
 }
@@ -1131,6 +1188,10 @@ enum { OSD_SEC_CAP_V1_ALL_CAPS =
 	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
 };
 
+enum { OSD_SEC_CAP_V2_ALL_CAPS =
+	OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT
+};
+
 void osd_sec_init_nosec_doall_caps(void *caps,
 	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
 {
@@ -1172,9 +1233,14 @@ void osd_sec_init_nosec_doall_caps(void *caps,
 }
 EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
 
+/* FIXME: Extract version from caps pointer.
+ *        Also Pete's target only supports caps from OSDv1 for now
+ */
 void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 {
-	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+	bool is_ver1 = true;
+	/* NOTE: They start at same address */
+	memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN);
 }
 
 bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms)
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index a647c51..8779f66 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -21,6 +21,23 @@
 
 /* Note: "NI" in comments below means "Not Implemented yet" */
 
+/* Configure of code:
+ * #undef if you *don't* want OSD v1 support in runtime.
+ * If #defined the initiator will dynamically configure to encode OSD v1
+ * CDB's if the target is detected to be OSD v1 only.
+ * OSD v2 only commands, options, and attributes will be ignored if target
+ * is v1 only.
+ * If #defined will result in bigger/slower code (OK Slower maybe not)
+ * Q: Should this be CONFIG_SCSI_OSD_VER1_SUPPORT and set from Kconfig?
+ */
+#define OSD_VER1_SUPPORT y
+
+enum osd_std_version {
+	OSD_VER_NONE = 0,
+	OSD_VER1 = 1,
+	OSD_VER2 = 2,
+};
+
 /*
  * Object-based Storage Device.
  * This object represents an OSD device.
@@ -31,11 +48,23 @@
 struct osd_dev {
 	struct scsi_device *scsi_dev;
 	unsigned def_timeout;
+
+#ifdef OSD_VER1_SUPPORT
+	enum osd_std_version version;
+#endif
 };
 
 void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
 void osd_dev_fini(struct osd_dev *);
 
+/* we might want to use function vector in the future */
+static inline void osd_dev_set_ver(struct osd_dev *dev, enum osd_std_version v)
+{
+#ifdef OSD_VER1_SUPPORT
+	dev->version = v;
+#endif
+}
+
 struct osd_request {
 	struct osd_cdb cdb;
 	struct osd_data_out_integrity_info out_data_integ;
@@ -65,6 +94,16 @@ struct osd_request {
 	enum osd_attributes_mode attributes_mode;
 };
 
+/* OSD Version control */
+static inline bool osd_req_is_ver1(struct osd_request *or)
+{
+#ifdef OSD_VER1_SUPPORT
+	return or->osd_dev->version == OSD_VER1;
+#else
+	return false;
+#endif
+}
+
 /**
  * How to use the osd library:
  *
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
index 77a74a3..ef7505e 100644
--- a/include/scsi/osd_protocol.h
+++ b/include/scsi/osd_protocol.h
@@ -25,9 +25,12 @@ enum {
 	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
 	OSDv1_CAP_LEN = 80,
 	/* Latest supported version */
-	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
-	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
-	OSD_CAP_LEN = OSDv1_CAP_LEN,
+/* 	OSD_ADDITIONAL_CDB_LENGTH = 216,*/
+	OSD_ADDITIONAL_CDB_LENGTH =
+		OSDv1_ADDITIONAL_CDB_LENGTH, /* FIXME: Pete rev-001 sup */
+	OSD_TOTAL_CDB_LEN = OSD_ADDITIONAL_CDB_LENGTH + 8,
+/* 	OSD_CAP_LEN = 104,*/
+	OSD_CAP_LEN = OSDv1_CAP_LEN,/* FIXME: Pete rev-001 sup */
 
 	OSD_SYSTEMID_LEN = 20,
 	OSD_CRYPTO_KEYID_SIZE = 20,
@@ -108,6 +111,7 @@ enum {
 	OSD_OFFSET_MAX_BITS = 28,
 
 	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MIN_SHIFT = 3,
 	OSD_OFFSET_MAX_SHIFT = 16,
 };
 
@@ -129,6 +133,16 @@ static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
 				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
 }
 
+/* Minimum 8 bytes alignment
+ * Same as v1 but since exponent can be signed than a less than
+ * 256 alignment can be reached with small offsets (<2GB)
+ */
+static inline osd_cdb_offset osd_encode_offset_v2(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				   OSD_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
 /* osd2r03: 5.2.1 Overview */
 struct osd_cdb_head {
 	struct scsi_varlen_cdb_hdr varlen_cdb;
@@ -144,6 +158,13 @@ struct osd_cdb_head {
 /*36*/			__be64		length;
 /*44*/			__be64		start_address;
 		} __packed v1;
+
+		struct __osdv2_cdb_addr_len {
+			/* called allocation_length in some commands */
+/*32*/			__be64	length;
+/*40*/			__be64	start_address;
+/*48*/			__be32 list_identifier;/* Rarely used */
+		} __packed v2;
 	};
 /*52*/	union { /* selected attributes mode Page/List/Single */
 		struct osd_attributes_page_mode {
@@ -182,6 +203,7 @@ struct osd_cdb_head {
 /*80*/
 
 /*160 v1*/
+/*184 v2*/
 struct osd_security_parameters {
 /*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
 /*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
@@ -189,6 +211,7 @@ struct osd_security_parameters {
 /*196*/osd_cdb_offset	data_out_integrity_check_offset;
 } __packed;
 /*200 v1*/
+/*224 v2*/
 
 struct osdv1_cdb {
 	struct osd_cdb_head h;
@@ -196,9 +219,16 @@ struct osdv1_cdb {
 	struct osd_security_parameters sec_params;
 } __packed;
 
+struct osdv2_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSD_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
 struct osd_cdb {
 	union {
 		struct osdv1_cdb v1;
+		struct osdv2_cdb v2;
 		u8 buff[OSD_TOTAL_CDB_LEN];
 	};
 } __packed;
@@ -269,6 +299,7 @@ struct osd_attributes_list_attrid {
 /*
  * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
  *                  for setting attributes
+ * NOTE: v2 is 8-bytes aligned, v1 is not aligned.
  */
 struct osd_attributes_list_element {
 	__be32 page;
@@ -279,6 +310,7 @@ struct osd_attributes_list_element {
 
 enum {
 	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+	OSD_ATTRIBUTES_ELEM_ALIGN = 8,
 };
 
 enum {
@@ -292,6 +324,12 @@ static inline unsigned osdv1_attr_list_elem_size(unsigned len)
 		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
 }
 
+static inline unsigned osdv2_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSD_ATTRIBUTES_ELEM_ALIGN);
+}
+
 /*
  * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
  */
@@ -326,6 +364,21 @@ static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
 	return be16_to_cpu(h->list_bytes);
 }
 
+struct osdv2_attributes_list_header {
+	u8 type;	/* lower 4-bits only */
+	u8 pad[3];
+/*4*/	__be32 list_bytes; /* Initiator shall set to zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv2_list_size(struct osdv2_attributes_list_header *h)
+{
+	return be32_to_cpu(h->list_bytes);
+}
+
 /* (osd-r10 6.13)
  * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
  *	for root_lstchg below
@@ -469,11 +522,36 @@ struct osdv1_cap_object_descriptor {
 } __packed;
 /*80 v1*/
 
-struct osd_capability {
+/*56 v2*/
+struct osd_cap_object_descriptor {
+	union {
+		struct {
+			__be32 allowed_attributes_access;
+/*60*/			__be32 policy_access_tag;
+/*64*/			__be16 boot_epoch;
+/*66*/			u8 reserved[72-66];
+/*72*/			__be64 allowed_partition_id;
+/*80*/			__be64 allowed_object_id;
+/*88*/			__be64 allowed_range_length;
+/*96*/			__be64 allowed_range_start;
+		} __packed obj_desc;
+
+		u8 object_descriptor[104-56]; /*48*/
+	};
+} __packed;
+/*104 v2*/
+
+struct osdv1_capability {
 	struct osd_capability_head h;
 	struct osdv1_cap_object_descriptor od;
 } __packed;
 
+struct osd_capability {
+	struct osd_capability_head h;
+/* 	struct osd_cap_object_descriptor od;*/
+	struct osdv1_cap_object_descriptor od; /* FIXME: Pete rev-001 sup */
+} __packed;
+
 /**
  * osd_sec_set_caps - set cap-bits into the capabilities header
  *
-- 
1.5.6.rc1.5.gadf6


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 11/14] osd_ktests: OSDv2 auto detection
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
                     ` (9 preceding siblings ...)
  2008-07-24 17:58   ` [RFC 10/14] libosd: OSD version 2 Support Boaz Harrosh
@ 2008-07-24 17:59   ` Boaz Harrosh
  2008-07-24 18:00   ` [RFC 12/14] osd: Kconfig file for in-tree builds Boaz Harrosh
                     ` (2 subsequent siblings)
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 17:59 UTC (permalink / raw)
  To: open-osd development
  Cc: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig, FUJITA Tomonori, linux-scsi


Auto detect an OSDv2 or OSDv1 target at run time. Note how none of the OSD
calls change, apart from the added detection code.

This test passes against both the IBM-OSD-SIM OSD1 target as well as Pete's
OSC's OSD2 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_ktests.c |   18 ++++++++++++++----
 1 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
index 3186fc8..45a0dcc 100644
--- a/drivers/scsi/osd/osd_ktests.c
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -101,6 +101,11 @@ int test_exec(struct osd_request *or, void *caps, const struct osd_obj_id *obj)
 
 #define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
 
+static char *osd_ver_desc(struct osd_request *or)
+{
+	return osd_req_is_ver1(or) ? "OSD1" : "OSD2";
+}
+
 int ktest_read_system_info(struct osd_dev *osd_dev)
 {
 	struct osd_request *or;
@@ -131,14 +136,14 @@ int ktest_read_system_info(struct osd_dev *osd_dev)
 
 	ret = test_exec(or, g_caps, &osd_root_object);
 	if (ret) {
-		OSD_ERR("Failed to detect %s => %d\n", "OSD1", ret);
+		OSD_ERR("Failed to detect %s => %d\n", osd_ver_desc(or), ret);
 		goto out;
 	}
 
 	osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
 
 	OSD_INFO("Detected %s device\n",
-		"OSD1");
+		osd_ver_desc(or));
 
 	pFirst = get_attrs[a++].val_ptr;
 	OSD_INFO("OSD_ATTR_RI_VENDOR_IDENTIFICATION [%s]\n",
@@ -459,8 +464,13 @@ int do_test_17(struct scsi_device *scsi_dev)
 
 	osd_dev_init(&osd_dev, scsi_dev);
 
-	if (ktest_read_system_info(&osd_dev))
-		goto dev_fini;
+	/* Auto-detect the osd version */
+	if (ktest_read_system_info(&osd_dev)) {
+		osd_dev_set_ver(&osd_dev, OSD_VER1);
+		OSD_DEBUG("converting to OSD1\n");
+		if (ktest_read_system_info(&osd_dev))
+			goto dev_fini;
+	}
 
 /* osd_format */
 	if (ktest_format(&osd_dev))
-- 
1.5.6.rc1.5.gadf6



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 12/14] osd: Kconfig file for in-tree builds
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
                     ` (10 preceding siblings ...)
  2008-07-24 17:59   ` [RFC 11/14] osd_ktests: OSDv2 auto detection Boaz Harrosh
@ 2008-07-24 18:00   ` Boaz Harrosh
  2008-07-24 18:02   ` [RFC 13/14] osd: Documentation for OSD library Boaz Harrosh
  2008-07-24 18:03   ` [RFC 14/14] scsi: Add osd library to build system Boaz Harrosh
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 18:00 UTC (permalink / raw)
  To: open-osd development
  Cc: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig, FUJITA Tomonori, linux-scsi


This file is not needed in the out-of-tree repository, but is put here
so the defines are kept in sync. (eg. CONFIG_SCSI_OSD_DEBUG)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kconfig |   41 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 41 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kconfig

diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
new file mode 100644
index 0000000..006fc87
--- /dev/null
+++ b/drivers/scsi/osd/Kconfig
@@ -0,0 +1,41 @@
+#
+# Kernel configuration file for the OSD scsi protocol
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public version 2 License as
+# published by the Free Software Foundation
+#
+# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
+#        How is it done properly?
+#
+
+config SCSI_OSD_INITIATOR
+	tristate "OSD-Initiator library"
+	depends on SCSI
+	help
+		Enable the OSD-Initiator library (libosd.ko).
+		NOTE: You must also select CRYPTO_SHA1 + CRYPTO_HMAC and their
+		dependencies
+
+config SCSI_OSD_ULD
+	tristate "OSD Upper Level driver"
+	depends on SCSI_OSD_INITIATOR
+	help
+		Build a SCSI upper layer driver that exports /dev/osdX devices
+		to user-mode for testing and controlling OSD devices. This is
+		only useful if you want to run the OSD regression tests
+
+config SCSI_OSD_DEBUG
+	bool "Compile All OSD modules with lots of DEBUG prints"
+	default n
+	depends on SCSI_OSD_INITIATOR
+	help
+		OSD Code is populated with lots of OSD_DEBUG(..) printouts to
+		dmesg. Enable this if you found a bug and you want to help us
+		track the problem (see also MAINTAINERS).
-- 
1.5.6.rc1.5.gadf6



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 13/14] osd: Documentation for OSD library
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
                     ` (11 preceding siblings ...)
  2008-07-24 18:00   ` [RFC 12/14] osd: Kconfig file for in-tree builds Boaz Harrosh
@ 2008-07-24 18:02   ` Boaz Harrosh
  2008-07-24 18:03   ` [RFC 14/14] scsi: Add osd library to build system Boaz Harrosh
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 18:02 UTC (permalink / raw)
  To: open-osd development
  Cc: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig, FUJITA Tomonori, linux-scsi


Add osd.txt to Documentation/scsi/

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 Documentation/scsi/osd.txt |  187 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 187 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/scsi/osd.txt

diff --git a/Documentation/scsi/osd.txt b/Documentation/scsi/osd.txt
new file mode 100644
index 0000000..6e85ad0
--- /dev/null
+++ b/Documentation/scsi/osd.txt
@@ -0,0 +1,187 @@
+The OSD Standard
+================
+OSD (Object-Based Storage Device) is a T10 SCSI command set that is designed
+to provide efficient operation of input/output logical units that manage the
+allocation, placement, and accessing of variable-size data-storage containers,
+called objects. Objects are intended to contain operating system and application
+constructs. Each object has associated attributes attached to it, which are
+integral part of the object and provide metadata about the object. The standard
+defines some common obligatory attributes, but user attributes can be added as
+needed.
+
+See: http://www.t10.org/ftp/t10/drafts/osd2/ for the latest draft for OSD 2
+or search the web for "OSD SCSI"
+
+OSD in the Linux Kernel
+=======================
+osd-initiator:
+  The main component of OSD in Kernel is the osd-initiator library. Its main
+user is intended to be the pNFS-over-objects layout driver, which uses objects
+as its back-end data storage. Other clients are the other osd parts listed below.
+
+osd-uld:
+  This is a SCSI ULD that registers for OSD type devices and provides a testing
+platform, both for the in-kernel initiator as well as connected targets. It
+currently has no useful user-mode API, though it could have if need be.
+
+There are no current plans for an OSD target implementation in kernel. For all
+needs, a user-mode target that is based on the scsi tgt target framework is
+available from Ohio Supercomputer Center (OSC) at:
+http://www.osc.edu/~pw/osd/index.php
+
+Files and Folders
+=================
+This is the complete list of files included in this work:
+include/scsi/
+	osd_initiator.h   Main API for the initiator library
+	osd_types.h	  Common OSD types
+	osd_sec.h	  Security Manager API
+	osd_protocol.h	  Wire definitions of the OSD standard protocol
+	osd_attributes.h  Wire definitions of OSD attributes
+
+drivers/scsi/osd/
+	osd_initiator.c   OSD-Initiator library implementation
+	osd_uld.c	  The OSD scsi ULD (used for testing)
+	osd_ktest.{h,c}	  In-kernel test suite (called by osd_uld)
+	osd_debug.h	  Some printk macros
+	Makefile	  For both in-tree and out-of-tree compilation
+	Kconfig		  Enables inclusion of the different pieces
+	osd_test.c	  User-mode application to call the kernel tests
+
+The OSD-Initiator Library
+=========================
+osd_initiator is a low level implementation of an osd initiator encoder.
+But even though, it should be intuitive and easy to use. Perhaps over time an
+higher lever will form that automates some of the more common recipes.
+
+init/fini:
+- osd_dev_init() associates a scsi_device with an osd_dev structure
+  and initializes some global pools. This should be done once per scsi_device
+  (OSD LUN). The osd_dev structure is needed for calling osd_start_request().
+
+- osd_dev_fini() cleans up before a osd_dev/scsi_device destruction.
+
+OSD commands encoding, execution, and decoding of results:
+
+struct osd_request's is used to iteratively encode an OSD command and carry
+its state throughout execution. Each request goes through these stages:
+
+a. osd_start_request() allocates the request.
+
+b. Any of the osd_req_* methods is used to encode a request of the specified
+   type.
+
+c. osd_req_add_{get,set}_attr_* may be called to add get/set attributes to the
+   CDB. "List" or "Page" mode can be used exclusively. The attribute-list API
+   can be called multiple times on the same request. However, only one
+   attribute-page can be read, as mandated by the OSD standard.
+
+d. osd_finalize_request() computes offsets into the data-in and data-out buffers
+   and signs the request using the provided capability key and integrity-
+   check parameters.
+
+e. osd_execute_request() may be called to execute the request via the block
+   layer and wait for its completion.  The request can be executed
+   asynchronously by calling the block layer API directly.
+
+f. After execution, osd_req_decode_sense() can be called to decode the request's
+   sense information.
+
+g. osd_req_decode_get_attr() may be called to retrieve osd_add_get_attr_list()
+   values.
+
+h. osd_end_request() must be called to deallocate the request and any resource
+   associated with it. Note that osd_end_request cleans up the request at any
+   stage and it must always be called after a successful osd_start_request().
+
+osd_request's structure:
+
+The OSD standard defines a complex structure of IO segments pointed to by
+members in the CDB. Up to 3 segments can be deployed in the IN-Buffer and up to
+4 in the OUT-Buffer. The ASCII illustration below depicts a secure-read with
+associated get+set of attributes-lists. Other combinations very on the same
+basic theme. From no-segments-used up to all-segments-used.
+
+|________OSD-CDB__________|
+|                         |
+|read_len (offset=0)     -|---------\
+|                         |         |
+|get_attrs_list_length    |         |
+|get_attrs_list_offset   -|----\    |
+|                         |    |    |
+|retrieved_attrs_alloc_len|    |    |
+|retrieved_attrs_offset  -|----|----|-\
+|                         |    |    | |
+|set_attrs_list_length    |    |    | |
+|set_attrs_list_offset   -|-\  |    | |
+|                         | |  |    | |
+|in_data_integ_offset    -|-|--|----|-|-\
+|out_data_integ_offset   -|-|--|--\ | | |
+\_________________________/ |  |  | | | |
+                            |  |  | | | |
+|_______OUT-BUFFER________| |  |  | | | |
+|      Set attr list      |</  |  | | | |
+|                         |    |  | | | |
+|-------------------------|    |  | | | |
+|   Get attr descriptors  |<---/  | | | |
+|                         |       | | | |
+|-------------------------|       | | | |
+|    Out-data integrity   |<------/ | | |
+|                         |         | | |
+\_________________________/         | | |
+                                    | | |
+|________IN-BUFFER________|         | | |
+|      In-Data read       |<--------/ | |
+|                         |           | |
+|-------------------------|           | |
+|      Get attr list      |<----------/ |
+|                         |             |
+|-------------------------|             |
+|    In-data integrity    |<------------/
+|                         |
+\_________________________/
+
+A block device request can carry bidirectional payload by means of associating
+a bidi_read request with a main write-request. Each in/out request is described
+by a chain of BIOs associated with each request.
+The CDB is of a SCSI VARLEN CDB format, as described by OSD standard.
+The OSD standard also mandates alignment restrictions at start of each segment.
+
+In the code, in struct osd_request, there are two _osd_io_info structures to
+describe the IN/OUT buffers above, two BIOs for the data payload and up to five
+_osd_req_data_segment structures to hold the different segments allocation and
+information.
+
+Important: We have chosen to disregard the assumption that a BIO-chain (and
+the resulting sg-list) describes a linear memory buffer. Meaning only first and
+last scatter chain can be incomplete and all the middle chains are of PAGE_SIZE.
+For us, a scatter-gather-list, as its name implies and as used by the Networking
+layer, is to describe a vector of buffers that will be transferred to/from the
+wire. It works very well with current iSCSI transport. iSCSI is currently the
+only deployed OSD transport. In the future we anticipate SAS and FC attached OSD
+devices as well.
+
+The OSD Testing ULD
+===================
+TODO: More user-mode control on tests.
+
+Authors, Mailing list
+=====================
+Please communicate with us on any deployment of osd, whether using this code
+or not.
+
+Any problems, questions, bug reports, lonely OSD nights, please email:
+   OSD Dev List <osd-dev@open-osd.org>
+
+Boaz Harrosh <bharrosh@panasas.com>
+Benny Halevy <bhalevy@panasas.com>
+
+References
+==========
+Weber, R., "SCSI Object-Based Storage Device Commands",
+T10/1355-D ANSI/INCITS 400-2004,
+http://www.t10.org/ftp/t10/drafts/osd/osd-r10.pdf
+
+Weber, R., "SCSI Object-Based Storage Device Commands -2 (OSD-2)"
+T10/1729-D, Working Draft, rev. 3
+http://www.t10.org/ftp/t10/drafts/osd2/osd2r03.pdf
-- 
1.5.6.rc1.5.gadf6



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [RFC 14/14] scsi: Add osd library to build system
  2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
                     ` (12 preceding siblings ...)
  2008-07-24 18:02   ` [RFC 13/14] osd: Documentation for OSD library Boaz Harrosh
@ 2008-07-24 18:03   ` Boaz Harrosh
  13 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-07-24 18:03 UTC (permalink / raw)
  To: open-osd development
  Cc: Benny Halevy, James Bottomley, Mike Christie, Pete Wyckoff,
	Christoph Hellwig, FUJITA Tomonori, linux-scsi


OSD in kernel source code is assumed to be at:
drivers/scsi/osd/ with its own Makefile and Kconfig

Add includes to them from drivers/scsi Makefile and Kconfig
Add osd to MAINTAINERS file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 MAINTAINERS           |   10 ++++++++++
 drivers/scsi/Kconfig  |    2 ++
 drivers/scsi/Makefile |    2 ++
 3 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 93fd6b2..814d5b0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3137,6 +3137,16 @@ L:	orinoco-devel@lists.sourceforge.net
 W:	http://www.nongnu.org/orinoco/
 S:	Maintained
 
+OSD LIBRARY
+P:	Boaz Harrosh
+M:	bharrosh@panasas.com
+P:	Benny Halevy
+M:	bhalevy@panasas.com
+L:	osd-dev@open-osd.org
+W:	http://open-osd.org
+T:	git://git.open-osd.org/osd-lib.git
+S:	Maintained
+
 PA SEMI ETHERNET DRIVER
 P:	Olof Johansson
 M:	olof@lixom.net
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index c7f0629..60a7e3a 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1795,4 +1795,6 @@ source "drivers/scsi/pcmcia/Kconfig"
 
 source "drivers/scsi/device_handler/Kconfig"
 
+source "drivers/scsi/osd/Kconfig"
+
 endmenu
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 72fd504..1e49632 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -135,6 +135,8 @@ obj-$(CONFIG_CHR_DEV_SG)	+= sg.o
 obj-$(CONFIG_CHR_DEV_SCH)	+= ch.o
 obj-$(CONFIG_SCSI_ENCLOSURE)	+= ses.o
 
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += osd/
+
 # This goes last, so that "real" scsi devices probe earlier
 obj-$(CONFIG_SCSI_DEBUG)	+= scsi_debug.o
 
-- 
1.5.6.rc1.5.gadf6



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* Re: [RFC 03/14] osd_uld: OSD scsi ULD
  2008-07-24 17:47   ` [RFC 03/14] osd_uld: OSD scsi ULD Boaz Harrosh
@ 2008-07-27 21:16     ` James Bottomley
  2008-08-06 17:25       ` Boaz Harrosh
  0 siblings, 1 reply; 183+ messages in thread
From: James Bottomley @ 2008-07-27 21:16 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: Benny Halevy, Mike Christie, Pete Wyckoff, Christoph Hellwig,
	FUJITA Tomonori, linux-scsi, open-osd ml

On Thu, 2008-07-24 at 20:47 +0300, Boaz Harrosh wrote:
> Add a Linux driver module that registers as a SCSI ULD and probes for OSD type
> SCSI devices.
> 
> When an OSD-type SCSI device is found a character device is created in the form
> of /dev/osdX - where X goes from 0 up to hard coded 64.
> The Major character device number used is *232*, which is free (as of Linux
> v2.6.27). The same Major was used by the old IBM initiator project.
> 
> TODO: How to dynamically allocate a Major and have a /dev/osdX entry linked
> to it? Do I need/should reserve the minor range in advance, if not how?
> 
> A single ioctl is currently supported that will invoke an in-kernel test on
> the specified OSD device (lun).

The first thing that immediately leaps to mind is are you sure this
should be a character device?  Since it's only open/close/ioctl (as in
no read/write) you could then use all the file bdev handling to get back
to struct osd_device, plus you can bind to bsg (and SG_IO) which is
unaccountably missing in this prototype.

The second observation is that refcounting in this driver is
non-existent.  Doing a kfree(osd_dev) from osd_remove makes open device
remove module do something else look to be a certain oops ... you can
use the refcounting models of sd or st to see how this is done.

There's a convention that gendisk->private_data points to a pointer to
the driver.  This was originally a viro clever trick to allow the
private_data to store both the driver and the uld device (struct
osd_dev).  I think we've dispensed with needing the driver, so perhaps
this trick is unnecessary, but you'll need something similar to do
refcounting properly.

Since OSDs are currently potentially removable spinning media with
caches, it looks like you potentially also need locking control.  You
might also need a shutdown method to cope with object flushing before
power down.

Somehow the capacity has to be plumbed in (this also really makes them
block devices not character devices).  It looks like the total capacity
attribute of the root information attributes page would be appropriate
for this.

The ioctl flow needs to be plumbed into scsi_ioctl() since the gendisk
ULD will need to handle all the standard SCSI ioctls.

You can't have 232 char as the major for this ... it's already assigned
to biometric devices (although I think 232 block is free).  Whatever
number you choose has to be requested through lanana and
Documentation/device-list.txt updated accordingly.

(as you noted, TYPE_OSD has to be correctly in the global headers)

Please don't use sysfs_create_file (it can be racy and accident prone);
just do the extra files as declared attributes of the osd class and let
drivers/base handle all the setup/teardown  (sd is a good template).

James



^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [RFC 03/14] osd_uld: OSD scsi ULD
  2008-07-27 21:16     ` James Bottomley
@ 2008-08-06 17:25       ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-08-06 17:25 UTC (permalink / raw)
  To: James Bottomley
  Cc: Benny Halevy, Mike Christie, Pete Wyckoff, Christoph Hellwig,
	FUJITA Tomonori, linux-scsi, open-osd ml

James Bottomley wrote:
> On Thu, 2008-07-24 at 20:47 +0300, Boaz Harrosh wrote:
>> Add a Linux driver module that registers as a SCSI ULD and probes for OSD type
>> SCSI devices.
>>
>> When an OSD-type SCSI device is found a character device is created in the form
>> of /dev/osdX - where X goes from 0 up to hard coded 64.
>> The Major character device number used is *232*, which is free (as of Linux
>> v2.6.27). The same Major was used by the old IBM initiator project.
>>
>> TODO: How to dynamically allocate a Major and have a /dev/osdX entry linked
>> to it? Do I need/should reserve the minor range in advance, if not how?
>>
>> A single ioctl is currently supported that will invoke an in-kernel test on
>> the specified OSD device (lun).
> 
> The first thing that immediately leaps to mind is are you sure this
> should be a character device?  Since it's only open/close/ioctl (as in
> no read/write) you could then use all the file bdev handling to get back
> to struct osd_device, plus you can bind to bsg (and SG_IO) which is
> unaccountably missing in this prototype.

AN OSD device is by no means a BLOCK device and it does not export any
such functionality per-se. It is a completely new SCSI command-set and
does not inherent any SCSI block functionality. Except these commands 
explicitly specified that allow the device probing and login(iscsi).

There is a provision to send standard SCSI commnds (READ/WRITE etc..)
to individual objects inside the OSD. But only after all proper 
administration and security was set for the device, partition, and 
object in question.

We have thought about emulating such a layer where once login into
an OSD device. a scan will look for all objects that, say, have an
"export-block-device" special user defined attribute, and will export
these as scsi-block devices, which lives inside OSD objects. This
way you can have over commits, OSD-security, data migration, raid and
all kind of fun stuff. Over an OSD grid. But people we ask did not
like it. and frankly we didn't either. So we are not going to do that.

So an OSD can be used for data storage but not in the traditional sense
there must be an higher layer that makes policy decisions on how a traditional
file system sits over an OSD device. But this is not the scope of this layer.
We have in our labs two such higher beasts that do that. One is the 
pNFS-objects that caries out policy governed by a network Object-based file
system, and initiates all the proper OSD commands to read/write etc .. to
OSD targets. And an osdfs from IBM that we have converted to use our
Initiator. These higher level layers will make policy decisions (break
some eggs) and will have to issue the right OSD commands in the proper
state, for flushing read/write create and all these things that they
need to take care of. At this layer of Initiator library we cannot know
all this because we don't set any policy.

So to answer your question It's a char device because that was the easiest
way for us to export a Kernel API for issuing test vectors to OSD targets.
Perhaps we could make a sysfs API to do the same thing.

> 
> The second observation is that refcounting in this driver is
> non-existent.  Doing a kfree(osd_dev) from osd_remove makes open device
> remove module do something else look to be a certain oops ... you can
> use the refcounting models of sd or st to see how this is done.
> 

I will look into this thanks

I have done some tests and I saw that as long as I have files open the
cdev will not die. and since I'm only removed when .remove is called by
the scsi-ml then I'm some how protect as long as I'm working. So it looks
like the system protects me from deletion while working. (Note that I only
have synchronous ioctl)

What I have not checked, is the coupling between the driver module, and it's 
open devices. I assumed the Kernel takes care of that as long as I have files
open on devices made by the driver, but apparently I was wrong.

> There's a convention that gendisk->private_data points to a pointer to
> the driver.  This was originally a viro clever trick to allow the
> private_data to store both the driver and the uld device (struct
> osd_dev).  I think we've dispensed with needing the driver, so perhaps
> this trick is unnecessary, but you'll need something similar to do
> refcounting properly.
> 

I'm not sure I understand what you mean. I only have a 
struct osd_uld_device allocated per scsi_device that holds pointers to
allocated resources that are freed when .remove is called on the 
associated scsi_device. I do not keep any driver information.

If you meant that when I'll do a refcounting I will need one then
I thought I will just keep a global counter and locks so I don't need
a pointer per se.

> Since OSDs are currently potentially removable spinning media with
> caches, it looks like you potentially also need locking control.  You
> might also need a shutdown method to cope with object flushing before
> power down.
> 

Again as explained above this is out of scope here. This is not a file 
system or block device that exports any data storage to users. Higher
level systems like osdfs or pNFS-objects layout driver will (do) take
care of that at the proper state. This here is just a library that exports
OSD command set, and a ULD that let you issue test vectors to an OSD target.

> Somehow the capacity has to be plumbed in (this also really makes them
> block devices not character devices).  It looks like the total capacity
> attribute of the root information attributes page would be appropriate
> for this.
> 

Again an higher level that actually knows these things does that, this
OSD-library does not make any policy decisions.

> The ioctl flow needs to be plumbed into scsi_ioctl() since the gendisk
> ULD will need to handle all the standard SCSI ioctls.
> 
Again not at this level

> You can't have 232 char as the major for this ... it's already assigned
> to biometric devices (although I think 232 block is free).  Whatever
> number you choose has to be requested through lanana and
> Documentation/device-list.txt updated accordingly.
> 

Sorry last I checked it was free, or perhaps I did not identify it
correctly. I'll fix that.

> (as you noted, TYPE_OSD has to be correctly in the global headers)
> 
> Please don't use sysfs_create_file (it can be racy and accident prone);
> just do the extra files as declared attributes of the osd class and let
> drivers/base handle all the setup/teardown  (sd is a good template).
> 

I will not, thanks. Though currently I don't have any planed and it is
all in comments. I will remove these comments for the final version.

> James
> 
> 

Sorry for the late response I was cut up into something else.

As I said in introductory email. I have no good use planed for
an OSD ULD. It is only used for sending test vectors to make 
sure changes work and there are no new regressions.
I do not know what is the policy for these things in Linux
Should it stay out-of-tree and risk bit-rot or it should be in-tree
but Kconfigured in such a way that distributions don't end up
putting it on CDs. Please advise.

Thank you very much for the review
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* [PATCHSET 00/18] open-osd: OSD Initiator library for Linux
       [not found] <48876009.8010701@panasas.com>
@ 2008-11-04 16:09   ` Boaz Harrosh
  2008-11-04 16:09   ` Boaz Harrosh
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:09 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: Sami.Iren, Pete Wyckoff, linux-kernel


Please consider for inclusion, an in-kernel OSD initiator
library. Its main users are planned to be various OSD based file
systems and the pNFS-Objects Layout Driver. (To be submitted soon)
 
To try out and run the library please visit
http://open-osd.org and follow the instructions there.

The submitted patchset is also available via git at:
   git://git.open-osd.org/linux-open-osd.git osd
   http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=osd

Or a compact out-of-tree repository that includes sources 
and some extras:
   git://git.open-osd.org/open-osd.git master
   http://git.open-osd.org/gitweb.cgi?p=open-osd.git;a=summary

The submitted patches add public header files to include/scsi/
for use by other subsystems. The source files and private headers 
are put at a new drivers/scsi/osd/ directory, with the privilege of
a separate Makefile and Kconfig.

here is the list of patches:

[PATCH 01/18] major.h: char-major number for OSD device driver
	A request for a new char-device major number

[PATCH 02/18] scsi: OSD_TYPE
	The OSD scsi type constant definition.

[PATCH 03/18] libosd: OSDv1 Headers
[PATCH 04/18] libosd: OSDv1 preliminary implementation
  Most basic, but usable library module (libosd.ko) including
  Kbuild/Makefile.

[PATCH 05/18] osd_uld: OSD scsi ULD
[PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel
[PATCH 07/18] osd_test: User-mode application to run the OSD tests
[PATCH 08/18] osd_ktests: Add basic OSD tests
  These patches add a scsi ULD for OSD type devices. Please see
  commit logs for details.

[PATCH 09/18] libosd: attributes Support
[PATCH 10/18] osd_ktests: Test Attribute lists
[PATCH 11/18] libosd: OSD Security processing stubs
[PATCH 12/18] libosd: Add Flush and List-objects support
[PATCH 13/18] libosd: Not implemented commands
[PATCH 14/18] libosd: OSD version 2 Support
[PATCH 15/18] libosd: OSDv2 auto detection
  Up to here this is a fairly complete body of work, to support
  both OSD1 and OSD2 targets. Main pieces that are still missing
  from the library at this point are: The OSD2 capabilities structure,
  do to lack of an OSD target that supports it, so it was never tested.
  And the absence of any OSD-security methods other then NO_SECURITY.
  These will come in future versions.

[PATCH 16/18] osd: Documentation for OSD library
  Some reading about OSD in general and further usability instructions.
  Please comment on anything missing from this document.

[PATCH 17/18] osd: Kconfig file for in-tree builds
[PATCH 18/18] scsi: Add osd library to build system
  The in-tree compilation is only enabled at the end of the patchset.
  Run your favorite configure-tool to enable the library and osd_uld
  compilation. Default is off.
  The patchset is however fully bisectable and compilable from the beginning if
  Invoked out-of-tree style with the -M switch. (see out-of-tree URL for how)

We would like this to sit in -mm tree for a while to make sure it is compilable
on all platform. We don't see any danger of it being included in the next Kernel
as it will not break anything. Of course, given that we have addressed everyone's
comments, at this round.

What's new/changed since the last RFC:
  Mainly work has been done to address James comments about the ULD.
See http://archive.netbsd.se/?ml=linux-scsi&a=2008-07&m=8051556
I hope I've nailed down all possible problems in the reference
counting / locking of both the osd_uld_device structure , and the MODULE.
Also a new API was devised for in-kernel users to query for osd devices.
See: "[PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel"
for further discussion on this subject.
  Also the development and support of osdfs, submitted as RFC last week, was
a good test bed for stability and usability. So there were a few fixes and
cleanups do to that effort.

All-in-all I'm very confident in this work and feel it can serve as a good
base for OSD work in the Linux Kernel. We welcome anyone to please try this
SW, test it, break it to pieces, and please tell us about your experience.

Thanks
Boaz


^ permalink raw reply	[flat|nested] 183+ messages in thread

* [PATCHSET 00/18] open-osd: OSD Initiator library for Linux
@ 2008-11-04 16:09   ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:09 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: Sami.Iren, Pete Wyckoff, linux-kernel


Please consider for inclusion, an in-kernel OSD initiator
library. Its main users are planned to be various OSD based file
systems and the pNFS-Objects Layout Driver. (To be submitted soon)
 
To try out and run the library please visit
http://open-osd.org and follow the instructions there.

The submitted patchset is also available via git at:
   git://git.open-osd.org/linux-open-osd.git osd
   http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=osd

Or a compact out-of-tree repository that includes sources 
and some extras:
   git://git.open-osd.org/open-osd.git master
   http://git.open-osd.org/gitweb.cgi?p=open-osd.git;a=summary

The submitted patches add public header files to include/scsi/
for use by other subsystems. The source files and private headers 
are put at a new drivers/scsi/osd/ directory, with the privilege of
a separate Makefile and Kconfig.

here is the list of patches:

[PATCH 01/18] major.h: char-major number for OSD device driver
	A request for a new char-device major number

[PATCH 02/18] scsi: OSD_TYPE
	The OSD scsi type constant definition.

[PATCH 03/18] libosd: OSDv1 Headers
[PATCH 04/18] libosd: OSDv1 preliminary implementation
  Most basic, but usable library module (libosd.ko) including
  Kbuild/Makefile.

[PATCH 05/18] osd_uld: OSD scsi ULD
[PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel
[PATCH 07/18] osd_test: User-mode application to run the OSD tests
[PATCH 08/18] osd_ktests: Add basic OSD tests
  These patches add a scsi ULD for OSD type devices. Please see
  commit logs for details.

[PATCH 09/18] libosd: attributes Support
[PATCH 10/18] osd_ktests: Test Attribute lists
[PATCH 11/18] libosd: OSD Security processing stubs
[PATCH 12/18] libosd: Add Flush and List-objects support
[PATCH 13/18] libosd: Not implemented commands
[PATCH 14/18] libosd: OSD version 2 Support
[PATCH 15/18] libosd: OSDv2 auto detection
  Up to here this is a fairly complete body of work, to support
  both OSD1 and OSD2 targets. Main pieces that are still missing
  from the library at this point are: The OSD2 capabilities structure,
  do to lack of an OSD target that supports it, so it was never tested.
  And the absence of any OSD-security methods other then NO_SECURITY.
  These will come in future versions.

[PATCH 16/18] osd: Documentation for OSD library
  Some reading about OSD in general and further usability instructions.
  Please comment on anything missing from this document.

[PATCH 17/18] osd: Kconfig file for in-tree builds
[PATCH 18/18] scsi: Add osd library to build system
  The in-tree compilation is only enabled at the end of the patchset.
  Run your favorite configure-tool to enable the library and osd_uld
  compilation. Default is off.
  The patchset is however fully bisectable and compilable from the beginning if
  Invoked out-of-tree style with the -M switch. (see out-of-tree URL for how)

We would like this to sit in -mm tree for a while to make sure it is compilable
on all platform. We don't see any danger of it being included in the next Kernel
as it will not break anything. Of course, given that we have addressed everyone's
comments, at this round.

What's new/changed since the last RFC:
  Mainly work has been done to address James comments about the ULD.
See http://archive.netbsd.se/?ml=linux-scsi&a=2008-07&m=8051556
I hope I've nailed down all possible problems in the reference
counting / locking of both the osd_uld_device structure , and the MODULE.
Also a new API was devised for in-kernel users to query for osd devices.
See: "[PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel"
for further discussion on this subject.
  Also the development and support of osdfs, submitted as RFC last week, was
a good test bed for stability and usability. So there were a few fixes and
cleanups do to that effort.

All-in-all I'm very confident in this work and feel it can serve as a good
base for OSD work in the Linux Kernel. We welcome anyone to please try this
SW, test it, break it to pieces, and please tell us about your experience.

Thanks
Boaz


^ permalink raw reply	[flat|nested] 183+ messages in thread

* [PATCH 01/18] major.h: char-major number for OSD device driver
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:17     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:17 UTC (permalink / raw)
  To: Torben Mathiasen, James Bottomley, Andrew Morton, Mike Christie,
	FUJITA Tomonori, Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

We need a major for a char device for our OSD device driver.
Attached is a proposed patch for the Documentation/devices.txt
and include/linux/major.h files.

I have allocated the *260* char device as it looked like the next
available on the lanana.org web-site
(http://lanana.org/docs/device-list/devices-2.6+.txt)

Any number will do. Please allocate a number for us

(See http:/open-osd.org for further information)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
CC: Torben Mathiasen <device@lanana.org>
---
 Documentation/devices.txt |    6 ++++++
 include/linux/major.h     |    1 +
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 05c8064..d18070b 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -3142,6 +3142,12 @@ Your cooperation is appreciated.
 		  1 = /dev/blockrom1	Second ROM card's translation layer interface
 		  ...
 
+260 char	OSD (Object-based-device) SCSI Device
+		  0 = /dev/osd0		First OSD Device
+		  1 = /dev/osd1		Second OSD Device
+		  ...
+		  255 = /dev/osd255	256th OSD Device
+
  ****	ADDITIONAL /dev DIRECTORY ENTRIES
 
 This section details additional entries that should or may exist in
diff --git a/include/linux/major.h b/include/linux/major.h
index 8824945..058ec15 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -171,5 +171,6 @@
 #define VIOTAPE_MAJOR		230
 
 #define BLOCK_EXT_MAJOR		259
+#define SCSI_OSD_MAJOR		260	/* open-osd's OSD scsi device */
 
 #endif
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 01/18] major.h: char-major number for OSD device driver
@ 2008-11-04 16:17     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:17 UTC (permalink / raw)
  To: Torben Mathiasen, James Bottomley, Andrew Morton, Mike Christie, FUJITA
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

We need a major for a char device for our OSD device driver.
Attached is a proposed patch for the Documentation/devices.txt
and include/linux/major.h files.

I have allocated the *260* char device as it looked like the next
available on the lanana.org web-site
(http://lanana.org/docs/device-list/devices-2.6+.txt)

Any number will do. Please allocate a number for us

(See http:/open-osd.org for further information)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
CC: Torben Mathiasen <device@lanana.org>
---
 Documentation/devices.txt |    6 ++++++
 include/linux/major.h     |    1 +
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 05c8064..d18070b 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -3142,6 +3142,12 @@ Your cooperation is appreciated.
 		  1 = /dev/blockrom1	Second ROM card's translation layer interface
 		  ...
 
+260 char	OSD (Object-based-device) SCSI Device
+		  0 = /dev/osd0		First OSD Device
+		  1 = /dev/osd1		Second OSD Device
+		  ...
+		  255 = /dev/osd255	256th OSD Device
+
  ****	ADDITIONAL /dev DIRECTORY ENTRIES
 
 This section details additional entries that should or may exist in
diff --git a/include/linux/major.h b/include/linux/major.h
index 8824945..058ec15 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -171,5 +171,6 @@
 #define VIOTAPE_MAJOR		230
 
 #define BLOCK_EXT_MAJOR		259
+#define SCSI_OSD_MAJOR		260	/* open-osd's OSD scsi device */
 
 #endif
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 02/18] scsi: OSD_TYPE
  2008-11-04 16:09   ` Boaz Harrosh
                     ` (2 preceding siblings ...)
  (?)
@ 2008-11-04 16:42   ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:42 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

- Define the OSD_TYPE scsi device and let it show up in scans

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/scsi_scan.c |    1 +
 include/scsi/scsi.h      |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index b14dc02..633cb87 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -783,6 +783,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
 	case TYPE_ENCLOSURE:
 	case TYPE_COMM:
 	case TYPE_RAID:
+	case TYPE_OSD:
 		sdev->writeable = 1;
 		break;
 	case TYPE_ROM:
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index a109165..de1cef2 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -263,6 +263,7 @@ static inline int scsi_status_is_good(int status)
 #define TYPE_RAID           0x0c
 #define TYPE_ENCLOSURE      0x0d    /* Enclosure Services Device */
 #define TYPE_RBC	    0x0e
+#define TYPE_OSD            0x11
 #define TYPE_NO_LUN         0x7f
 
 /* SCSI protocols; these are taken from SPC-3 section 7.5 */
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 02/18] scsi: OSD_TYPE
  2008-11-04 16:09   ` Boaz Harrosh
  (?)
  (?)
@ 2008-11-04 16:42   ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:42 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

- Define the OSD_TYPE scsi device and let it show up in scans

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/scsi_scan.c |    1 +
 include/scsi/scsi.h      |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index b14dc02..633cb87 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -783,6 +783,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
 	case TYPE_ENCLOSURE:
 	case TYPE_COMM:
 	case TYPE_RAID:
+	case TYPE_OSD:
 		sdev->writeable = 1;
 		break;
 	case TYPE_ROM:
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index a109165..de1cef2 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -263,6 +263,7 @@ static inline int scsi_status_is_good(int status)
 #define TYPE_RAID           0x0c
 #define TYPE_ENCLOSURE      0x0d    /* Enclosure Services Device */
 #define TYPE_RBC	    0x0e
+#define TYPE_OSD            0x11
 #define TYPE_NO_LUN         0x7f
 
 /* SCSI protocols; these are taken from SPC-3 section 7.5 */
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 03/18] libosd: OSDv1 Headers
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 28348 bytes --]

Headers only patch.

osd_protocol.h
	Contains a C-fied definition of the T10 OSD standard
osd_types.h
	Contains CPU order common used types
osd_initiator.h
	API definition of the osd_initiator library
osd_sec.h
	Contains High level API for the security manager.

[Note that checkpatch spews errors on things that are valid in this context
and will not be fixed]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
 include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_sec.h       |   45 ++++
 include/scsi/osd_types.h     |   40 ++++
 4 files changed, 914 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_initiator.h
 create mode 100644 include/scsi/osd_protocol.h
 create mode 100644 include/scsi/osd_sec.h
 create mode 100644 include/scsi/osd_types.h

diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
new file mode 100644
index 0000000..24a70b7
--- /dev/null
+++ b/include/scsi/osd_initiator.h
@@ -0,0 +1,332 @@
+/*
+ * osd_initiator.h - OSD initiator API definition
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_INITIATOR_H__
+#define __OSD_INITIATOR_H__
+
+#include <linux/blkdev.h>
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/* Note: "NI" in comments below means "Not Implemented yet" */
+
+/*
+ * Object-based Storage Device.
+ * This object represents an OSD device.
+ * It is not a full linux device in any way. It is only
+ * a place to hang resources associated with a Linux
+ * request Q and some default properties.
+ */
+struct osd_dev {
+	struct scsi_device *scsi_dev;
+	unsigned def_timeout;
+};
+
+void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
+void osd_dev_fini(struct osd_dev *);
+
+struct osd_request;
+typedef void (osd_req_done_fn)(struct osd_request *, void *);
+
+struct osd_request {
+	struct osd_cdb cdb;
+	struct osd_data_out_integrity_info out_data_integ;
+	struct osd_data_in_integrity_info in_data_integ;
+
+	struct osd_dev *osd_dev;
+	struct request *request;
+
+	struct _osd_req_data_segment {
+		void *buff;
+		unsigned alloc_size; /* 0 here means not allocated by us */
+		unsigned total_bytes;
+	} set_attr, enc_get_attr, get_attr;
+
+	struct _osd_io_info {
+		struct bio *bio;
+		u64 total_bytes;
+		struct request *req;
+		struct _osd_req_data_segment *last_seg;
+		u8 *pad_buff;
+	} out, in;
+
+	gfp_t alloc_flags;
+	unsigned timeout;
+	unsigned retries;
+	u8 sense[OSD_MAX_SENSE_LEN];
+	enum osd_attributes_mode attributes_mode;
+
+	osd_req_done_fn *async_done;
+	void *async_private;
+	int async_error;
+};
+
+/**
+ * How to use the osd library:
+ *
+ * osd_start_request
+ *	Allocates a request.
+ *
+ * osd_req_*
+ *	Call one of, to encode the desired operation.
+ *
+ * osd_add_{get,set}_attr
+ *	Optionally add attributes to the CDB, list or page mode.
+ *
+ * osd_finalize_request
+ *	Computes final data out/in offsets and signs the request,
+ *	making it ready for execution.
+ *
+ * osd_execute_request
+ *	May be called to execute it through the block layer. Other wise submit
+ *	the associated block request in some other way.
+ *
+ * After execution:
+ * osd_req_decode_sense
+ *	Decodes sense information to verify execution results.
+ *
+ * osd_req_decode_get_attr
+ *	Retrieve osd_add_get_attr_list() values if used.
+ *
+ * osd_end_request
+ *	Must be called to deallocate the request.
+ */
+
+/**
+ * osd_start_request - Allocate and initialize an osd_request
+ *
+ * @osd_dev:    OSD device that holds the scsi-device and default values
+ *              that the request is associated with.
+ * @gfp:        The allocation flags to use for request allocation, and all
+ *              subsequent allocations. This will be stored at
+ *              osd_request->alloc_flags, can be changed by user later
+ *
+ * Allocate osd_request and initialize all members to the
+ * default/initial state.
+ */
+struct osd_request *osd_start_request(struct osd_dev *, gfp_t gfp);
+
+enum osd_req_options {
+	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
+	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
+
+	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
+};
+
+/**
+ * osd_finalize_request - Sign request and prepare request for execution
+ *
+ * @or:		osd_request to prepare
+ * @options:	combination of osd_req_options bit flags or 0.
+ * @cap	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
+ *              The security manager as capabilities for this cdb.
+ * @cap_key	The cryptographic key used to sign the cdb/data. Can be null
+ *              if NOSEC is used.
+ *
+ * The actual request and bios are only allocated here, so are the get_attr
+ * buffers that will receive the returned attributes. Copy's @cap to cdb.
+ * Sign the cdb/data with @cap_key.
+ */
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key);
+
+/**
+ * osd_execute_request - Execute the request synchronously through
+ *                       the block-layer
+ * @or:		osd_request to Executed
+ *
+ * Calls blk_execute_rq to q the command and waits for completion.
+ */
+int osd_execute_request(struct osd_request *or);
+
+/**
+ * osd_execute_request_async - submits the request for execution through
+ *                             the block-layer without waitting.
+ * @or:                      - osd_request to Executed
+ * @done: (Optional)         - Called at end of execution
+ * @private:                 - Will be passes to @done function
+ *
+ * Calls blk_execute_rq_nowait to q the command. When execution is done
+ * Optionally calles @done with @private as parameter. or->async_error has the
+ * Return code
+ */
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private);
+
+/**
+ * osd_end_request - return osd_request to free store
+ *
+ * @or:		osd_request to free
+ *
+ * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
+ */
+void osd_end_request(struct osd_request *or);
+
+/*
+ * CDB Encoding
+ *
+ * Note: call only one of the following methods.
+ */
+
+/*
+ * Device commands
+ */
+void osd_req_set_master_seed_xchg(struct osd_request *, ...);/* NI */
+void osd_req_set_master_key(struct osd_request *, ...);/* NI */
+
+void osd_req_format(struct osd_request *, u64 tot_capacity);
+
+/* list all partitions
+ * @list header must be initialized to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_dev_partitions(struct osd_request *,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
+
+void osd_req_flush_obsd(struct osd_request *,
+	enum osd_options_flush_scope_values);
+
+void osd_req_perform_scsi_command(struct osd_request *,
+	const u8 *cdb, ...);/* NI */
+void osd_req_task_management(struct osd_request *, ...);/* NI */
+
+/*
+ * Partition commands
+ */
+void osd_req_create_partition(struct osd_request *, osd_id partition);
+void osd_req_remove_partition(struct osd_request *, osd_id partition);
+
+void osd_req_set_partition_key(struct osd_request *,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
+
+/* list all collections in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_collections(struct osd_request *,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+/* list all objects in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_objects(struct osd_request *,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+void osd_req_flush_partition(struct osd_request *,
+	osd_id partition, enum osd_options_flush_scope_values);
+
+/*
+ * Collection commands
+ */
+void osd_req_create_collection(struct osd_request *,
+	const struct osd_obj_id *);/* NI */
+void osd_req_remove_collection(struct osd_request *,
+	const struct osd_obj_id *);/* NI */
+
+/* list all objects in the collection */
+int osd_req_list_collection_objects(struct osd_request *,
+	const struct osd_obj_id *, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem);
+
+/* V2 only filtered list of objects in the collection */
+void osd_req_query(struct osd_request *, ...);/* NI */
+
+void osd_req_flush_collection(struct osd_request *,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values);
+
+void osd_req_get_member_attrs(struct osd_request *, ...);/* V2-only NI */
+void osd_req_set_member_attrs(struct osd_request *, ...);/* V2-only NI */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *, struct osd_obj_id *);
+void osd_req_remove_object(struct osd_request *, struct osd_obj_id *);
+
+void osd_req_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);
+void osd_req_append(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out);/* NI */
+void osd_req_create_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
+void osd_req_clear(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
+void osd_req_punch(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
+
+void osd_req_flush_object(struct osd_request *,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values,
+	/*V2*/ u64 offset, /*V2*/ u64 len);
+
+void osd_req_read(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_in, u64 offset);
+
+/*
+ * Root/Partition/Collection/Object Attributes commands
+ */
+
+/* get before set */
+void osd_req_get_attributes(struct osd_request *, const struct osd_obj_id *);
+
+/* set before get */
+void osd_req_set_attributes(struct osd_request *, const struct osd_obj_id *);
+
+/*
+ * Attributes appended to most commands
+ */
+
+/* Attributes List mode (or V2 CDB) */
+  /*
+   * TODO: In ver2 if at finalize time only one attr was set and no gets,
+   * then the Attributes CDB mode is used automatically to save IO.
+   */
+
+/* set a list of attributes. */
+int osd_req_add_set_attr_list(struct osd_request *,
+	const struct osd_attr *, unsigned nelem);
+
+/* get a list of attributes */
+int osd_req_add_get_attr_list(struct osd_request *,
+	const struct osd_attr *, unsigned nelem);
+
+/*
+ * Attributes list decoding
+ * Must be called after osd_request.request was executed
+ * It is called in a loop to decode the returned get_attr
+ * (see osd_add_get_attr)
+ */
+int osd_req_decode_get_attr_list(struct osd_request *,
+	struct osd_attr *, int *nelem, void **iterator);
+
+/* Attributes Page mode */
+
+/*
+ * Read an attribute page and optionally set one attribute
+ *
+ * Retrieves the attribute page directly to a user buffer.
+ * @attr_page_data shall stay valid until end of execution.
+ * See osd_attributes.h for common page structures
+ */
+int osd_req_add_get_attr_page(struct osd_request *,
+	u32 page_id, void *attr_page_data, unsigned max_page_len,
+	const struct osd_attr *set_one);
+
+#endif /* __OSD_LIB_H__ */
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
new file mode 100644
index 0000000..77a74a3
--- /dev/null
+++ b/include/scsi/osd_protocol.h
@@ -0,0 +1,497 @@
+/*
+ * osd_protocol.h - OSD T10 standard C definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_PROTOCOL_H__
+#define __OSD_PROTOCOL_H__
+
+#include <linux/types.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+enum {
+	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
+	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
+	OSDv1_CAP_LEN = 80,
+	/* Latest supported version */
+	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
+	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
+	OSD_CAP_LEN = OSDv1_CAP_LEN,
+
+	OSD_SYSTEMID_LEN = 20,
+	OSD_CRYPTO_KEYID_SIZE = 20,
+	OSD_CRYPTO_SEED_SIZE = 4,
+	OSD_CRYPTO_NONCE_SIZE = 12,
+	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
+
+	OSD_PARTITION_FIRST_ID = 0x10000,
+	OSD_OBJECT_FIRST_ID = 0x10000,
+};
+
+/* (osd-r10 5.2.4)
+ * osd2r03: 5.2.3 Caching control bits
+ */
+enum osd_options_byte {
+	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
+	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
+};
+
+/*
+ * osd2r03: 5.2.5 Isolation.
+ * First 3 bits, V2-only.
+ * Also for attr 110h "default isolation method" at Root Information page
+ */
+enum osd_options_byte_isolation {
+	OSD_ISOLATION_DEFAULT = 0,
+	OSD_ISOLATION_NONE = 1,
+	OSD_ISOLATION_STRICT = 2,
+	OSD_ISOLATION_RANGE = 4,
+	OSD_ISOLATION_FUNCTIONAL = 5,
+	OSD_ISOLATION_VENDOR = 7,
+};
+
+/* (osd-r10: 6.7)
+ * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
+ */
+enum osd_options_flush_scope_values {
+	OSD_CDB_FLUSH_ALL = 0,
+	OSD_CDB_FLUSH_ATTR_ONLY = 1,
+
+	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
+	/* V2-only */
+	OSD_CDB_FLUSH_ALL_RANGE = 2,
+};
+
+/* osd2r03: 5.2.10 Timestamps control */
+enum {
+	OSD_CDB_NORMAL_TIMESTAMPS = 0,
+	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
+};
+
+/* (osd-r10: 5.2.2.1)
+ * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
+ *	2 bits at second nibble of command_specific_options byte
+ */
+enum osd_attributes_mode {
+	/* V2-only */
+	OSD_CDB_SET_ONE_ATTR = 0x10,
+
+	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
+	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
+
+	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
+};
+
+/* (osd-r10: 4.12.5)
+ * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
+ *	byte offset = mantissa * (2^(exponent+8))
+ *	struct {
+ *		unsigned mantissa: 28;
+ *		int exponent: 04;
+ *	}
+ */
+typedef __be32 __bitwise osd_cdb_offset;
+
+enum {
+	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
+	OSD_OFFSET_MAX_BITS = 28,
+
+	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MAX_SHIFT = 16,
+};
+
+/* Return the smallest allowed encoded offset that contains @offset.
+ *
+ * The actual encoded offset returned is @offset + *padding.
+ * (up to max_shift, non-inclusive)
+ */
+osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
+	int min_shift, int max_shift);
+
+/* Minimum alignment is 256 bytes
+ * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
+ * which is 8 to 23 but IBM code restricts it to 16, so be it.
+ */
+static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
+/* osd2r03: 5.2.1 Overview */
+struct osd_cdb_head {
+	struct scsi_varlen_cdb_hdr varlen_cdb;
+/*10*/	u8		options;
+	u8		command_specific_options;
+	u8		timestamp_control;
+/*13*/	u8		reserved1[3];
+/*16*/	__be64		partition;
+/*24*/	__be64		object;
+/*32*/	union { /* V1 vs V2 alignment differences */
+		struct __osdv1_cdb_addr_len {
+/*32*/			__be32 		list_identifier;/* Rarely used */
+/*36*/			__be64		length;
+/*44*/			__be64		start_address;
+		} __packed v1;
+	};
+/*52*/	union { /* selected attributes mode Page/List/Single */
+		struct osd_attributes_page_mode {
+/*52*/			__be32		get_attr_page;
+/*56*/			__be32		get_attr_alloc_length;
+/*60*/			osd_cdb_offset	get_attr_offset;
+
+/*64*/			__be32		set_attr_page;
+/*68*/			__be32		set_attr_id;
+/*72*/			__be32		set_attr_length;
+/*76*/			osd_cdb_offset	set_attr_offset;
+		} __packed attrs_page;
+
+		struct osd_attributes_list_mode {
+/*52*/			__be32		get_attr_desc_bytes;
+/*56*/			osd_cdb_offset	get_attr_desc_offset;
+
+/*60*/			__be32		get_attr_alloc_length;
+/*64*/			osd_cdb_offset	get_attr_offset;
+
+/*68*/			__be32		set_attr_bytes;
+/*72*/			osd_cdb_offset	set_attr_offset;
+			__be32 not_used;
+		} __packed attrs_list;
+
+		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
+		struct osd_attributes_cdb_mode {
+/*52*/			__be32		set_attr_page;
+/*56*/			__be32		set_attr_id;
+/*60*/			__be16		set_attr_len;
+/*62*/			u8		set_attr_val[80-62];
+		} __packed attrs_cdb;
+/*52*/		u8 get_set_attributes_parameters[80-52];
+	};
+} __packed;
+/*80*/
+
+/*160 v1*/
+struct osd_security_parameters {
+/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*192*/osd_cdb_offset	data_in_integrity_check_offset;
+/*196*/osd_cdb_offset	data_out_integrity_check_offset;
+} __packed;
+/*200 v1*/
+
+struct osdv1_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSDv1_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
+struct osd_cdb {
+	union {
+		struct osdv1_cdb v1;
+		u8 buff[OSD_TOTAL_CDB_LEN];
+	};
+} __packed;
+
+static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
+{
+	return (struct osd_cdb_head *)ocdb->buff;
+}
+
+/* define both version actions
+ * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
+ */
+#define OSD_ACT___(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
+
+/* V2 only actions */
+#define OSD_ACT_V2(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
+
+#define OSD_ACT_V1_V2(Name, Num1, Num2) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
+
+enum osd_service_actions {
+	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
+	OSD_ACT___(FORMAT_OSD,			0x01)
+	OSD_ACT___(CREATE,			0x02)
+	OSD_ACT___(LIST,			0x03)
+	OSD_ACT_V2(PUNCH,			0x04)
+	OSD_ACT___(READ,			0x05)
+	OSD_ACT___(WRITE,			0x06)
+	OSD_ACT___(APPEND,			0x07)
+	OSD_ACT___(FLUSH,			0x08)
+	OSD_ACT_V2(CLEAR,			0x09)
+	OSD_ACT___(REMOVE,			0x0A)
+	OSD_ACT___(CREATE_PARTITION,		0x0B)
+	OSD_ACT___(REMOVE_PARTITION,		0x0C)
+	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
+	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
+	OSD_ACT___(CREATE_AND_WRITE,		0x12)
+	OSD_ACT___(CREATE_COLLECTION,		0x15)
+	OSD_ACT___(REMOVE_COLLECTION,		0x16)
+	OSD_ACT___(LIST_COLLECTION,		0x17)
+	OSD_ACT___(SET_KEY,			0x18)
+	OSD_ACT___(SET_MASTER_KEY,		0x19)
+	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
+	OSD_ACT___(FLUSH_PARTITION,		0x1B)
+	OSD_ACT___(FLUSH_OSD,			0x1C)
+
+	OSD_ACT_V2(QUERY,			0x20)
+	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
+	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
+	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
+	OSD_ACT_V2(READ_MAP,			0x31)
+
+	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
+	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
+	/* 0x8F80 to 0x8FFF are Vendor specific */
+};
+
+/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
+struct osd_attributes_list_attrid {
+	__be32 page;
+	__be32 attr_id;
+} __packed;
+
+/*
+ * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
+ *                  for setting attributes
+ */
+struct osd_attributes_list_element {
+	__be32 page;
+	__be32 attr_id;
+	__be16 attr_bytes;
+	u8 attr_val[0];
+} __packed;
+
+enum {
+	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+};
+
+enum {
+	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
+	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
+};
+
+static inline unsigned osdv1_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
+}
+
+/*
+ * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
+ */
+enum osd_attr_list_types {
+	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
+	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
+	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
+	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
+};
+
+/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
+struct osd_attributes_list_multi_header {
+	__be64 object_id;
+	u8 object_type; /* object_type enum below */
+	u8 reserved[5];
+	__be16 list_bytes;
+	/* followed by struct osd_attributes_list_element's */
+};
+
+struct osdv1_attributes_list_header {
+	u8 type;	/* low 4-bit only */
+	u8 pad;
+	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
+{
+	return be16_to_cpu(h->list_bytes);
+}
+
+/* (osd-r10 6.13)
+ * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
+ *	for root_lstchg below
+ */
+enum {
+	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
+	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
+};
+
+/*
+ * osd2r03: 6.15.2 LIST command parameter data
+ * (Also for LIST COLLECTION)
+ */
+struct osd_obj_id_list {
+	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
+	__be64 continuation_id;
+	__be32 list_identifier;
+	u8 pad[3];
+	u8 root_lstchg;
+	__be64 object_ids[0];
+} __packed;
+
+static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
+	bool *is_changed)
+{
+	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
+	return 0 != list->continuation_id;
+}
+
+/*
+ * osd2r03: 4.12.4.5 The ALLDATA security method
+ */
+struct osd_data_out_integrity_info {
+	__be64 data_bytes;
+	__be64 set_attributes_bytes;
+	__be64 get_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_data_in_integrity_info {
+	__be64 data_bytes;
+	__be64 retrieved_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_timestamp {
+	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
+} __packed;
+/* FIXME: define helper functions to convert to/from osd time format */
+
+/*
+ * Capability & Security definitions
+ * osd2r03: 4.11.2.2 Capability format
+ * osd2r03: 5.2.8 Security parameters
+ */
+
+struct osd_key_identifier {
+	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+} __packed;
+
+/* for osd_capability.format */
+enum {
+	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
+	OSD_SEC_CAP_FORMAT_VER1 = 1,
+	OSD_SEC_CAP_FORMAT_VER2 = 2,
+};
+
+/* security_method */
+enum {
+	OSD_SEC_NOSEC = 0,
+	OSD_SEC_CAPKEY = 1,
+	OSD_SEC_CMDRSP = 2,
+	OSD_SEC_ALLDATA = 3,
+};
+
+enum object_type {
+	OSD_SEC_OBJ_ROOT = 0x1,
+	OSD_SEC_OBJ_PARTITION = 0x2,
+	OSD_SEC_OBJ_COLLECTION = 0x40,
+	OSD_SEC_OBJ_USER = 0x80,
+};
+
+enum osd_capability_bit_masks {
+	OSD_SEC_CAP_APPEND	= (1 << 0),
+	OSD_SEC_CAP_OBJ_MGMT	= (1 << 1),
+	OSD_SEC_CAP_REMOVE	= (1 << 2),
+	OSD_SEC_CAP_CREATE	= (1 << 3),
+	OSD_SEC_CAP_SET_ATTR	= (1 << 4),
+	OSD_SEC_CAP_GET_ATTR	= (1 << 5),
+	OSD_SEC_CAP_WRITE	= (1 << 6),
+	OSD_SEC_CAP_READ	= (1 << 7),
+
+	OSD_SEC_CAP_NONE1	= (1 << 8),
+	OSD_SEC_CAP_NONE2	= (1 << 9),
+	OSD_SEC_CAP_NONE3	= (1 << 10),
+	OSD_SEC_CAP_QUERY	= (1 << 11), /*v2 only*/
+	OSD_SEC_CAP_M_OBJECT	= (1 << 12), /*v2 only*/
+	OSD_SEC_CAP_POL_SEC	= (1 << 13),
+	OSD_SEC_CAP_GLOBAL	= (1 << 14),
+	OSD_SEC_CAP_DEV_MGMT	= (1 << 15),
+};
+
+/* for object_descriptor_type (hi nibble used) */
+enum {
+	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
+	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
+	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
+	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
+};
+
+/* (osd-r10:4.9.2.2)
+ * osd2r03:4.11.2.2 Capability format
+ */
+struct osd_capability_head {
+	u8 format; /* low nibble */
+	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
+	u8 security_method;
+	u8 reserved1;
+/*04*/	struct osd_timestamp expiration_time;
+/*10*/	u8 audit[30-10];
+/*30*/	u8 discriminator[42-30];
+/*42*/	struct osd_timestamp object_created_time;
+/*48*/	u8 object_type;
+	u8 permissions_bit_mask[54-49];
+/*54*/	u8 reserved2;
+/*55*/	u8 object_descriptor_type; /* high nibble */
+} __packed;
+
+/*56 v1*/
+struct osdv1_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 policy_access_tag;
+/*60*/			__be64 allowed_partition_id;
+/*68*/			__be64 allowed_object_id;
+/*76*/			__be32 reserved;
+		} __packed obj_desc;
+
+		u8 object_descriptor[80-56];/*24*/
+	};
+} __packed;
+/*80 v1*/
+
+struct osd_capability {
+	struct osd_capability_head h;
+	struct osdv1_cap_object_descriptor od;
+} __packed;
+
+/**
+ * osd_sec_set_caps - set cap-bits into the capabilities header
+ *
+ * @cap:	The osd_capability_head to set cap bits to.
+ * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
+ *
+ * permissions_bit_mask is unaligned use below to set into caps
+ * in a version independent way
+ */
+static inline void osd_sec_set_caps(struct osd_capability_head *cap,
+	u16 bit_mask)
+{
+	/*
+	 *Note: The bits above are defined LE order this is because this way
+	 *      they can grow in the future to more then 16, and still retain
+	 *      there constant values.
+	 */
+	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
+}
+
+#endif /* ndef __OSD_PROTOCOL_H__ */
diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h
new file mode 100644
index 0000000..4c09fee
--- /dev/null
+++ b/include/scsi/osd_sec.h
@@ -0,0 +1,45 @@
+/*
+ * osd_sec.h - OSD security manager API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_SEC_H__
+#define __OSD_SEC_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/*
+ * Contains types and constants of osd capabilities and security
+ * encoding/decoding.
+ * API is trying to keep security abstract so initiator of an object
+ * based pNFS client knows as little as possible about security and
+ * capabilities. It is the Server's osd-initiator place to know more.
+ * Also can be used by osd-target.
+ */
+void osd_sec_encode_caps(void *caps, ...);/* NI */
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1);
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_params);
+
+/* Conditionally sign the CDB according to security setting in ocdb
+ * with cap_key */
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key);
+
+/* Unconditionally sign the BIO data with cap_key.
+ * Check for osd_is_sec_alldata() was done prior to calling this. */
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key);
+
+/* Version independent copy of caps into the cdb */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps);
+
+#endif /* ndef __OSD_SEC_H__ */
diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h
new file mode 100644
index 0000000..ea5372d
--- /dev/null
+++ b/include/scsi/osd_types.h
@@ -0,0 +1,40 @@
+/*
+ * osd_types.h - Types and constants which are not part of the protocol.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Contains types and constants that are implementation specific and are
+ * used by more than one part of the osd library.
+ *     (Eg initiator/target/security_manager/...)
+ */
+#ifndef __OSD_TYPES_H__
+#define __OSD_TYPES_H__
+
+struct osd_systemid {
+	u8 data[OSD_SYSTEMID_LEN];
+};
+
+typedef u64 __bitwise osd_id;
+
+struct osd_obj_id {
+	osd_id partition;
+	osd_id id;
+};
+
+static const struct __weak osd_obj_id osd_root_object = {0, 0};
+
+struct osd_attr {
+	u32 page;
+	u32 attr_id;
+	u16 len;		/* byte count of operand */
+	void *val_ptr;		/* in network order */
+};
+
+#endif /* ndef __OSD_TYPES_H__ */
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 03/18] libosd: OSDv1 Headers
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Headers only patch.

osd_protocol.h
	Contains a C-fied definition of the T10 OSD standard
osd_types.h
	Contains CPU order common used types
osd_initiator.h
	API definition of the osd_initiator library
osd_sec.h
	Contains High level API for the security manager.

[Note that checkpatch spews errors on things that are valid in this context
and will not be fixed]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
 include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_sec.h       |   45 ++++
 include/scsi/osd_types.h     |   40 ++++
 4 files changed, 914 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_initiator.h
 create mode 100644 include/scsi/osd_protocol.h
 create mode 100644 include/scsi/osd_sec.h
 create mode 100644 include/scsi/osd_types.h

diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
new file mode 100644
index 0000000..24a70b7
--- /dev/null
+++ b/include/scsi/osd_initiator.h
@@ -0,0 +1,332 @@
+/*
+ * osd_initiator.h - OSD initiator API definition
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_INITIATOR_H__
+#define __OSD_INITIATOR_H__
+
+#include <linux/blkdev.h>
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/* Note: "NI" in comments below means "Not Implemented yet" */
+
+/*
+ * Object-based Storage Device.
+ * This object represents an OSD device.
+ * It is not a full linux device in any way. It is only
+ * a place to hang resources associated with a Linux
+ * request Q and some default properties.
+ */
+struct osd_dev {
+	struct scsi_device *scsi_dev;
+	unsigned def_timeout;
+};
+
+void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
+void osd_dev_fini(struct osd_dev *);
+
+struct osd_request;
+typedef void (osd_req_done_fn)(struct osd_request *, void *);
+
+struct osd_request {
+	struct osd_cdb cdb;
+	struct osd_data_out_integrity_info out_data_integ;
+	struct osd_data_in_integrity_info in_data_integ;
+
+	struct osd_dev *osd_dev;
+	struct request *request;
+
+	struct _osd_req_data_segment {
+		void *buff;
+		unsigned alloc_size; /* 0 here means not allocated by us */
+		unsigned total_bytes;
+	} set_attr, enc_get_attr, get_attr;
+
+	struct _osd_io_info {
+		struct bio *bio;
+		u64 total_bytes;
+		struct request *req;
+		struct _osd_req_data_segment *last_seg;
+		u8 *pad_buff;
+	} out, in;
+
+	gfp_t alloc_flags;
+	unsigned timeout;
+	unsigned retries;
+	u8 sense[OSD_MAX_SENSE_LEN];
+	enum osd_attributes_mode attributes_mode;
+
+	osd_req_done_fn *async_done;
+	void *async_private;
+	int async_error;
+};
+
+/**
+ * How to use the osd library:
+ *
+ * osd_start_request
+ *	Allocates a request.
+ *
+ * osd_req_*
+ *	Call one of, to encode the desired operation.
+ *
+ * osd_add_{get,set}_attr
+ *	Optionally add attributes to the CDB, list or page mode.
+ *
+ * osd_finalize_request
+ *	Computes final data out/in offsets and signs the request,
+ *	making it ready for execution.
+ *
+ * osd_execute_request
+ *	May be called to execute it through the block layer. Other wise submit
+ *	the associated block request in some other way.
+ *
+ * After execution:
+ * osd_req_decode_sense
+ *	Decodes sense information to verify execution results.
+ *
+ * osd_req_decode_get_attr
+ *	Retrieve osd_add_get_attr_list() values if used.
+ *
+ * osd_end_request
+ *	Must be called to deallocate the request.
+ */
+
+/**
+ * osd_start_request - Allocate and initialize an osd_request
+ *
+ * @osd_dev:    OSD device that holds the scsi-device and default values
+ *              that the request is associated with.
+ * @gfp:        The allocation flags to use for request allocation, and all
+ *              subsequent allocations. This will be stored at
+ *              osd_request->alloc_flags, can be changed by user later
+ *
+ * Allocate osd_request and initialize all members to the
+ * default/initial state.
+ */
+struct osd_request *osd_start_request(struct osd_dev *, gfp_t gfp);
+
+enum osd_req_options {
+	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
+	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
+
+	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
+};
+
+/**
+ * osd_finalize_request - Sign request and prepare request for execution
+ *
+ * @or:		osd_request to prepare
+ * @options:	combination of osd_req_options bit flags or 0.
+ * @cap	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
+ *              The security manager as capabilities for this cdb.
+ * @cap_key	The cryptographic key used to sign the cdb/data. Can be null
+ *              if NOSEC is used.
+ *
+ * The actual request and bios are only allocated here, so are the get_attr
+ * buffers that will receive the returned attributes. Copy's @cap to cdb.
+ * Sign the cdb/data with @cap_key.
+ */
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key);
+
+/**
+ * osd_execute_request - Execute the request synchronously through
+ *                       the block-layer
+ * @or:		osd_request to Executed
+ *
+ * Calls blk_execute_rq to q the command and waits for completion.
+ */
+int osd_execute_request(struct osd_request *or);
+
+/**
+ * osd_execute_request_async - submits the request for execution through
+ *                             the block-layer without waitting.
+ * @or:                      - osd_request to Executed
+ * @done: (Optional)         - Called at end of execution
+ * @private:                 - Will be passes to @done function
+ *
+ * Calls blk_execute_rq_nowait to q the command. When execution is done
+ * Optionally calles @done with @private as parameter. or->async_error has the
+ * Return code
+ */
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private);
+
+/**
+ * osd_end_request - return osd_request to free store
+ *
+ * @or:		osd_request to free
+ *
+ * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
+ */
+void osd_end_request(struct osd_request *or);
+
+/*
+ * CDB Encoding
+ *
+ * Note: call only one of the following methods.
+ */
+
+/*
+ * Device commands
+ */
+void osd_req_set_master_seed_xchg(struct osd_request *, ...);/* NI */
+void osd_req_set_master_key(struct osd_request *, ...);/* NI */
+
+void osd_req_format(struct osd_request *, u64 tot_capacity);
+
+/* list all partitions
+ * @list header must be initialized to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_dev_partitions(struct osd_request *,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
+
+void osd_req_flush_obsd(struct osd_request *,
+	enum osd_options_flush_scope_values);
+
+void osd_req_perform_scsi_command(struct osd_request *,
+	const u8 *cdb, ...);/* NI */
+void osd_req_task_management(struct osd_request *, ...);/* NI */
+
+/*
+ * Partition commands
+ */
+void osd_req_create_partition(struct osd_request *, osd_id partition);
+void osd_req_remove_partition(struct osd_request *, osd_id partition);
+
+void osd_req_set_partition_key(struct osd_request *,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
+
+/* list all collections in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_collections(struct osd_request *,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+/* list all objects in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_objects(struct osd_request *,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+void osd_req_flush_partition(struct osd_request *,
+	osd_id partition, enum osd_options_flush_scope_values);
+
+/*
+ * Collection commands
+ */
+void osd_req_create_collection(struct osd_request *,
+	const struct osd_obj_id *);/* NI */
+void osd_req_remove_collection(struct osd_request *,
+	const struct osd_obj_id *);/* NI */
+
+/* list all objects in the collection */
+int osd_req_list_collection_objects(struct osd_request *,
+	const struct osd_obj_id *, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem);
+
+/* V2 only filtered list of objects in the collection */
+void osd_req_query(struct osd_request *, ...);/* NI */
+
+void osd_req_flush_collection(struct osd_request *,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values);
+
+void osd_req_get_member_attrs(struct osd_request *, ...);/* V2-only NI */
+void osd_req_set_member_attrs(struct osd_request *, ...);/* V2-only NI */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *, struct osd_obj_id *);
+void osd_req_remove_object(struct osd_request *, struct osd_obj_id *);
+
+void osd_req_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);
+void osd_req_append(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out);/* NI */
+void osd_req_create_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
+void osd_req_clear(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
+void osd_req_punch(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
+
+void osd_req_flush_object(struct osd_request *,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values,
+	/*V2*/ u64 offset, /*V2*/ u64 len);
+
+void osd_req_read(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_in, u64 offset);
+
+/*
+ * Root/Partition/Collection/Object Attributes commands
+ */
+
+/* get before set */
+void osd_req_get_attributes(struct osd_request *, const struct osd_obj_id *);
+
+/* set before get */
+void osd_req_set_attributes(struct osd_request *, const struct osd_obj_id *);
+
+/*
+ * Attributes appended to most commands
+ */
+
+/* Attributes List mode (or V2 CDB) */
+  /*
+   * TODO: In ver2 if at finalize time only one attr was set and no gets,
+   * then the Attributes CDB mode is used automatically to save IO.
+   */
+
+/* set a list of attributes. */
+int osd_req_add_set_attr_list(struct osd_request *,
+	const struct osd_attr *, unsigned nelem);
+
+/* get a list of attributes */
+int osd_req_add_get_attr_list(struct osd_request *,
+	const struct osd_attr *, unsigned nelem);
+
+/*
+ * Attributes list decoding
+ * Must be called after osd_request.request was executed
+ * It is called in a loop to decode the returned get_attr
+ * (see osd_add_get_attr)
+ */
+int osd_req_decode_get_attr_list(struct osd_request *,
+	struct osd_attr *, int *nelem, void **iterator);
+
+/* Attributes Page mode */
+
+/*
+ * Read an attribute page and optionally set one attribute
+ *
+ * Retrieves the attribute page directly to a user buffer.
+ * @attr_page_data shall stay valid until end of execution.
+ * See osd_attributes.h for common page structures
+ */
+int osd_req_add_get_attr_page(struct osd_request *,
+	u32 page_id, void *attr_page_data, unsigned max_page_len,
+	const struct osd_attr *set_one);
+
+#endif /* __OSD_LIB_H__ */
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
new file mode 100644
index 0000000..77a74a3
--- /dev/null
+++ b/include/scsi/osd_protocol.h
@@ -0,0 +1,497 @@
+/*
+ * osd_protocol.h - OSD T10 standard C definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_PROTOCOL_H__
+#define __OSD_PROTOCOL_H__
+
+#include <linux/types.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+enum {
+	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
+	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
+	OSDv1_CAP_LEN = 80,
+	/* Latest supported version */
+	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
+	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
+	OSD_CAP_LEN = OSDv1_CAP_LEN,
+
+	OSD_SYSTEMID_LEN = 20,
+	OSD_CRYPTO_KEYID_SIZE = 20,
+	OSD_CRYPTO_SEED_SIZE = 4,
+	OSD_CRYPTO_NONCE_SIZE = 12,
+	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
+
+	OSD_PARTITION_FIRST_ID = 0x10000,
+	OSD_OBJECT_FIRST_ID = 0x10000,
+};
+
+/* (osd-r10 5.2.4)
+ * osd2r03: 5.2.3 Caching control bits
+ */
+enum osd_options_byte {
+	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
+	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
+};
+
+/*
+ * osd2r03: 5.2.5 Isolation.
+ * First 3 bits, V2-only.
+ * Also for attr 110h "default isolation method" at Root Information page
+ */
+enum osd_options_byte_isolation {
+	OSD_ISOLATION_DEFAULT = 0,
+	OSD_ISOLATION_NONE = 1,
+	OSD_ISOLATION_STRICT = 2,
+	OSD_ISOLATION_RANGE = 4,
+	OSD_ISOLATION_FUNCTIONAL = 5,
+	OSD_ISOLATION_VENDOR = 7,
+};
+
+/* (osd-r10: 6.7)
+ * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
+ */
+enum osd_options_flush_scope_values {
+	OSD_CDB_FLUSH_ALL = 0,
+	OSD_CDB_FLUSH_ATTR_ONLY = 1,
+
+	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
+	/* V2-only */
+	OSD_CDB_FLUSH_ALL_RANGE = 2,
+};
+
+/* osd2r03: 5.2.10 Timestamps control */
+enum {
+	OSD_CDB_NORMAL_TIMESTAMPS = 0,
+	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
+};
+
+/* (osd-r10: 5.2.2.1)
+ * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
+ *	2 bits at second nibble of command_specific_options byte
+ */
+enum osd_attributes_mode {
+	/* V2-only */
+	OSD_CDB_SET_ONE_ATTR = 0x10,
+
+	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
+	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
+
+	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
+};
+
+/* (osd-r10: 4.12.5)
+ * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
+ *	byte offset = mantissa * (2^(exponent+8))
+ *	struct {
+ *		unsigned mantissa: 28;
+ *		int exponent: 04;
+ *	}
+ */
+typedef __be32 __bitwise osd_cdb_offset;
+
+enum {
+	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
+	OSD_OFFSET_MAX_BITS = 28,
+
+	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MAX_SHIFT = 16,
+};
+
+/* Return the smallest allowed encoded offset that contains @offset.
+ *
+ * The actual encoded offset returned is @offset + *padding.
+ * (up to max_shift, non-inclusive)
+ */
+osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
+	int min_shift, int max_shift);
+
+/* Minimum alignment is 256 bytes
+ * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
+ * which is 8 to 23 but IBM code restricts it to 16, so be it.
+ */
+static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
+/* osd2r03: 5.2.1 Overview */
+struct osd_cdb_head {
+	struct scsi_varlen_cdb_hdr varlen_cdb;
+/*10*/	u8		options;
+	u8		command_specific_options;
+	u8		timestamp_control;
+/*13*/	u8		reserved1[3];
+/*16*/	__be64		partition;
+/*24*/	__be64		object;
+/*32*/	union { /* V1 vs V2 alignment differences */
+		struct __osdv1_cdb_addr_len {
+/*32*/			__be32 		list_identifier;/* Rarely used */
+/*36*/			__be64		length;
+/*44*/			__be64		start_address;
+		} __packed v1;
+	};
+/*52*/	union { /* selected attributes mode Page/List/Single */
+		struct osd_attributes_page_mode {
+/*52*/			__be32		get_attr_page;
+/*56*/			__be32		get_attr_alloc_length;
+/*60*/			osd_cdb_offset	get_attr_offset;
+
+/*64*/			__be32		set_attr_page;
+/*68*/			__be32		set_attr_id;
+/*72*/			__be32		set_attr_length;
+/*76*/			osd_cdb_offset	set_attr_offset;
+		} __packed attrs_page;
+
+		struct osd_attributes_list_mode {
+/*52*/			__be32		get_attr_desc_bytes;
+/*56*/			osd_cdb_offset	get_attr_desc_offset;
+
+/*60*/			__be32		get_attr_alloc_length;
+/*64*/			osd_cdb_offset	get_attr_offset;
+
+/*68*/			__be32		set_attr_bytes;
+/*72*/			osd_cdb_offset	set_attr_offset;
+			__be32 not_used;
+		} __packed attrs_list;
+
+		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
+		struct osd_attributes_cdb_mode {
+/*52*/			__be32		set_attr_page;
+/*56*/			__be32		set_attr_id;
+/*60*/			__be16		set_attr_len;
+/*62*/			u8		set_attr_val[80-62];
+		} __packed attrs_cdb;
+/*52*/		u8 get_set_attributes_parameters[80-52];
+	};
+} __packed;
+/*80*/
+
+/*160 v1*/
+struct osd_security_parameters {
+/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*192*/osd_cdb_offset	data_in_integrity_check_offset;
+/*196*/osd_cdb_offset	data_out_integrity_check_offset;
+} __packed;
+/*200 v1*/
+
+struct osdv1_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSDv1_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
+struct osd_cdb {
+	union {
+		struct osdv1_cdb v1;
+		u8 buff[OSD_TOTAL_CDB_LEN];
+	};
+} __packed;
+
+static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
+{
+	return (struct osd_cdb_head *)ocdb->buff;
+}
+
+/* define both version actions
+ * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
+ */
+#define OSD_ACT___(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
+
+/* V2 only actions */
+#define OSD_ACT_V2(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
+
+#define OSD_ACT_V1_V2(Name, Num1, Num2) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
+
+enum osd_service_actions {
+	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
+	OSD_ACT___(FORMAT_OSD,			0x01)
+	OSD_ACT___(CREATE,			0x02)
+	OSD_ACT___(LIST,			0x03)
+	OSD_ACT_V2(PUNCH,			0x04)
+	OSD_ACT___(READ,			0x05)
+	OSD_ACT___(WRITE,			0x06)
+	OSD_ACT___(APPEND,			0x07)
+	OSD_ACT___(FLUSH,			0x08)
+	OSD_ACT_V2(CLEAR,			0x09)
+	OSD_ACT___(REMOVE,			0x0A)
+	OSD_ACT___(CREATE_PARTITION,		0x0B)
+	OSD_ACT___(REMOVE_PARTITION,		0x0C)
+	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
+	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
+	OSD_ACT___(CREATE_AND_WRITE,		0x12)
+	OSD_ACT___(CREATE_COLLECTION,		0x15)
+	OSD_ACT___(REMOVE_COLLECTION,		0x16)
+	OSD_ACT___(LIST_COLLECTION,		0x17)
+	OSD_ACT___(SET_KEY,			0x18)
+	OSD_ACT___(SET_MASTER_KEY,		0x19)
+	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
+	OSD_ACT___(FLUSH_PARTITION,		0x1B)
+	OSD_ACT___(FLUSH_OSD,			0x1C)
+
+	OSD_ACT_V2(QUERY,			0x20)
+	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
+	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
+	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
+	OSD_ACT_V2(READ_MAP,			0x31)
+
+	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
+	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
+	/* 0x8F80 to 0x8FFF are Vendor specific */
+};
+
+/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
+struct osd_attributes_list_attrid {
+	__be32 page;
+	__be32 attr_id;
+} __packed;
+
+/*
+ * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
+ *                  for setting attributes
+ */
+struct osd_attributes_list_element {
+	__be32 page;
+	__be32 attr_id;
+	__be16 attr_bytes;
+	u8 attr_val[0];
+} __packed;
+
+enum {
+	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+};
+
+enum {
+	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
+	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
+};
+
+static inline unsigned osdv1_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
+}
+
+/*
+ * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
+ */
+enum osd_attr_list_types {
+	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
+	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
+	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
+	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
+};
+
+/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
+struct osd_attributes_list_multi_header {
+	__be64 object_id;
+	u8 object_type; /* object_type enum below */
+	u8 reserved[5];
+	__be16 list_bytes;
+	/* followed by struct osd_attributes_list_element's */
+};
+
+struct osdv1_attributes_list_header {
+	u8 type;	/* low 4-bit only */
+	u8 pad;
+	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
+{
+	return be16_to_cpu(h->list_bytes);
+}
+
+/* (osd-r10 6.13)
+ * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
+ *	for root_lstchg below
+ */
+enum {
+	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
+	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
+};
+
+/*
+ * osd2r03: 6.15.2 LIST command parameter data
+ * (Also for LIST COLLECTION)
+ */
+struct osd_obj_id_list {
+	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
+	__be64 continuation_id;
+	__be32 list_identifier;
+	u8 pad[3];
+	u8 root_lstchg;
+	__be64 object_ids[0];
+} __packed;
+
+static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
+	bool *is_changed)
+{
+	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
+	return 0 != list->continuation_id;
+}
+
+/*
+ * osd2r03: 4.12.4.5 The ALLDATA security method
+ */
+struct osd_data_out_integrity_info {
+	__be64 data_bytes;
+	__be64 set_attributes_bytes;
+	__be64 get_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_data_in_integrity_info {
+	__be64 data_bytes;
+	__be64 retrieved_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_timestamp {
+	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
+} __packed;
+/* FIXME: define helper functions to convert to/from osd time format */
+
+/*
+ * Capability & Security definitions
+ * osd2r03: 4.11.2.2 Capability format
+ * osd2r03: 5.2.8 Security parameters
+ */
+
+struct osd_key_identifier {
+	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+} __packed;
+
+/* for osd_capability.format */
+enum {
+	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
+	OSD_SEC_CAP_FORMAT_VER1 = 1,
+	OSD_SEC_CAP_FORMAT_VER2 = 2,
+};
+
+/* security_method */
+enum {
+	OSD_SEC_NOSEC = 0,
+	OSD_SEC_CAPKEY = 1,
+	OSD_SEC_CMDRSP = 2,
+	OSD_SEC_ALLDATA = 3,
+};
+
+enum object_type {
+	OSD_SEC_OBJ_ROOT = 0x1,
+	OSD_SEC_OBJ_PARTITION = 0x2,
+	OSD_SEC_OBJ_COLLECTION = 0x40,
+	OSD_SEC_OBJ_USER = 0x80,
+};
+
+enum osd_capability_bit_masks {
+	OSD_SEC_CAP_APPEND	= (1 << 0),
+	OSD_SEC_CAP_OBJ_MGMT	= (1 << 1),
+	OSD_SEC_CAP_REMOVE	= (1 << 2),
+	OSD_SEC_CAP_CREATE	= (1 << 3),
+	OSD_SEC_CAP_SET_ATTR	= (1 << 4),
+	OSD_SEC_CAP_GET_ATTR	= (1 << 5),
+	OSD_SEC_CAP_WRITE	= (1 << 6),
+	OSD_SEC_CAP_READ	= (1 << 7),
+
+	OSD_SEC_CAP_NONE1	= (1 << 8),
+	OSD_SEC_CAP_NONE2	= (1 << 9),
+	OSD_SEC_CAP_NONE3	= (1 << 10),
+	OSD_SEC_CAP_QUERY	= (1 << 11), /*v2 only*/
+	OSD_SEC_CAP_M_OBJECT	= (1 << 12), /*v2 only*/
+	OSD_SEC_CAP_POL_SEC	= (1 << 13),
+	OSD_SEC_CAP_GLOBAL	= (1 << 14),
+	OSD_SEC_CAP_DEV_MGMT	= (1 << 15),
+};
+
+/* for object_descriptor_type (hi nibble used) */
+enum {
+	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
+	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
+	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
+	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
+};
+
+/* (osd-r10:4.9.2.2)
+ * osd2r03:4.11.2.2 Capability format
+ */
+struct osd_capability_head {
+	u8 format; /* low nibble */
+	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
+	u8 security_method;
+	u8 reserved1;
+/*04*/	struct osd_timestamp expiration_time;
+/*10*/	u8 audit[30-10];
+/*30*/	u8 discriminator[42-30];
+/*42*/	struct osd_timestamp object_created_time;
+/*48*/	u8 object_type;
+	u8 permissions_bit_mask[54-49];
+/*54*/	u8 reserved2;
+/*55*/	u8 object_descriptor_type; /* high nibble */
+} __packed;
+
+/*56 v1*/
+struct osdv1_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 policy_access_tag;
+/*60*/			__be64 allowed_partition_id;
+/*68*/			__be64 allowed_object_id;
+/*76*/			__be32 reserved;
+		} __packed obj_desc;
+
+		u8 object_descriptor[80-56];/*24*/
+	};
+} __packed;
+/*80 v1*/
+
+struct osd_capability {
+	struct osd_capability_head h;
+	struct osdv1_cap_object_descriptor od;
+} __packed;
+
+/**
+ * osd_sec_set_caps - set cap-bits into the capabilities header
+ *
+ * @cap:	The osd_capability_head to set cap bits to.
+ * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
+ *
+ * permissions_bit_mask is unaligned use below to set into caps
+ * in a version independent way
+ */
+static inline void osd_sec_set_caps(struct osd_capability_head *cap,
+	u16 bit_mask)
+{
+	/*
+	 *Note: The bits above are defined LE order this is because this way
+	 *      they can grow in the future to more then 16, and still retain
+	 *      there constant values.
+	 */
+	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
+}
+
+#endif /* ndef __OSD_PROTOCOL_H__ */
diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h
new file mode 100644
index 0000000..4c09fee
--- /dev/null
+++ b/include/scsi/osd_sec.h
@@ -0,0 +1,45 @@
+/*
+ * osd_sec.h - OSD security manager API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_SEC_H__
+#define __OSD_SEC_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/*
+ * Contains types and constants of osd capabilities and security
+ * encoding/decoding.
+ * API is trying to keep security abstract so initiator of an object
+ * based pNFS client knows as little as possible about security and
+ * capabilities. It is the Server's osd-initiator place to know more.
+ * Also can be used by osd-target.
+ */
+void osd_sec_encode_caps(void *caps, ...);/* NI */
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1);
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_params);
+
+/* Conditionally sign the CDB according to security setting in ocdb
+ * with cap_key */
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key);
+
+/* Unconditionally sign the BIO data with cap_key.
+ * Check for osd_is_sec_alldata() was done prior to calling this. */
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key);
+
+/* Version independent copy of caps into the cdb */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps);
+
+#endif /* ndef __OSD_SEC_H__ */
diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h
new file mode 100644
index 0000000..ea5372d
--- /dev/null
+++ b/include/scsi/osd_types.h
@@ -0,0 +1,40 @@
+/*
+ * osd_types.h - Types and constants which are not part of the protocol.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Contains types and constants that are implementation specific and are
+ * used by more than one part of the osd library.
+ *     (Eg initiator/target/security_manager/...)
+ */
+#ifndef __OSD_TYPES_H__
+#define __OSD_TYPES_H__
+
+struct osd_systemid {
+	u8 data[OSD_SYSTEMID_LEN];
+};
+
+typedef u64 __bitwise osd_id;
+
+struct osd_obj_id {
+	osd_id partition;
+	osd_id id;
+};
+
+static const struct __weak osd_obj_id osd_root_object = {0, 0};
+
+struct osd_attr {
+	u32 page;
+	u32 attr_id;
+	u16 len;		/* byte count of operand */
+	void *val_ptr;		/* in network order */
+};
+
+#endif /* ndef __OSD_TYPES_H__ */
-- 
1.6.0.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 04/18] libosd: OSDv1 preliminary implementation
  2008-11-04 16:09   ` Boaz Harrosh
                     ` (4 preceding siblings ...)
  (?)
@ 2008-11-04 16:44   ` Boaz Harrosh
  2008-11-04 18:03     ` Sam Ravnborg
                       ` (2 more replies)
  -1 siblings, 3 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Implementation of the most basic OSD functionality and
infrastructure. Mainly Format, Create/Remove Partition,
Create/Remove Object, and read/write.

- Add Makefile and Kbuild to compile libosd.ko
- osd_initiator.c Implementation file for osd_initiator.h
  and osd_sec.h APIs
- osd_debug.h - Some kprintf macro definitions

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild          |   26 +++
 drivers/scsi/osd/Makefile        |   37 +++
 drivers/scsi/osd/osd_debug.h     |   27 +++
 drivers/scsi/osd/osd_initiator.c |  450 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 540 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kbuild
 create mode 100755 drivers/scsi/osd/Makefile
 create mode 100644 drivers/scsi/osd/osd_debug.h
 create mode 100644 drivers/scsi/osd/osd_initiator.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
new file mode 100644
index 0000000..b4678e0
--- /dev/null
+++ b/drivers/scsi/osd/Kbuild
@@ -0,0 +1,26 @@
+#
+# Kbuild for the OSD modules
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+
+ifneq ($(OSD_INC),)
+# we are built out-of-tree Kconfigure everything as on
+
+CONFIG_SCSI_OSD_INITIATOR=m
+EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
+
+EXTRA_CFLAGS += -I$(OSD_INC)
+# EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_DEBUG
+
+endif
+
+libosd-objs := osd_initiator.o
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile
new file mode 100755
index 0000000..d905344
--- /dev/null
+++ b/drivers/scsi/osd/Makefile
@@ -0,0 +1,37 @@
+#
+# Makefile for the OSD modules (out of tree)
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+# This Makefile is used to call the kernel Makefile in case of an out-of-tree
+# build.
+# $KSRC should point to a Kernel source tree otherwise host's default is
+# used. (eg. /lib/modules/`uname -r`/build)
+
+# include path for out-of-tree Headers
+OSD_INC ?= `pwd`/../../../include
+
+# allow users to override these
+# e.g. to compile for a kernel that you aren't currently running
+KSRC ?= /lib/modules/$(shell uname -r)/build
+KBUILD_OUTPUT ?=
+ARCH ?=
+V ?= 0
+
+# this is the basic Kbuild out-of-tree invocation, with the M= option
+KBUILD_BASE = +$(MAKE) -C $(KSRC) M=`pwd` KBUILD_OUTPUT=$(KBUILD_OUTPUT) ARCH=$(ARCH) V=$(V)
+
+all: libosd
+
+libosd: ;
+	$(KBUILD_BASE) OSD_INC=$(OSD_INC) modules
+
+clean:
+	$(KBUILD_BASE) clean
diff --git a/drivers/scsi/osd/osd_debug.h b/drivers/scsi/osd/osd_debug.h
new file mode 100644
index 0000000..0bc65fa
--- /dev/null
+++ b/drivers/scsi/osd/osd_debug.h
@@ -0,0 +1,27 @@
+/*
+ * osd_debug.h - Some kprintf macros
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_DEBUG_H__
+#define __OSD_DEBUG_H__
+
+#define OSD_ERR(fmt, a...) printk(KERN_ERR "osd: " fmt, ##a)
+#define OSD_INFO(fmt, a...) printk(KERN_NOTICE "osd: " fmt, ##a)
+
+#ifdef CONFIG_SCSI_OSD_DEBUG
+#define OSD_DEBUG(fmt, a...) \
+	printk(KERN_NOTICE "osd @%s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define OSD_DEBUG(fmt, a...) do {} while (0)
+#endif
+
+#endif /* ndef __OSD_DEBUG_H__ */
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
new file mode 100644
index 0000000..33450b8
--- /dev/null
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -0,0 +1,450 @@
+/*
+ * osd_initiator - Main body of the osd initiator library.
+ *
+ * Note: The file does not contain the advanced security functionality which
+ * is only needed by the security_manager's initiators.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+#include <scsi/scsi_device.h>
+
+#include "osd_debug.h"
+
+enum { OSD_REQ_RETRIES = 1 };
+
+#ifdef CONFIG_SCSI_OSD_INITIATOR_MODULE
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd initiator library libosd.ko");
+MODULE_LICENSE("GPL");
+#endif
+
+static inline void build_test(void)
+{
+	/* structures were not packed */
+	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
+}
+
+static unsigned _osd_req_cdb_len(struct osd_request *or)
+{
+	return OSDv1_TOTAL_CDB_LEN;
+}
+
+void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
+{
+	memset(osdd, 0, sizeof(*osdd));
+	osdd->scsi_dev = scsi_dev;
+	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+	/* TODO: Allocate pools for osd_request attributes ... */
+}
+EXPORT_SYMBOL(osd_dev_init);
+
+void osd_dev_fini(struct osd_dev *osdd)
+{
+	/* TODO: De-allocate pools */
+
+	osdd->scsi_dev = NULL;
+}
+EXPORT_SYMBOL(osd_dev_fini);
+
+struct osd_request *_osd_request_alloc(gfp_t gfp)
+{
+	struct osd_request *or;
+
+	/* TODO: Use mempool with one saved request */
+	or = kzalloc(sizeof(*or), gfp);
+	return or;
+}
+
+void _osd_request_free(struct osd_request *or)
+{
+	kfree(or);
+}
+
+struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp)
+{
+	struct osd_request *or;
+
+	or = _osd_request_alloc(gfp);
+	if (!or)
+		return NULL;
+
+	or->osd_dev = dev;
+	or->alloc_flags = gfp;
+	or->timeout = dev->def_timeout;
+	or->retries = OSD_REQ_RETRIES;
+
+	return or;
+}
+EXPORT_SYMBOL(osd_start_request);
+
+/*
+ * If osd_finalize_request() was called but the request was not executed through
+ * the block layer, then we must release BIOs.
+ */
+static void _abort_unexecuted_bios(struct request *rq)
+{
+	struct bio *bio;
+
+	while ((bio = rq->bio) != NULL) {
+		rq->bio = bio->bi_next;
+		bio_endio(bio, 0);
+	}
+}
+
+void osd_end_request(struct osd_request *or)
+{
+	struct request *rq = or->request;
+
+	if (rq) {
+		if (rq->next_rq) {
+			_abort_unexecuted_bios(rq->next_rq);
+			blk_put_request(rq->next_rq);
+		}
+
+		_abort_unexecuted_bios(rq);
+		blk_put_request(rq);
+	}
+	_osd_request_free(or);
+}
+EXPORT_SYMBOL(osd_end_request);
+
+int osd_execute_request(struct osd_request *or)
+{
+	return blk_execute_rq(or->request->q, NULL, or->request, 0);
+}
+EXPORT_SYMBOL(osd_execute_request);
+
+static void osd_request_async_done(struct request *req, int error)
+{
+	struct osd_request *or = req->end_io_data;
+
+	or->async_error = error;
+
+	if (error)
+		OSD_DEBUG("osd_request_async_done error recieved %d\n", error);
+
+	if (or->async_done)
+		or->async_done(or, or->async_private);
+	else
+		osd_end_request(or);
+}
+
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private)
+{
+	or->request->end_io_data = or;
+	or->async_private = private;
+	or->async_done = done;
+
+	blk_execute_rq_nowait(or->request->q, NULL, or->request, 0,
+			      osd_request_async_done);
+	return 0;
+}
+EXPORT_SYMBOL(osd_execute_request_async);
+
+/*
+ * Common to all OSD commands
+ */
+
+static void _osdv1_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv1_cdb *ocdb = &or->cdb.v1;
+
+	/*
+	 * For speed, the commands
+	 *	OSD_ACT_PERFORM_SCSI_COMMAND	, V1 0x8F7E, V2 0x8F7C
+	 *	OSD_ACT_SCSI_TASK_MANAGEMENT	, V1 0x8F7F, V2 0x8F7D
+	 * are not supported here. Should pass zero and set after the call
+	 */
+	act &= __constant_cpu_to_be16(~0x0080); /* V1 action code */
+
+	OSD_DEBUG("OSDv1 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v1.length = cpu_to_be64(len);
+	ocdb->h.v1.start_address = cpu_to_be64(offset);
+}
+
+static void _osd_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	_osdv1_req_encode_common(or, act, obj, offset, len);
+}
+
+/*
+ * Device commands
+ */
+void osd_req_format(struct osd_request *or, u64 tot_capacity)
+{
+	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
+				tot_capacity);
+}
+EXPORT_SYMBOL(osd_req_format);
+
+/*
+ * Partition commands
+ */
+static void _osd_req_encode_partition(struct osd_request *or,
+	__be16 act, osd_id partition)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	_osd_req_encode_common(or, act, &par, 0, 0);
+}
+
+void osd_req_create_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_CREATE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_create_partition);
+
+void osd_req_remove_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_REMOVE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_remove_partition);
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_CREATE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_create_object);
+
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_REMOVE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_remove_object);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, bio->bi_size);
+	WARN_ON(or->out.bio || or->out.total_bytes);
+	bio->bi_rw |= (1 << BIO_RW);
+	or->out.bio = bio;
+	or->out.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_write);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_READ, obj, offset, bio->bi_size);
+	WARN_ON(or->in.bio || or->in.total_bytes);
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_read);
+
+/*
+ * osd_finalize_request and helpers
+ */
+
+static int _init_blk_request(struct osd_request *or,
+	bool has_in, bool has_out)
+{
+	gfp_t flags = or->alloc_flags;
+	struct scsi_device *scsi_dev = or->osd_dev->scsi_dev;
+	struct request_queue *q = scsi_dev->request_queue;
+	struct request *req;
+	int ret = -ENOMEM;
+
+	req = blk_get_request(q, has_out, flags);
+	if (!req)
+		goto out;
+
+	or->request = req;
+	req->cmd_type = REQ_TYPE_BLOCK_PC;
+	req->timeout = or->timeout;
+	req->retries = or->retries;
+	req->sense = or->sense;
+	req->sense_len = 0;
+
+	if (has_out) {
+		or->out.req = req;
+		if (has_in) {
+			/* allocate bidi request */
+			req = blk_get_request(q, READ, flags);
+			if (!req) {
+				OSD_DEBUG("blk_get_request for bidi failed\n");
+				goto out;
+			}
+			req->cmd_type = REQ_TYPE_BLOCK_PC;
+			or->in.req = or->request->next_rq = req;
+		}
+	} else if (has_in)
+		or->in.req = req;
+
+	ret = 0;
+out:
+	OSD_DEBUG("or=%p has_in=%d has_out=%d => %d, %p\n",
+			or, has_in, has_out, ret, or->request);
+	return ret;
+}
+
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	bool has_in, has_out;
+	int ret;
+
+	if (options & OSD_REQ_FUA)
+		cdbh->options |= OSD_CDB_FUA;
+
+	if (options & OSD_REQ_DPO)
+		cdbh->options |= OSD_CDB_DPO;
+
+	if (options & OSD_REQ_BYPASS_TIMESTAMPS)
+		cdbh->timestamp_control = OSD_CDB_BYPASS_TIMESTAMPS;
+
+	osd_set_caps(&or->cdb, cap);
+
+	has_in = or->in.bio || or->get_attr.total_bytes;
+	has_out = or->out.bio || or->set_attr.total_bytes ||
+		or->enc_get_attr.total_bytes;
+
+	ret = _init_blk_request(or, has_in, has_out);
+	if (ret) {
+		OSD_DEBUG("_init_blk_request failed\n");
+		return ret;
+	}
+
+	if (or->out.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->out.req,
+					or->out.bio);
+		if (ret) {
+			OSD_DEBUG("blk_rq_append_bio out failed\n");
+			return ret;
+		}
+		OSD_DEBUG("out bytes=%llu (bytes_req=%u)\n",
+			or->out.total_bytes, or->out.req->data_len);
+	}
+	if (or->in.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->in.req, or->in.bio);
+		if (ret) {
+			OSD_DEBUG("blk_rq_append_bio in failed\n");
+			return ret;
+		}
+		OSD_DEBUG("in bytes=%llu (bytes_req=%u)\n",
+			or->in.total_bytes, or->in.req->data_len);
+	}
+
+	if (!or->attributes_mode)
+		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+	cdbh->command_specific_options |= or->attributes_mode;
+
+	or->request->cmd = or->cdb.buff;
+	or->request->cmd_len = _osd_req_cdb_len(or);
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_finalize_request);
+
+/*
+ * Implementation of osd_sec.h API
+ * TODO: Move to a separate osd_sec.c file at a later stage.
+ */
+
+enum { OSD_SEC_CAP_V1_ALL_CAPS =
+	OSD_SEC_CAP_APPEND | OSD_SEC_CAP_OBJ_MGMT | OSD_SEC_CAP_REMOVE   |
+	OSD_SEC_CAP_CREATE | OSD_SEC_CAP_SET_ATTR | OSD_SEC_CAP_GET_ATTR |
+	OSD_SEC_CAP_WRITE  | OSD_SEC_CAP_READ     | OSD_SEC_CAP_POL_SEC  |
+	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
+};
+
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
+{
+	struct osd_capability *cap = caps;
+	u8 type;
+	u8 descriptor_type;
+
+	if (likely(obj->id)) {
+		if (unlikely(is_collection)) {
+			type = OSD_SEC_OBJ_COLLECTION;
+			descriptor_type = is_v1 ? OSD_SEC_OBJ_DESC_OBJ :
+						  OSD_SEC_OBJ_DESC_COL;
+		} else {
+			type = OSD_SEC_OBJ_USER;
+			descriptor_type = OSD_SEC_OBJ_DESC_OBJ;
+		}
+		WARN_ON(!obj->partition);
+	} else {
+		type = obj->partition ? OSD_SEC_OBJ_PARTITION :
+					OSD_SEC_OBJ_ROOT;
+		descriptor_type = OSD_SEC_OBJ_DESC_PAR;
+	}
+
+	memset(cap, 0, sizeof(*cap));
+
+	cap->h.format = OSD_SEC_CAP_FORMAT_VER1;
+	cap->h.integrity_algorithm__key_version = 0; /* MAKE_BYTE(0, 0); */
+	cap->h.security_method = OSD_SEC_NOSEC;
+/*	cap->expiration_time;
+	cap->AUDIT[30-10];
+	cap->discriminator[42-30];
+	cap->object_created_time; */
+	cap->h.object_type = type;
+	osd_sec_set_caps(&cap->h, OSD_SEC_CAP_V1_ALL_CAPS);
+	cap->h.object_descriptor_type = descriptor_type;
+	cap->od.obj_desc.policy_access_tag = 0;
+	cap->od.obj_desc.allowed_partition_id = cpu_to_be64(obj->partition);
+	cap->od.obj_desc.allowed_object_id = cpu_to_be64(obj->id);
+}
+EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
+
+void osd_set_caps(struct osd_cdb *cdb, const void *caps)
+{
+	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+}
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 04/18] libosd: OSDv1 preliminary implementation
  2008-11-04 16:09   ` Boaz Harrosh
                     ` (5 preceding siblings ...)
  (?)
@ 2008-11-04 16:44   ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Implementation of the most basic OSD functionality and
infrastructure. Mainly Format, Create/Remove Partition,
Create/Remove Object, and read/write.

- Add Makefile and Kbuild to compile libosd.ko
- osd_initiator.c Implementation file for osd_initiator.h
  and osd_sec.h APIs
- osd_debug.h - Some kprintf macro definitions

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild          |   26 +++
 drivers/scsi/osd/Makefile        |   37 +++
 drivers/scsi/osd/osd_debug.h     |   27 +++
 drivers/scsi/osd/osd_initiator.c |  450 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 540 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kbuild
 create mode 100755 drivers/scsi/osd/Makefile
 create mode 100644 drivers/scsi/osd/osd_debug.h
 create mode 100644 drivers/scsi/osd/osd_initiator.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
new file mode 100644
index 0000000..b4678e0
--- /dev/null
+++ b/drivers/scsi/osd/Kbuild
@@ -0,0 +1,26 @@
+#
+# Kbuild for the OSD modules
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+
+ifneq ($(OSD_INC),)
+# we are built out-of-tree Kconfigure everything as on
+
+CONFIG_SCSI_OSD_INITIATOR=m
+EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
+
+EXTRA_CFLAGS += -I$(OSD_INC)
+# EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_DEBUG
+
+endif
+
+libosd-objs := osd_initiator.o
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile
new file mode 100755
index 0000000..d905344
--- /dev/null
+++ b/drivers/scsi/osd/Makefile
@@ -0,0 +1,37 @@
+#
+# Makefile for the OSD modules (out of tree)
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+# This Makefile is used to call the kernel Makefile in case of an out-of-tree
+# build.
+# $KSRC should point to a Kernel source tree otherwise host's default is
+# used. (eg. /lib/modules/`uname -r`/build)
+
+# include path for out-of-tree Headers
+OSD_INC ?= `pwd`/../../../include
+
+# allow users to override these
+# e.g. to compile for a kernel that you aren't currently running
+KSRC ?= /lib/modules/$(shell uname -r)/build
+KBUILD_OUTPUT ?=
+ARCH ?=
+V ?= 0
+
+# this is the basic Kbuild out-of-tree invocation, with the M= option
+KBUILD_BASE = +$(MAKE) -C $(KSRC) M=`pwd` KBUILD_OUTPUT=$(KBUILD_OUTPUT) ARCH=$(ARCH) V=$(V)
+
+all: libosd
+
+libosd: ;
+	$(KBUILD_BASE) OSD_INC=$(OSD_INC) modules
+
+clean:
+	$(KBUILD_BASE) clean
diff --git a/drivers/scsi/osd/osd_debug.h b/drivers/scsi/osd/osd_debug.h
new file mode 100644
index 0000000..0bc65fa
--- /dev/null
+++ b/drivers/scsi/osd/osd_debug.h
@@ -0,0 +1,27 @@
+/*
+ * osd_debug.h - Some kprintf macros
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_DEBUG_H__
+#define __OSD_DEBUG_H__
+
+#define OSD_ERR(fmt, a...) printk(KERN_ERR "osd: " fmt, ##a)
+#define OSD_INFO(fmt, a...) printk(KERN_NOTICE "osd: " fmt, ##a)
+
+#ifdef CONFIG_SCSI_OSD_DEBUG
+#define OSD_DEBUG(fmt, a...) \
+	printk(KERN_NOTICE "osd @%s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define OSD_DEBUG(fmt, a...) do {} while (0)
+#endif
+
+#endif /* ndef __OSD_DEBUG_H__ */
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
new file mode 100644
index 0000000..33450b8
--- /dev/null
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -0,0 +1,450 @@
+/*
+ * osd_initiator - Main body of the osd initiator library.
+ *
+ * Note: The file does not contain the advanced security functionality which
+ * is only needed by the security_manager's initiators.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+#include <scsi/scsi_device.h>
+
+#include "osd_debug.h"
+
+enum { OSD_REQ_RETRIES = 1 };
+
+#ifdef CONFIG_SCSI_OSD_INITIATOR_MODULE
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd initiator library libosd.ko");
+MODULE_LICENSE("GPL");
+#endif
+
+static inline void build_test(void)
+{
+	/* structures were not packed */
+	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
+}
+
+static unsigned _osd_req_cdb_len(struct osd_request *or)
+{
+	return OSDv1_TOTAL_CDB_LEN;
+}
+
+void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
+{
+	memset(osdd, 0, sizeof(*osdd));
+	osdd->scsi_dev = scsi_dev;
+	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+	/* TODO: Allocate pools for osd_request attributes ... */
+}
+EXPORT_SYMBOL(osd_dev_init);
+
+void osd_dev_fini(struct osd_dev *osdd)
+{
+	/* TODO: De-allocate pools */
+
+	osdd->scsi_dev = NULL;
+}
+EXPORT_SYMBOL(osd_dev_fini);
+
+struct osd_request *_osd_request_alloc(gfp_t gfp)
+{
+	struct osd_request *or;
+
+	/* TODO: Use mempool with one saved request */
+	or = kzalloc(sizeof(*or), gfp);
+	return or;
+}
+
+void _osd_request_free(struct osd_request *or)
+{
+	kfree(or);
+}
+
+struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp)
+{
+	struct osd_request *or;
+
+	or = _osd_request_alloc(gfp);
+	if (!or)
+		return NULL;
+
+	or->osd_dev = dev;
+	or->alloc_flags = gfp;
+	or->timeout = dev->def_timeout;
+	or->retries = OSD_REQ_RETRIES;
+
+	return or;
+}
+EXPORT_SYMBOL(osd_start_request);
+
+/*
+ * If osd_finalize_request() was called but the request was not executed through
+ * the block layer, then we must release BIOs.
+ */
+static void _abort_unexecuted_bios(struct request *rq)
+{
+	struct bio *bio;
+
+	while ((bio = rq->bio) != NULL) {
+		rq->bio = bio->bi_next;
+		bio_endio(bio, 0);
+	}
+}
+
+void osd_end_request(struct osd_request *or)
+{
+	struct request *rq = or->request;
+
+	if (rq) {
+		if (rq->next_rq) {
+			_abort_unexecuted_bios(rq->next_rq);
+			blk_put_request(rq->next_rq);
+		}
+
+		_abort_unexecuted_bios(rq);
+		blk_put_request(rq);
+	}
+	_osd_request_free(or);
+}
+EXPORT_SYMBOL(osd_end_request);
+
+int osd_execute_request(struct osd_request *or)
+{
+	return blk_execute_rq(or->request->q, NULL, or->request, 0);
+}
+EXPORT_SYMBOL(osd_execute_request);
+
+static void osd_request_async_done(struct request *req, int error)
+{
+	struct osd_request *or = req->end_io_data;
+
+	or->async_error = error;
+
+	if (error)
+		OSD_DEBUG("osd_request_async_done error recieved %d\n", error);
+
+	if (or->async_done)
+		or->async_done(or, or->async_private);
+	else
+		osd_end_request(or);
+}
+
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private)
+{
+	or->request->end_io_data = or;
+	or->async_private = private;
+	or->async_done = done;
+
+	blk_execute_rq_nowait(or->request->q, NULL, or->request, 0,
+			      osd_request_async_done);
+	return 0;
+}
+EXPORT_SYMBOL(osd_execute_request_async);
+
+/*
+ * Common to all OSD commands
+ */
+
+static void _osdv1_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv1_cdb *ocdb = &or->cdb.v1;
+
+	/*
+	 * For speed, the commands
+	 *	OSD_ACT_PERFORM_SCSI_COMMAND	, V1 0x8F7E, V2 0x8F7C
+	 *	OSD_ACT_SCSI_TASK_MANAGEMENT	, V1 0x8F7F, V2 0x8F7D
+	 * are not supported here. Should pass zero and set after the call
+	 */
+	act &= __constant_cpu_to_be16(~0x0080); /* V1 action code */
+
+	OSD_DEBUG("OSDv1 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v1.length = cpu_to_be64(len);
+	ocdb->h.v1.start_address = cpu_to_be64(offset);
+}
+
+static void _osd_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	_osdv1_req_encode_common(or, act, obj, offset, len);
+}
+
+/*
+ * Device commands
+ */
+void osd_req_format(struct osd_request *or, u64 tot_capacity)
+{
+	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
+				tot_capacity);
+}
+EXPORT_SYMBOL(osd_req_format);
+
+/*
+ * Partition commands
+ */
+static void _osd_req_encode_partition(struct osd_request *or,
+	__be16 act, osd_id partition)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	_osd_req_encode_common(or, act, &par, 0, 0);
+}
+
+void osd_req_create_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_CREATE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_create_partition);
+
+void osd_req_remove_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_REMOVE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_remove_partition);
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_CREATE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_create_object);
+
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_REMOVE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_remove_object);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, bio->bi_size);
+	WARN_ON(or->out.bio || or->out.total_bytes);
+	bio->bi_rw |= (1 << BIO_RW);
+	or->out.bio = bio;
+	or->out.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_write);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_READ, obj, offset, bio->bi_size);
+	WARN_ON(or->in.bio || or->in.total_bytes);
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_read);
+
+/*
+ * osd_finalize_request and helpers
+ */
+
+static int _init_blk_request(struct osd_request *or,
+	bool has_in, bool has_out)
+{
+	gfp_t flags = or->alloc_flags;
+	struct scsi_device *scsi_dev = or->osd_dev->scsi_dev;
+	struct request_queue *q = scsi_dev->request_queue;
+	struct request *req;
+	int ret = -ENOMEM;
+
+	req = blk_get_request(q, has_out, flags);
+	if (!req)
+		goto out;
+
+	or->request = req;
+	req->cmd_type = REQ_TYPE_BLOCK_PC;
+	req->timeout = or->timeout;
+	req->retries = or->retries;
+	req->sense = or->sense;
+	req->sense_len = 0;
+
+	if (has_out) {
+		or->out.req = req;
+		if (has_in) {
+			/* allocate bidi request */
+			req = blk_get_request(q, READ, flags);
+			if (!req) {
+				OSD_DEBUG("blk_get_request for bidi failed\n");
+				goto out;
+			}
+			req->cmd_type = REQ_TYPE_BLOCK_PC;
+			or->in.req = or->request->next_rq = req;
+		}
+	} else if (has_in)
+		or->in.req = req;
+
+	ret = 0;
+out:
+	OSD_DEBUG("or=%p has_in=%d has_out=%d => %d, %p\n",
+			or, has_in, has_out, ret, or->request);
+	return ret;
+}
+
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	bool has_in, has_out;
+	int ret;
+
+	if (options & OSD_REQ_FUA)
+		cdbh->options |= OSD_CDB_FUA;
+
+	if (options & OSD_REQ_DPO)
+		cdbh->options |= OSD_CDB_DPO;
+
+	if (options & OSD_REQ_BYPASS_TIMESTAMPS)
+		cdbh->timestamp_control = OSD_CDB_BYPASS_TIMESTAMPS;
+
+	osd_set_caps(&or->cdb, cap);
+
+	has_in = or->in.bio || or->get_attr.total_bytes;
+	has_out = or->out.bio || or->set_attr.total_bytes ||
+		or->enc_get_attr.total_bytes;
+
+	ret = _init_blk_request(or, has_in, has_out);
+	if (ret) {
+		OSD_DEBUG("_init_blk_request failed\n");
+		return ret;
+	}
+
+	if (or->out.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->out.req,
+					or->out.bio);
+		if (ret) {
+			OSD_DEBUG("blk_rq_append_bio out failed\n");
+			return ret;
+		}
+		OSD_DEBUG("out bytes=%llu (bytes_req=%u)\n",
+			or->out.total_bytes, or->out.req->data_len);
+	}
+	if (or->in.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->in.req, or->in.bio);
+		if (ret) {
+			OSD_DEBUG("blk_rq_append_bio in failed\n");
+			return ret;
+		}
+		OSD_DEBUG("in bytes=%llu (bytes_req=%u)\n",
+			or->in.total_bytes, or->in.req->data_len);
+	}
+
+	if (!or->attributes_mode)
+		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+	cdbh->command_specific_options |= or->attributes_mode;
+
+	or->request->cmd = or->cdb.buff;
+	or->request->cmd_len = _osd_req_cdb_len(or);
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_finalize_request);
+
+/*
+ * Implementation of osd_sec.h API
+ * TODO: Move to a separate osd_sec.c file at a later stage.
+ */
+
+enum { OSD_SEC_CAP_V1_ALL_CAPS =
+	OSD_SEC_CAP_APPEND | OSD_SEC_CAP_OBJ_MGMT | OSD_SEC_CAP_REMOVE   |
+	OSD_SEC_CAP_CREATE | OSD_SEC_CAP_SET_ATTR | OSD_SEC_CAP_GET_ATTR |
+	OSD_SEC_CAP_WRITE  | OSD_SEC_CAP_READ     | OSD_SEC_CAP_POL_SEC  |
+	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
+};
+
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
+{
+	struct osd_capability *cap = caps;
+	u8 type;
+	u8 descriptor_type;
+
+	if (likely(obj->id)) {
+		if (unlikely(is_collection)) {
+			type = OSD_SEC_OBJ_COLLECTION;
+			descriptor_type = is_v1 ? OSD_SEC_OBJ_DESC_OBJ :
+						  OSD_SEC_OBJ_DESC_COL;
+		} else {
+			type = OSD_SEC_OBJ_USER;
+			descriptor_type = OSD_SEC_OBJ_DESC_OBJ;
+		}
+		WARN_ON(!obj->partition);
+	} else {
+		type = obj->partition ? OSD_SEC_OBJ_PARTITION :
+					OSD_SEC_OBJ_ROOT;
+		descriptor_type = OSD_SEC_OBJ_DESC_PAR;
+	}
+
+	memset(cap, 0, sizeof(*cap));
+
+	cap->h.format = OSD_SEC_CAP_FORMAT_VER1;
+	cap->h.integrity_algorithm__key_version = 0; /* MAKE_BYTE(0, 0); */
+	cap->h.security_method = OSD_SEC_NOSEC;
+/*	cap->expiration_time;
+	cap->AUDIT[30-10];
+	cap->discriminator[42-30];
+	cap->object_created_time; */
+	cap->h.object_type = type;
+	osd_sec_set_caps(&cap->h, OSD_SEC_CAP_V1_ALL_CAPS);
+	cap->h.object_descriptor_type = descriptor_type;
+	cap->od.obj_desc.policy_access_tag = 0;
+	cap->od.obj_desc.allowed_partition_id = cpu_to_be64(obj->partition);
+	cap->od.obj_desc.allowed_object_id = cpu_to_be64(obj->id);
+}
+EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
+
+void osd_set_caps(struct osd_cdb *cdb, const void *caps)
+{
+	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+}
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 05/18] osd_uld: OSD scsi ULD
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Add a Linux driver module that registers as a SCSI ULD and probes
for OSD type SCSI devices.

When an OSD-type SCSI device is found a character device is created
in the form of /dev/osdX - where X goes from 0 up to hard coded 64.
The Major character device number used is *260*, which is free
(as of Linux v2.6.28-rc3).

A single ioctl is currently supported that will invoke an in-kernel
test on the specified OSD device (lun).

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild       |    7 +
 drivers/scsi/osd/osd_ktests.h |   27 +++
 drivers/scsi/osd/osd_uld.c    |  388 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 422 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_ktests.h
 create mode 100644 drivers/scsi/osd/osd_uld.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index b4678e0..f39f82f 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -17,6 +17,9 @@ ifneq ($(OSD_INC),)
 CONFIG_SCSI_OSD_INITIATOR=m
 EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
 
+CONFIG_SCSI_OSD_ULD=m
+EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_ULD -DCONFIG_SCSI_OSD_ULD_MODULE
+
 EXTRA_CFLAGS += -I$(OSD_INC)
 # EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_DEBUG
 
@@ -24,3 +27,7 @@ endif
 
 libosd-objs := osd_initiator.o
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
+
+# osd.ko - SCSI ULD and char-device
+osd-objs := osd_uld.o
+obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
diff --git a/drivers/scsi/osd/osd_ktests.h b/drivers/scsi/osd/osd_ktests.h
new file mode 100644
index 0000000..a9e5e00
--- /dev/null
+++ b/drivers/scsi/osd/osd_ktests.h
@@ -0,0 +1,27 @@
+/*
+ * osd_ktests.h - Define the ktests.c API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_KTESTS_H__
+#define __OSD_KTESTS_H__
+
+/* Tests from osd_ktests.c */
+/* TODO: Only one simple test for now. Later I will add a test definition
+ *	structure that will define what tests to preform and with some
+ *	parametrization, so concurrent tests could be run on same OSD lun
+ *	without stepping on each other. (E.g. Format called when other tests
+ *	are in progress)
+ */
+
+enum { OSD_TEST_ALL = 17 };
+
+#endif /*ndef __OSD_KTESTS_H__*/
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
new file mode 100644
index 0000000..87b4540
--- /dev/null
+++ b/drivers/scsi/osd/osd_uld.c
@@ -0,0 +1,388 @@
+/*
+ * osd_uld.c - OSD Upper Layer Driver
+ *
+ * A Linux driver module that registers as a SCSI ULD and probes
+ * for OSD type SCSI devices.
+ * It's main function is to export osd devices to in-kernel users like
+ * osdfs and pNFS-objects-LD. It also provides one ioctl for running
+ * in Kernel tests.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/major.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_ioctl.h>
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+
+#include "osd_ktests.h"
+#include "osd_debug.h"
+
+#ifndef TYPE_OSD
+#  define TYPE_OSD 0x11
+#endif
+
+#ifndef SCSI_OSD_MAJOR
+#  define SCSI_OSD_MAJOR 260
+#endif
+#define SCSI_OSD_MAX_MINOR 64
+
+static const char osd_name[] = "osd";
+static const char *osd_version_string = "open-osd 0.1.0";
+const char osd_symlink[] = "scsi_osd";
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SCSI_OSD_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_OSD);
+
+struct osd_uld_device {
+	int minor;
+	struct kref kref;
+	struct cdev cdev;
+	struct osd_dev od;
+	struct gendisk *disk;
+	struct device *class_member;
+};
+
+static void __uld_get(struct osd_uld_device *oud);
+static void __uld_put(struct osd_uld_device *oud);
+
+/*
+ * Char Device operations
+ */
+
+static int osd_uld_open(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *oud = container_of(inode->i_cdev,
+					struct osd_uld_device, cdev);
+
+	__uld_get(oud);
+	/* cache osd_uld_device on file handle */
+	file->private_data = oud;
+	OSD_DEBUG("osd_uld_open %p\n", oud);
+	return 0;
+}
+
+static int osd_uld_release(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *oud = file->private_data;
+
+	OSD_DEBUG("osd_uld_release %p\n", file->private_data);
+	file->private_data = NULL;
+	__uld_put(oud);
+	return 0;
+}
+
+static long osd_uld_ioctl(struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	struct osd_uld_device *oud = file->private_data;
+	int ret;
+
+	switch (cmd) {
+	case OSD_TEST_ALL:
+		OSD_DEBUG("Kernel test %d: osd_uld_device=%p\n", cmd, oud);
+		ret = 0;
+		break;
+	default:
+		OSD_ERR("Unknown osd_uld_ioctl %d\n", cmd);
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+static const struct file_operations osd_fops = {
+	.owner          = THIS_MODULE,
+	.open           = osd_uld_open,
+	.release        = osd_uld_release,
+	.unlocked_ioctl = osd_uld_ioctl,
+};
+
+/*
+ * Scsi Device operations
+ */
+
+static int __detect_osd(struct osd_uld_device *oud)
+{
+	struct scsi_device *scsi_dev = oud->od.scsi_dev;
+	int error;
+
+	/* sending a test_unit_ready as first command seems to be needed
+	 * by some targets
+	 */
+	OSD_DEBUG("start scsi_test_unit_ready %p %p %p\n",
+			oud, scsi_dev, scsi_dev->request_queue);
+	error = scsi_test_unit_ready(scsi_dev, 10*HZ, 5, NULL);
+	if (error)
+		OSD_ERR("warning: scsi_test_unit_ready failed\n");
+
+	return 0;
+}
+
+static struct class *osd_sysfs_class;
+static DEFINE_IDA(osd_minor_ida);
+
+static int osd_probe(struct device *dev)
+{
+	struct scsi_device *scsi_dev = to_scsi_device(dev);
+	struct gendisk *disk;
+	struct osd_uld_device *oud;
+	int minor;
+	int error;
+
+	if (scsi_dev->type != TYPE_OSD)
+		return -ENODEV;
+
+	do {
+		if (!ida_pre_get(&osd_minor_ida, GFP_KERNEL))
+			return -ENODEV;
+
+		error = ida_get_new(&osd_minor_ida, &minor);
+	} while (error == -EAGAIN);
+
+	if (error)
+		return error;
+	if (minor >= SCSI_OSD_MAX_MINOR) {
+		error = -EBUSY;
+		goto err_retract_minor;
+	}
+
+	error = -ENOMEM;
+	oud = kzalloc(sizeof(*oud), GFP_KERNEL);
+	if (NULL == oud)
+		goto err_retract_minor;
+
+	kref_init(&oud->kref);
+	dev_set_drvdata(dev, oud);
+	oud->minor = minor;
+
+	/* allocate a disk and set it up */
+	/* FIXME: do we need this since sg has already done that */
+	disk = alloc_disk(1);
+	if (!disk) {
+		OSD_ERR("alloc_disk failed\n");
+		goto err_free_osd;
+	}
+	disk->major = SCSI_OSD_MAJOR;
+	disk->first_minor = oud->minor;
+	sprintf(disk->disk_name, "osd%d", oud->minor);
+	oud->disk = disk;
+
+	/* hold one more reference to the scsi_dev that will get released
+	 * in __release, in case a logout is happening while fs is mounted
+	 */
+	scsi_device_get(scsi_dev);
+	osd_dev_init(&oud->od, scsi_dev);
+
+	/* Detect the OSD Version */
+	error = __detect_osd(oud);
+	if (error) {
+		OSD_ERR("osd detection failed, non-compatible OSD device\n");
+		goto err_put_disk;
+	}
+
+	/* init the char-device for communication with user-mode */
+	cdev_init(&oud->cdev, &osd_fops);
+	oud->cdev.owner = THIS_MODULE;
+	error = cdev_add(&oud->cdev,
+			 MKDEV(SCSI_OSD_MAJOR, oud->minor), 1);
+	if (error) {
+		OSD_ERR("cdev_add failed\n");
+		goto err_put_disk;
+	}
+	kobject_get(&oud->cdev.kobj); /* 2nd ref see osd_remove() */
+
+	/* class_member */
+	oud->class_member = device_create(osd_sysfs_class, dev,
+		MKDEV(SCSI_OSD_MAJOR, oud->minor), "%s", disk->disk_name);
+	if (IS_ERR(oud->class_member)) {
+		OSD_ERR("class_device_create failed\n");
+		error = PTR_ERR(oud->class_member);
+		goto err_put_cdev;
+	}
+
+	dev_set_drvdata(oud->class_member, oud);
+	error = sysfs_create_link(&scsi_dev->sdev_gendev.kobj,
+				  &oud->class_member->kobj, osd_symlink);
+	if (error)
+		OSD_ERR("warning: unable to make symlink\n");
+
+	OSD_INFO("osd_probe %s\n", disk->disk_name);
+	return 0;
+
+err_put_cdev:
+	cdev_del(&oud->cdev);
+err_put_disk:
+	scsi_device_put(scsi_dev);
+	put_disk(disk);
+err_free_osd:
+	dev_set_drvdata(dev, NULL);
+	kfree(oud);
+err_retract_minor:
+	ida_remove(&osd_minor_ida, minor);
+	return error;
+}
+
+static int osd_remove(struct device *dev)
+{
+	struct scsi_device *scsi_dev = to_scsi_device(dev);
+	struct osd_uld_device *oud = dev_get_drvdata(dev);
+
+	if (!oud || (oud->od.scsi_dev != scsi_dev)) {
+		OSD_ERR("Half cooked osd-device %p,%p || %p!=%p",
+			dev, oud, oud ? oud->od.scsi_dev : NULL,
+			scsi_dev);
+	}
+
+	sysfs_remove_link(&oud->od.scsi_dev->sdev_gendev.kobj, osd_symlink);
+
+	if (oud->class_member)
+		device_destroy(osd_sysfs_class,
+			       MKDEV(SCSI_OSD_MAJOR, oud->minor));
+
+	/* We have 2 references to the cdev. One is released here
+	 * and also takes down the /dev/osdX mapping. The second
+	 * Will be released in __remove() after all users have released
+	 * the osd_uld_device.
+	 */
+	if (oud->cdev.owner)
+		cdev_del(&oud->cdev);
+
+	__uld_put(oud);
+	return 0;
+}
+
+static void __remove(struct kref *kref)
+{
+	struct osd_uld_device *oud = container_of(kref,
+					struct osd_uld_device, kref);
+	struct scsi_device *scsi_dev = oud->od.scsi_dev;
+
+	/* now let delete the char_dev */
+	kobject_put(&oud->cdev.kobj);
+
+	osd_dev_fini(&oud->od);
+	scsi_device_put(scsi_dev);
+
+	OSD_INFO("osd_remove %s\n",
+		 oud->disk ? oud->disk->disk_name : NULL);
+
+	if (oud->disk)
+		put_disk(oud->disk);
+
+	ida_remove(&osd_minor_ida, oud->minor);
+	kfree(oud);
+}
+
+static void __uld_get(struct osd_uld_device *oud)
+{
+	kref_get(&oud->kref);
+}
+
+static void __uld_put(struct osd_uld_device *oud)
+{
+	kref_put(&oud->kref, __remove);
+}
+
+/*
+ * Global driver and scsi registration
+ */
+
+static struct scsi_driver osd_driver = {
+	.owner			= THIS_MODULE,
+	.gendrv = {
+		.name		= osd_name,
+		.probe		= osd_probe,
+		.remove		= osd_remove,
+	}
+};
+
+static int __init osd_uld_init(void)
+{
+	int err;
+
+	osd_sysfs_class = class_create(THIS_MODULE, osd_symlink);
+	if (IS_ERR(osd_sysfs_class)) {
+		OSD_ERR("Unable to register sysfs class => %ld\n",
+			PTR_ERR(osd_sysfs_class));
+		return PTR_ERR(osd_sysfs_class);
+	}
+
+	err = register_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0),
+				     SCSI_OSD_MAX_MINOR, osd_name);
+	if (err) {
+		OSD_ERR("Unable to register major %d for osd ULD => %d\n",
+			SCSI_OSD_MAJOR, err);
+		goto err_out;
+	}
+
+	err = scsi_register_driver(&osd_driver.gendrv);
+	if (err) {
+		OSD_ERR("scsi_register_driver failed => %d\n", err);
+		goto err_out_chrdev;
+	}
+
+	OSD_INFO("LOADED %s\n", osd_version_string);
+	return 0;
+
+err_out_chrdev:
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+err_out:
+	class_destroy(osd_sysfs_class);
+	return err;
+}
+
+static void __exit osd_uld_exit(void)
+{
+	scsi_unregister_driver(&osd_driver.gendrv);
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+	class_destroy(osd_sysfs_class);
+	OSD_INFO("UNLOADED %s\n", osd_version_string);
+}
+
+module_init(osd_uld_init);
+module_exit(osd_uld_exit);
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 05/18] osd_uld: OSD scsi ULD
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Add a Linux driver module that registers as a SCSI ULD and probes
for OSD type SCSI devices.

When an OSD-type SCSI device is found a character device is created
in the form of /dev/osdX - where X goes from 0 up to hard coded 64.
The Major character device number used is *260*, which is free
(as of Linux v2.6.28-rc3).

A single ioctl is currently supported that will invoke an in-kernel
test on the specified OSD device (lun).

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild       |    7 +
 drivers/scsi/osd/osd_ktests.h |   27 +++
 drivers/scsi/osd/osd_uld.c    |  388 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 422 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_ktests.h
 create mode 100644 drivers/scsi/osd/osd_uld.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index b4678e0..f39f82f 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -17,6 +17,9 @@ ifneq ($(OSD_INC),)
 CONFIG_SCSI_OSD_INITIATOR=m
 EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
 
+CONFIG_SCSI_OSD_ULD=m
+EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_ULD -DCONFIG_SCSI_OSD_ULD_MODULE
+
 EXTRA_CFLAGS += -I$(OSD_INC)
 # EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_DEBUG
 
@@ -24,3 +27,7 @@ endif
 
 libosd-objs := osd_initiator.o
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
+
+# osd.ko - SCSI ULD and char-device
+osd-objs := osd_uld.o
+obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
diff --git a/drivers/scsi/osd/osd_ktests.h b/drivers/scsi/osd/osd_ktests.h
new file mode 100644
index 0000000..a9e5e00
--- /dev/null
+++ b/drivers/scsi/osd/osd_ktests.h
@@ -0,0 +1,27 @@
+/*
+ * osd_ktests.h - Define the ktests.c API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_KTESTS_H__
+#define __OSD_KTESTS_H__
+
+/* Tests from osd_ktests.c */
+/* TODO: Only one simple test for now. Later I will add a test definition
+ *	structure that will define what tests to preform and with some
+ *	parametrization, so concurrent tests could be run on same OSD lun
+ *	without stepping on each other. (E.g. Format called when other tests
+ *	are in progress)
+ */
+
+enum { OSD_TEST_ALL = 17 };
+
+#endif /*ndef __OSD_KTESTS_H__*/
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
new file mode 100644
index 0000000..87b4540
--- /dev/null
+++ b/drivers/scsi/osd/osd_uld.c
@@ -0,0 +1,388 @@
+/*
+ * osd_uld.c - OSD Upper Layer Driver
+ *
+ * A Linux driver module that registers as a SCSI ULD and probes
+ * for OSD type SCSI devices.
+ * It's main function is to export osd devices to in-kernel users like
+ * osdfs and pNFS-objects-LD. It also provides one ioctl for running
+ * in Kernel tests.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/major.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_ioctl.h>
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+
+#include "osd_ktests.h"
+#include "osd_debug.h"
+
+#ifndef TYPE_OSD
+#  define TYPE_OSD 0x11
+#endif
+
+#ifndef SCSI_OSD_MAJOR
+#  define SCSI_OSD_MAJOR 260
+#endif
+#define SCSI_OSD_MAX_MINOR 64
+
+static const char osd_name[] = "osd";
+static const char *osd_version_string = "open-osd 0.1.0";
+const char osd_symlink[] = "scsi_osd";
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SCSI_OSD_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_OSD);
+
+struct osd_uld_device {
+	int minor;
+	struct kref kref;
+	struct cdev cdev;
+	struct osd_dev od;
+	struct gendisk *disk;
+	struct device *class_member;
+};
+
+static void __uld_get(struct osd_uld_device *oud);
+static void __uld_put(struct osd_uld_device *oud);
+
+/*
+ * Char Device operations
+ */
+
+static int osd_uld_open(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *oud = container_of(inode->i_cdev,
+					struct osd_uld_device, cdev);
+
+	__uld_get(oud);
+	/* cache osd_uld_device on file handle */
+	file->private_data = oud;
+	OSD_DEBUG("osd_uld_open %p\n", oud);
+	return 0;
+}
+
+static int osd_uld_release(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *oud = file->private_data;
+
+	OSD_DEBUG("osd_uld_release %p\n", file->private_data);
+	file->private_data = NULL;
+	__uld_put(oud);
+	return 0;
+}
+
+static long osd_uld_ioctl(struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	struct osd_uld_device *oud = file->private_data;
+	int ret;
+
+	switch (cmd) {
+	case OSD_TEST_ALL:
+		OSD_DEBUG("Kernel test %d: osd_uld_device=%p\n", cmd, oud);
+		ret = 0;
+		break;
+	default:
+		OSD_ERR("Unknown osd_uld_ioctl %d\n", cmd);
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+static const struct file_operations osd_fops = {
+	.owner          = THIS_MODULE,
+	.open           = osd_uld_open,
+	.release        = osd_uld_release,
+	.unlocked_ioctl = osd_uld_ioctl,
+};
+
+/*
+ * Scsi Device operations
+ */
+
+static int __detect_osd(struct osd_uld_device *oud)
+{
+	struct scsi_device *scsi_dev = oud->od.scsi_dev;
+	int error;
+
+	/* sending a test_unit_ready as first command seems to be needed
+	 * by some targets
+	 */
+	OSD_DEBUG("start scsi_test_unit_ready %p %p %p\n",
+			oud, scsi_dev, scsi_dev->request_queue);
+	error = scsi_test_unit_ready(scsi_dev, 10*HZ, 5, NULL);
+	if (error)
+		OSD_ERR("warning: scsi_test_unit_ready failed\n");
+
+	return 0;
+}
+
+static struct class *osd_sysfs_class;
+static DEFINE_IDA(osd_minor_ida);
+
+static int osd_probe(struct device *dev)
+{
+	struct scsi_device *scsi_dev = to_scsi_device(dev);
+	struct gendisk *disk;
+	struct osd_uld_device *oud;
+	int minor;
+	int error;
+
+	if (scsi_dev->type != TYPE_OSD)
+		return -ENODEV;
+
+	do {
+		if (!ida_pre_get(&osd_minor_ida, GFP_KERNEL))
+			return -ENODEV;
+
+		error = ida_get_new(&osd_minor_ida, &minor);
+	} while (error == -EAGAIN);
+
+	if (error)
+		return error;
+	if (minor >= SCSI_OSD_MAX_MINOR) {
+		error = -EBUSY;
+		goto err_retract_minor;
+	}
+
+	error = -ENOMEM;
+	oud = kzalloc(sizeof(*oud), GFP_KERNEL);
+	if (NULL == oud)
+		goto err_retract_minor;
+
+	kref_init(&oud->kref);
+	dev_set_drvdata(dev, oud);
+	oud->minor = minor;
+
+	/* allocate a disk and set it up */
+	/* FIXME: do we need this since sg has already done that */
+	disk = alloc_disk(1);
+	if (!disk) {
+		OSD_ERR("alloc_disk failed\n");
+		goto err_free_osd;
+	}
+	disk->major = SCSI_OSD_MAJOR;
+	disk->first_minor = oud->minor;
+	sprintf(disk->disk_name, "osd%d", oud->minor);
+	oud->disk = disk;
+
+	/* hold one more reference to the scsi_dev that will get released
+	 * in __release, in case a logout is happening while fs is mounted
+	 */
+	scsi_device_get(scsi_dev);
+	osd_dev_init(&oud->od, scsi_dev);
+
+	/* Detect the OSD Version */
+	error = __detect_osd(oud);
+	if (error) {
+		OSD_ERR("osd detection failed, non-compatible OSD device\n");
+		goto err_put_disk;
+	}
+
+	/* init the char-device for communication with user-mode */
+	cdev_init(&oud->cdev, &osd_fops);
+	oud->cdev.owner = THIS_MODULE;
+	error = cdev_add(&oud->cdev,
+			 MKDEV(SCSI_OSD_MAJOR, oud->minor), 1);
+	if (error) {
+		OSD_ERR("cdev_add failed\n");
+		goto err_put_disk;
+	}
+	kobject_get(&oud->cdev.kobj); /* 2nd ref see osd_remove() */
+
+	/* class_member */
+	oud->class_member = device_create(osd_sysfs_class, dev,
+		MKDEV(SCSI_OSD_MAJOR, oud->minor), "%s", disk->disk_name);
+	if (IS_ERR(oud->class_member)) {
+		OSD_ERR("class_device_create failed\n");
+		error = PTR_ERR(oud->class_member);
+		goto err_put_cdev;
+	}
+
+	dev_set_drvdata(oud->class_member, oud);
+	error = sysfs_create_link(&scsi_dev->sdev_gendev.kobj,
+				  &oud->class_member->kobj, osd_symlink);
+	if (error)
+		OSD_ERR("warning: unable to make symlink\n");
+
+	OSD_INFO("osd_probe %s\n", disk->disk_name);
+	return 0;
+
+err_put_cdev:
+	cdev_del(&oud->cdev);
+err_put_disk:
+	scsi_device_put(scsi_dev);
+	put_disk(disk);
+err_free_osd:
+	dev_set_drvdata(dev, NULL);
+	kfree(oud);
+err_retract_minor:
+	ida_remove(&osd_minor_ida, minor);
+	return error;
+}
+
+static int osd_remove(struct device *dev)
+{
+	struct scsi_device *scsi_dev = to_scsi_device(dev);
+	struct osd_uld_device *oud = dev_get_drvdata(dev);
+
+	if (!oud || (oud->od.scsi_dev != scsi_dev)) {
+		OSD_ERR("Half cooked osd-device %p,%p || %p!=%p",
+			dev, oud, oud ? oud->od.scsi_dev : NULL,
+			scsi_dev);
+	}
+
+	sysfs_remove_link(&oud->od.scsi_dev->sdev_gendev.kobj, osd_symlink);
+
+	if (oud->class_member)
+		device_destroy(osd_sysfs_class,
+			       MKDEV(SCSI_OSD_MAJOR, oud->minor));
+
+	/* We have 2 references to the cdev. One is released here
+	 * and also takes down the /dev/osdX mapping. The second
+	 * Will be released in __remove() after all users have released
+	 * the osd_uld_device.
+	 */
+	if (oud->cdev.owner)
+		cdev_del(&oud->cdev);
+
+	__uld_put(oud);
+	return 0;
+}
+
+static void __remove(struct kref *kref)
+{
+	struct osd_uld_device *oud = container_of(kref,
+					struct osd_uld_device, kref);
+	struct scsi_device *scsi_dev = oud->od.scsi_dev;
+
+	/* now let delete the char_dev */
+	kobject_put(&oud->cdev.kobj);
+
+	osd_dev_fini(&oud->od);
+	scsi_device_put(scsi_dev);
+
+	OSD_INFO("osd_remove %s\n",
+		 oud->disk ? oud->disk->disk_name : NULL);
+
+	if (oud->disk)
+		put_disk(oud->disk);
+
+	ida_remove(&osd_minor_ida, oud->minor);
+	kfree(oud);
+}
+
+static void __uld_get(struct osd_uld_device *oud)
+{
+	kref_get(&oud->kref);
+}
+
+static void __uld_put(struct osd_uld_device *oud)
+{
+	kref_put(&oud->kref, __remove);
+}
+
+/*
+ * Global driver and scsi registration
+ */
+
+static struct scsi_driver osd_driver = {
+	.owner			= THIS_MODULE,
+	.gendrv = {
+		.name		= osd_name,
+		.probe		= osd_probe,
+		.remove		= osd_remove,
+	}
+};
+
+static int __init osd_uld_init(void)
+{
+	int err;
+
+	osd_sysfs_class = class_create(THIS_MODULE, osd_symlink);
+	if (IS_ERR(osd_sysfs_class)) {
+		OSD_ERR("Unable to register sysfs class => %ld\n",
+			PTR_ERR(osd_sysfs_class));
+		return PTR_ERR(osd_sysfs_class);
+	}
+
+	err = register_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0),
+				     SCSI_OSD_MAX_MINOR, osd_name);
+	if (err) {
+		OSD_ERR("Unable to register major %d for osd ULD => %d\n",
+			SCSI_OSD_MAJOR, err);
+		goto err_out;
+	}
+
+	err = scsi_register_driver(&osd_driver.gendrv);
+	if (err) {
+		OSD_ERR("scsi_register_driver failed => %d\n", err);
+		goto err_out_chrdev;
+	}
+
+	OSD_INFO("LOADED %s\n", osd_version_string);
+	return 0;
+
+err_out_chrdev:
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+err_out:
+	class_destroy(osd_sysfs_class);
+	return err;
+}
+
+static void __exit osd_uld_exit(void)
+{
+	scsi_unregister_driver(&osd_driver.gendrv);
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+	class_destroy(osd_sysfs_class);
+	OSD_INFO("UNLOADED %s\n", osd_version_string);
+}
+
+module_init(osd_uld_init);
+module_exit(osd_uld_exit);
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Kernel clients like osdfs can retrieve struct osd_dev(s)
by means of below API.

+ osduld_path_lookup() - given a path (e.g "/dev/osd0") locks and
returns the corresponding struct osd_dev, which is then needed
for subsequent libosd use.

+ osduld_put_device() - free up use of an osd_dev.

Devices can be shared by multiple clients. The osd_uld_device's
life time is governed by an embedded kref structure.

The osd_uld_device holds an extra reference to both it's
char-device and it's scsi_device, and will release these just
before the final deallocation.

There are three possible lock sources of the osd_uld_device
1. First and for most is the probe() function called by
  scsi-ml upon a successful login into a target. Released in release()
  when logout.
2. Second by user-mode file handles opened on the char-dev.
3. Third is here by Kernel users.
All three locks must be removed before the osd_uld_device is freed.

The MODULE has three lock sources as well:
1. scsi-ml at probe() time, removed after release(). (login/logout)
2. The user-mode file handles open/close.
3. Import symbols by client modules like osdfs.

TODO:
  This API is not enough for the pNFS-objects LD. A more versatile
  API will be needed. Proposed API could be:
  struct osd_dev *osduld_sysid_lookup(const char id[OSD_SYSTEMID_LEN]);

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/osd/osd_uld.c   |   52 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_initiator.h |    5 ++++
 2 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 87b4540..0229301 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -42,6 +42,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <linux/namei.h>
 #include <linux/cdev.h>
 #include <linux/fs.h>
 #include <linux/module.h>
@@ -142,6 +143,57 @@ static const struct file_operations osd_fops = {
 	.unlocked_ioctl = osd_uld_ioctl,
 };
 
+struct osd_dev *osduld_path_lookup(const char *path)
+{
+	struct nameidata nd;
+	struct inode *inode;
+	struct cdev *cdev;
+	struct osd_uld_device *oud;
+	int error;
+
+	if (!path || !*path)
+		return ERR_PTR(-EINVAL);
+
+	error = path_lookup(path, LOOKUP_FOLLOW, &nd);
+	if (error)
+		return ERR_PTR(error);
+
+	inode = nd.path.dentry->d_inode;
+	error = -EINVAL; /* Not the right device e.g osd_uld_device */
+	if (!S_ISCHR(inode->i_mode))
+		goto out;
+
+	cdev = inode->i_cdev;
+	if (!cdev)
+		goto out;
+
+	/* The Magic wand. Is it our char-dev */
+	/* TODO: Support sg devices */
+	if (cdev->owner != THIS_MODULE)
+		goto out;
+
+	oud = container_of(cdev, struct osd_uld_device, cdev);
+
+	__uld_get(oud);
+	error = 0;
+
+out:
+	path_put(&nd.path);
+	return error ? ERR_PTR(error) : &oud->od;
+}
+EXPORT_SYMBOL(osduld_path_lookup);
+
+void osduld_put_device(struct osd_dev *od)
+{
+	if (od) {
+		struct osd_uld_device *oud = container_of(od,
+						struct osd_uld_device, od);
+
+		__uld_put(oud);
+	}
+}
+EXPORT_SYMBOL(osduld_put_device);
+
 /*
  * Scsi Device operations
  */
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 24a70b7..0004df1 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -33,6 +33,11 @@ struct osd_dev {
 	unsigned def_timeout;
 };
 
+/* Retrieve/return osd_dev(s) for use by Kernel clients */
+struct osd_dev *osduld_path_lookup(const char *dev_name); /*Use IS_ERR/ERR_PTR*/
+void osduld_put_device(struct osd_dev *od);
+
+/* These are called by uld at probe time */
 void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
 void osd_dev_fini(struct osd_dev *);
 
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Kernel clients like osdfs can retrieve struct osd_dev(s)
by means of below API.

+ osduld_path_lookup() - given a path (e.g "/dev/osd0") locks and
returns the corresponding struct osd_dev, which is then needed
for subsequent libosd use.

+ osduld_put_device() - free up use of an osd_dev.

Devices can be shared by multiple clients. The osd_uld_device's
life time is governed by an embedded kref structure.

The osd_uld_device holds an extra reference to both it's
char-device and it's scsi_device, and will release these just
before the final deallocation.

There are three possible lock sources of the osd_uld_device
1. First and for most is the probe() function called by
  scsi-ml upon a successful login into a target. Released in release()
  when logout.
2. Second by user-mode file handles opened on the char-dev.
3. Third is here by Kernel users.
All three locks must be removed before the osd_uld_device is freed.

The MODULE has three lock sources as well:
1. scsi-ml at probe() time, removed after release(). (login/logout)
2. The user-mode file handles open/close.
3. Import symbols by client modules like osdfs.

TODO:
  This API is not enough for the pNFS-objects LD. A more versatile
  API will be needed. Proposed API could be:
  struct osd_dev *osduld_sysid_lookup(const char id[OSD_SYSTEMID_LEN]);

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/osd/osd_uld.c   |   52 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_initiator.h |    5 ++++
 2 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 87b4540..0229301 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -42,6 +42,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <linux/namei.h>
 #include <linux/cdev.h>
 #include <linux/fs.h>
 #include <linux/module.h>
@@ -142,6 +143,57 @@ static const struct file_operations osd_fops = {
 	.unlocked_ioctl = osd_uld_ioctl,
 };
 
+struct osd_dev *osduld_path_lookup(const char *path)
+{
+	struct nameidata nd;
+	struct inode *inode;
+	struct cdev *cdev;
+	struct osd_uld_device *oud;
+	int error;
+
+	if (!path || !*path)
+		return ERR_PTR(-EINVAL);
+
+	error = path_lookup(path, LOOKUP_FOLLOW, &nd);
+	if (error)
+		return ERR_PTR(error);
+
+	inode = nd.path.dentry->d_inode;
+	error = -EINVAL; /* Not the right device e.g osd_uld_device */
+	if (!S_ISCHR(inode->i_mode))
+		goto out;
+
+	cdev = inode->i_cdev;
+	if (!cdev)
+		goto out;
+
+	/* The Magic wand. Is it our char-dev */
+	/* TODO: Support sg devices */
+	if (cdev->owner != THIS_MODULE)
+		goto out;
+
+	oud = container_of(cdev, struct osd_uld_device, cdev);
+
+	__uld_get(oud);
+	error = 0;
+
+out:
+	path_put(&nd.path);
+	return error ? ERR_PTR(error) : &oud->od;
+}
+EXPORT_SYMBOL(osduld_path_lookup);
+
+void osduld_put_device(struct osd_dev *od)
+{
+	if (od) {
+		struct osd_uld_device *oud = container_of(od,
+						struct osd_uld_device, od);
+
+		__uld_put(oud);
+	}
+}
+EXPORT_SYMBOL(osduld_put_device);
+
 /*
  * Scsi Device operations
  */
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 24a70b7..0004df1 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -33,6 +33,11 @@ struct osd_dev {
 	unsigned def_timeout;
 };
 
+/* Retrieve/return osd_dev(s) for use by Kernel clients */
+struct osd_dev *osduld_path_lookup(const char *dev_name); /*Use IS_ERR/ERR_PTR*/
+void osduld_put_device(struct osd_dev *od);
+
+/* These are called by uld at probe time */
 void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
 void osd_dev_fini(struct osd_dev *);
 
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 07/18] osd_test: User-mode application to run the OSD tests
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Most simple user-app to invoke the in-kernel test ioctl of the
specified osd device.

Usage: osd_test "/dev/osdX"

Where /dev/osdX is the osd device (lun) to run tests on. The output
of the tests is in dmesg log file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/osd/Makefile   |   10 +++++-
 drivers/scsi/osd/osd_test.c |   74 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+), 2 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_test.c

diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile
index d905344..92d8b19 100755
--- a/drivers/scsi/osd/Makefile
+++ b/drivers/scsi/osd/Makefile
@@ -28,10 +28,16 @@ V ?= 0
 # this is the basic Kbuild out-of-tree invocation, with the M= option
 KBUILD_BASE = +$(MAKE) -C $(KSRC) M=`pwd` KBUILD_OUTPUT=$(KBUILD_OUTPUT) ARCH=$(ARCH) V=$(V)
 
-all: libosd
+all: libosd osd_test
 
 libosd: ;
 	$(KBUILD_BASE) OSD_INC=$(OSD_INC) modules
 
-clean:
+clean: osd_test_clean
 	$(KBUILD_BASE) clean
+
+osd_test: osd_test.o
+	$(CC) -o $@ $<
+
+osd_test_clean:
+	rm -vf osd_test
diff --git a/drivers/scsi/osd/osd_test.c b/drivers/scsi/osd/osd_test.c
new file mode 100644
index 0000000..dc74865
--- /dev/null
+++ b/drivers/scsi/osd/osd_test.c
@@ -0,0 +1,74 @@
+/*
+ * osd_test.c - A user-mode program that calls into the osd ULD
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "osd_ktests.h"
+
+void usage(void)
+{
+	printf("usage: osd_test /dev/osdX testNo\n");
+}
+
+int main(int argc, char *argv[])
+{
+	int osd_file, ret;
+
+	if (argc <= 1) {
+		usage();
+		return -2;
+	}
+
+	osd_file = open(argv[1], O_RDWR);
+	if (osd_file < 0) {
+		printf("Error opening <%s>\n", argv[1]);
+		return -3;
+	}
+
+	ret = ioctl(osd_file, OSD_TEST_ALL, 0);
+	if (ret) {
+		printf("ioctl 17 returned %d\n", ret);
+		return ret;
+	}
+
+	close(osd_file);
+	return 0;
+}
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 07/18] osd_test: User-mode application to run the OSD tests
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Most simple user-app to invoke the in-kernel test ioctl of the
specified osd device.

Usage: osd_test "/dev/osdX"

Where /dev/osdX is the osd device (lun) to run tests on. The output
of the tests is in dmesg log file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/osd/Makefile   |   10 +++++-
 drivers/scsi/osd/osd_test.c |   74 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+), 2 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_test.c

diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile
index d905344..92d8b19 100755
--- a/drivers/scsi/osd/Makefile
+++ b/drivers/scsi/osd/Makefile
@@ -28,10 +28,16 @@ V ?= 0
 # this is the basic Kbuild out-of-tree invocation, with the M= option
 KBUILD_BASE = +$(MAKE) -C $(KSRC) M=`pwd` KBUILD_OUTPUT=$(KBUILD_OUTPUT) ARCH=$(ARCH) V=$(V)
 
-all: libosd
+all: libosd osd_test
 
 libosd: ;
 	$(KBUILD_BASE) OSD_INC=$(OSD_INC) modules
 
-clean:
+clean: osd_test_clean
 	$(KBUILD_BASE) clean
+
+osd_test: osd_test.o
+	$(CC) -o $@ $<
+
+osd_test_clean:
+	rm -vf osd_test
diff --git a/drivers/scsi/osd/osd_test.c b/drivers/scsi/osd/osd_test.c
new file mode 100644
index 0000000..dc74865
--- /dev/null
+++ b/drivers/scsi/osd/osd_test.c
@@ -0,0 +1,74 @@
+/*
+ * osd_test.c - A user-mode program that calls into the osd ULD
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "osd_ktests.h"
+
+void usage(void)
+{
+	printf("usage: osd_test /dev/osdX testNo\n");
+}
+
+int main(int argc, char *argv[])
+{
+	int osd_file, ret;
+
+	if (argc <= 1) {
+		usage();
+		return -2;
+	}
+
+	osd_file = open(argv[1], O_RDWR);
+	if (osd_file < 0) {
+		printf("Error opening <%s>\n", argv[1]);
+		return -3;
+	}
+
+	ret = ioctl(osd_file, OSD_TEST_ALL, 0);
+	if (ret) {
+		printf("ioctl 17 returned %d\n", ret);
+		return ret;
+	}
+
+	close(osd_file);
+	return 0;
+}
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 08/18] osd_ktests: Add basic OSD tests
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Currently testing what is implemented in the osd_initiator library.
That is - format, create/remove partition, create/remove object,
read and write to objects.

This test passes against the IBM-OSD-SIM OSDv1 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild       |    2 +-
 drivers/scsi/osd/osd_ktests.c |  331 +++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/osd/osd_ktests.h |    4 +
 drivers/scsi/osd/osd_uld.c    |    2 +-
 4 files changed, 337 insertions(+), 2 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_ktests.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index f39f82f..da00ddb 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -29,5 +29,5 @@ libosd-objs := osd_initiator.o
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
 
 # osd.ko - SCSI ULD and char-device
-osd-objs := osd_uld.o
+osd-objs := osd_uld.o osd_ktests.o
 obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
new file mode 100644
index 0000000..f620915
--- /dev/null
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -0,0 +1,331 @@
+/*
+ * osd_ktests.c - An osd_initiator library in-kernel test suite
+ *              called by the osd_uld module
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <asm/unaligned.h>
+#include <linux/vmalloc.h>
+#include <scsi/scsi_device.h>
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+
+#include "osd_ktests.h"
+#include "osd_debug.h"
+
+enum {
+	K = 1024,
+	M = 1024 * K,
+	G = 1024 * M,
+};
+
+const u64 format_total_capacity = 128 * M;
+const osd_id first_par_id = 0x17171717L;
+const osd_id first_obj_id = 0x18181818L;
+const unsigned BUFF_SIZE = PAGE_SIZE;
+
+const int num_partitions = 1;
+const int num_objects = 2; /* per partition */
+
+int test_exec(struct osd_request *or, void *caps, const struct osd_obj_id *obj)
+{
+	int ret;
+
+	osd_sec_init_nosec_doall_caps(caps, obj, false, true);
+	ret = osd_finalize_request(or, 0, caps, NULL);
+	if (ret)
+		return ret;
+
+	ret = osd_execute_request(or);
+	/* osd_req_decode_sense(or, ret); */
+	return ret;
+}
+
+#define KTEST_START_REQ(osd_dev, or) do { \
+	or = osd_start_request(osd_dev, GFP_KERNEL); \
+	if (!or) { \
+		OSD_ERR("Error @%s:%d: osd_start_request", __func__,\
+			__LINE__); \
+		return -ENOMEM; \
+	} \
+} while (0)
+
+#define KTEST_EXEC_END(or, obj, g_caps, msg) do { \
+	ret = test_exec(or, g_caps, obj); \
+	osd_end_request(or); \
+	if (ret) { \
+		OSD_ERR("Error executing "msg" => %d\n", ret); \
+		return ret; \
+	} \
+	OSD_DEBUG(msg "\n"); \
+} while (0)
+
+int ktest_format(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+
+	KTEST_START_REQ(osd_dev, or);
+	osd_req_format(or, format_total_capacity);
+	KTEST_EXEC_END(or, &osd_root_object, g_caps, "format");
+	return 0;
+}
+
+int ktest_creat_par(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p;
+
+	for (p = 0; p < num_partitions; p++) {
+		struct osd_obj_id par = {
+			.partition = first_par_id + p,
+			.id = 0
+		};
+
+		KTEST_START_REQ(osd_dev, or);
+		osd_req_create_partition(or, par.partition);
+		KTEST_EXEC_END(or, &par, g_caps, "create_partition");
+	}
+
+	return 0;
+}
+
+int ktest_creat_obj(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			osd_req_create_object(or, &obj);
+			KTEST_EXEC_END(or, &obj, g_caps, "create_object");
+		}
+
+	return 0;
+}
+
+int ktest_write_obj(struct osd_dev *osd_dev, void *write_buff)
+{
+	struct request_queue *req_q = osd_dev->scsi_dev->request_queue;
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o; u64 offset = 0;
+	struct bio *write_bio;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			write_bio = bio_map_kern(req_q, write_buff,
+						 BUFF_SIZE, GFP_KERNEL);
+			if (!write_bio) {
+				OSD_ERR("!!! Failed to allocate write BIO\n");
+				return -ENOMEM;
+			}
+
+			osd_req_write(or, &obj, write_bio, offset);
+			KTEST_EXEC_END(or, &obj, g_caps, "write");
+			write_bio = NULL; /* released by scsi_midlayer */
+			offset += BUFF_SIZE;
+		}
+
+	return 0;
+}
+
+int ktest_read_obj(struct osd_dev *osd_dev, void *write_buff, void *read_buff)
+{
+	struct request_queue *req_q = osd_dev->scsi_dev->request_queue;
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o; u64 offset = 0;
+	struct bio *read_bio;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			read_bio = bio_map_kern(req_q, read_buff,
+						BUFF_SIZE, GFP_KERNEL);
+			if (!read_bio) {
+				OSD_ERR("!!! Failed to allocate read BIO\n");
+				return -ENOMEM;
+			}
+
+			osd_req_read(or, &obj, read_bio, offset);
+			KTEST_EXEC_END(or, &obj, g_caps, "read");
+			read_bio = NULL;
+			if (memcmp(read_buff, write_buff, BUFF_SIZE))
+				OSD_ERR("!!! Read did not compare");
+			offset += BUFF_SIZE;
+		}
+
+	return 0;
+}
+
+int ktest_remove_obj(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			osd_req_remove_object(or, &obj);
+			KTEST_EXEC_END(or, &obj, g_caps, "remove_object");
+		}
+
+	return 0;
+}
+
+int ktest_remove_par(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p;
+
+	for (p = 0; p < num_partitions; p++) {
+		struct osd_obj_id par = {
+			.partition = first_par_id + p,
+			.id = 0
+		};
+
+		KTEST_START_REQ(osd_dev, or);
+		osd_req_remove_partition(or, par.partition);
+		KTEST_EXEC_END(or, &par, g_caps, "remove_partition");
+	}
+
+	return 0;
+}
+
+int do_test_17(struct osd_dev *od)
+{
+	void *write_buff = NULL;
+	void *read_buff = NULL;
+	int ret = -ENOMEM, i;
+
+/* osd_format */
+	if (ktest_format(od))
+		goto dev_fini;
+
+/* create some partition */
+	if (ktest_creat_par(od))
+		goto dev_fini;
+/* list partition see if they're all there */
+/* create some objects on some partitions */
+	if (ktest_creat_obj(od))
+		goto dev_fini;
+
+/* Alloc some buffers and bios */
+/*	write_buff = kmalloc(BUFF_SIZE, or->alloc_flags);*/
+/*	read_buff = kmalloc(BUFF_SIZE, or->alloc_flags);*/
+	write_buff = (void *)__get_free_page(GFP_KERNEL);
+	read_buff = (void *)__get_free_page(GFP_KERNEL);
+	if (!write_buff || !read_buff) {
+		OSD_ERR("!!! Failed to allocate memory for test\n");
+		goto dev_fini;
+	}
+	for (i = 0; i < BUFF_SIZE / 4; i++)
+		((int *)write_buff)[i] = i;
+	OSD_DEBUG("allocate buffers\n");
+
+/* write to objects */
+	ret = ktest_write_obj(od, write_buff);
+	if (ret)
+		goto dev_fini;
+
+/* read from objects and compare to write */
+	ret = ktest_read_obj(od, write_buff, read_buff);
+	if (ret)
+		goto dev_fini;
+
+/* List all objects */
+
+/* Write with get_attr */
+/* Write with set_attr */
+/* Write with set_attr + get_attr */
+/* Read with set_attr */
+/* Read with get_attr */
+/* Read with get_attr + set_attr */
+/* remove objects */
+	ret = ktest_remove_obj(od);
+	if (ret)
+		goto dev_fini;
+
+/* remove partitions */
+	ret = ktest_remove_par(od);
+	if (ret)
+		goto dev_fini;
+
+/* good and done */
+	OSD_INFO("test17: All good and done\n");
+dev_fini:
+	if (read_buff)
+		free_page((ulong)read_buff);
+	if (write_buff)
+		free_page((ulong)write_buff);
+
+	return ret;
+}
diff --git a/drivers/scsi/osd/osd_ktests.h b/drivers/scsi/osd/osd_ktests.h
index a9e5e00..b625ee5 100644
--- a/drivers/scsi/osd/osd_ktests.h
+++ b/drivers/scsi/osd/osd_ktests.h
@@ -24,4 +24,8 @@
 
 enum { OSD_TEST_ALL = 17 };
 
+#ifdef __KERNEL__
+extern int do_test_17(struct osd_dev *od);
+#endif /* __KERNEL__ */
+
 #endif /*ndef __OSD_KTESTS_H__*/
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 0229301..1ce5eba 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -127,7 +127,7 @@ static long osd_uld_ioctl(struct file *file, unsigned int cmd,
 	switch (cmd) {
 	case OSD_TEST_ALL:
 		OSD_DEBUG("Kernel test %d: osd_uld_device=%p\n", cmd, oud);
-		ret = 0;
+		ret = do_test_17(&oud->od);
 		break;
 	default:
 		OSD_ERR("Unknown osd_uld_ioctl %d\n", cmd);
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 08/18] osd_ktests: Add basic OSD tests
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Currently testing what is implemented in the osd_initiator library.
That is - format, create/remove partition, create/remove object,
read and write to objects.

This test passes against the IBM-OSD-SIM OSDv1 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild       |    2 +-
 drivers/scsi/osd/osd_ktests.c |  331 +++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/osd/osd_ktests.h |    4 +
 drivers/scsi/osd/osd_uld.c    |    2 +-
 4 files changed, 337 insertions(+), 2 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_ktests.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index f39f82f..da00ddb 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -29,5 +29,5 @@ libosd-objs := osd_initiator.o
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
 
 # osd.ko - SCSI ULD and char-device
-osd-objs := osd_uld.o
+osd-objs := osd_uld.o osd_ktests.o
 obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
new file mode 100644
index 0000000..f620915
--- /dev/null
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -0,0 +1,331 @@
+/*
+ * osd_ktests.c - An osd_initiator library in-kernel test suite
+ *              called by the osd_uld module
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <asm/unaligned.h>
+#include <linux/vmalloc.h>
+#include <scsi/scsi_device.h>
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+
+#include "osd_ktests.h"
+#include "osd_debug.h"
+
+enum {
+	K = 1024,
+	M = 1024 * K,
+	G = 1024 * M,
+};
+
+const u64 format_total_capacity = 128 * M;
+const osd_id first_par_id = 0x17171717L;
+const osd_id first_obj_id = 0x18181818L;
+const unsigned BUFF_SIZE = PAGE_SIZE;
+
+const int num_partitions = 1;
+const int num_objects = 2; /* per partition */
+
+int test_exec(struct osd_request *or, void *caps, const struct osd_obj_id *obj)
+{
+	int ret;
+
+	osd_sec_init_nosec_doall_caps(caps, obj, false, true);
+	ret = osd_finalize_request(or, 0, caps, NULL);
+	if (ret)
+		return ret;
+
+	ret = osd_execute_request(or);
+	/* osd_req_decode_sense(or, ret); */
+	return ret;
+}
+
+#define KTEST_START_REQ(osd_dev, or) do { \
+	or = osd_start_request(osd_dev, GFP_KERNEL); \
+	if (!or) { \
+		OSD_ERR("Error @%s:%d: osd_start_request", __func__,\
+			__LINE__); \
+		return -ENOMEM; \
+	} \
+} while (0)
+
+#define KTEST_EXEC_END(or, obj, g_caps, msg) do { \
+	ret = test_exec(or, g_caps, obj); \
+	osd_end_request(or); \
+	if (ret) { \
+		OSD_ERR("Error executing "msg" => %d\n", ret); \
+		return ret; \
+	} \
+	OSD_DEBUG(msg "\n"); \
+} while (0)
+
+int ktest_format(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+
+	KTEST_START_REQ(osd_dev, or);
+	osd_req_format(or, format_total_capacity);
+	KTEST_EXEC_END(or, &osd_root_object, g_caps, "format");
+	return 0;
+}
+
+int ktest_creat_par(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p;
+
+	for (p = 0; p < num_partitions; p++) {
+		struct osd_obj_id par = {
+			.partition = first_par_id + p,
+			.id = 0
+		};
+
+		KTEST_START_REQ(osd_dev, or);
+		osd_req_create_partition(or, par.partition);
+		KTEST_EXEC_END(or, &par, g_caps, "create_partition");
+	}
+
+	return 0;
+}
+
+int ktest_creat_obj(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			osd_req_create_object(or, &obj);
+			KTEST_EXEC_END(or, &obj, g_caps, "create_object");
+		}
+
+	return 0;
+}
+
+int ktest_write_obj(struct osd_dev *osd_dev, void *write_buff)
+{
+	struct request_queue *req_q = osd_dev->scsi_dev->request_queue;
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o; u64 offset = 0;
+	struct bio *write_bio;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			write_bio = bio_map_kern(req_q, write_buff,
+						 BUFF_SIZE, GFP_KERNEL);
+			if (!write_bio) {
+				OSD_ERR("!!! Failed to allocate write BIO\n");
+				return -ENOMEM;
+			}
+
+			osd_req_write(or, &obj, write_bio, offset);
+			KTEST_EXEC_END(or, &obj, g_caps, "write");
+			write_bio = NULL; /* released by scsi_midlayer */
+			offset += BUFF_SIZE;
+		}
+
+	return 0;
+}
+
+int ktest_read_obj(struct osd_dev *osd_dev, void *write_buff, void *read_buff)
+{
+	struct request_queue *req_q = osd_dev->scsi_dev->request_queue;
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o; u64 offset = 0;
+	struct bio *read_bio;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			read_bio = bio_map_kern(req_q, read_buff,
+						BUFF_SIZE, GFP_KERNEL);
+			if (!read_bio) {
+				OSD_ERR("!!! Failed to allocate read BIO\n");
+				return -ENOMEM;
+			}
+
+			osd_req_read(or, &obj, read_bio, offset);
+			KTEST_EXEC_END(or, &obj, g_caps, "read");
+			read_bio = NULL;
+			if (memcmp(read_buff, write_buff, BUFF_SIZE))
+				OSD_ERR("!!! Read did not compare");
+			offset += BUFF_SIZE;
+		}
+
+	return 0;
+}
+
+int ktest_remove_obj(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			osd_req_remove_object(or, &obj);
+			KTEST_EXEC_END(or, &obj, g_caps, "remove_object");
+		}
+
+	return 0;
+}
+
+int ktest_remove_par(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p;
+
+	for (p = 0; p < num_partitions; p++) {
+		struct osd_obj_id par = {
+			.partition = first_par_id + p,
+			.id = 0
+		};
+
+		KTEST_START_REQ(osd_dev, or);
+		osd_req_remove_partition(or, par.partition);
+		KTEST_EXEC_END(or, &par, g_caps, "remove_partition");
+	}
+
+	return 0;
+}
+
+int do_test_17(struct osd_dev *od)
+{
+	void *write_buff = NULL;
+	void *read_buff = NULL;
+	int ret = -ENOMEM, i;
+
+/* osd_format */
+	if (ktest_format(od))
+		goto dev_fini;
+
+/* create some partition */
+	if (ktest_creat_par(od))
+		goto dev_fini;
+/* list partition see if they're all there */
+/* create some objects on some partitions */
+	if (ktest_creat_obj(od))
+		goto dev_fini;
+
+/* Alloc some buffers and bios */
+/*	write_buff = kmalloc(BUFF_SIZE, or->alloc_flags);*/
+/*	read_buff = kmalloc(BUFF_SIZE, or->alloc_flags);*/
+	write_buff = (void *)__get_free_page(GFP_KERNEL);
+	read_buff = (void *)__get_free_page(GFP_KERNEL);
+	if (!write_buff || !read_buff) {
+		OSD_ERR("!!! Failed to allocate memory for test\n");
+		goto dev_fini;
+	}
+	for (i = 0; i < BUFF_SIZE / 4; i++)
+		((int *)write_buff)[i] = i;
+	OSD_DEBUG("allocate buffers\n");
+
+/* write to objects */
+	ret = ktest_write_obj(od, write_buff);
+	if (ret)
+		goto dev_fini;
+
+/* read from objects and compare to write */
+	ret = ktest_read_obj(od, write_buff, read_buff);
+	if (ret)
+		goto dev_fini;
+
+/* List all objects */
+
+/* Write with get_attr */
+/* Write with set_attr */
+/* Write with set_attr + get_attr */
+/* Read with set_attr */
+/* Read with get_attr */
+/* Read with get_attr + set_attr */
+/* remove objects */
+	ret = ktest_remove_obj(od);
+	if (ret)
+		goto dev_fini;
+
+/* remove partitions */
+	ret = ktest_remove_par(od);
+	if (ret)
+		goto dev_fini;
+
+/* good and done */
+	OSD_INFO("test17: All good and done\n");
+dev_fini:
+	if (read_buff)
+		free_page((ulong)read_buff);
+	if (write_buff)
+		free_page((ulong)write_buff);
+
+	return ret;
+}
diff --git a/drivers/scsi/osd/osd_ktests.h b/drivers/scsi/osd/osd_ktests.h
index a9e5e00..b625ee5 100644
--- a/drivers/scsi/osd/osd_ktests.h
+++ b/drivers/scsi/osd/osd_ktests.h
@@ -24,4 +24,8 @@
 
 enum { OSD_TEST_ALL = 17 };
 
+#ifdef __KERNEL__
+extern int do_test_17(struct osd_dev *od);
+#endif /* __KERNEL__ */
+
 #endif /*ndef __OSD_KTESTS_H__*/
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 0229301..1ce5eba 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -127,7 +127,7 @@ static long osd_uld_ioctl(struct file *file, unsigned int cmd,
 	switch (cmd) {
 	case OSD_TEST_ALL:
 		OSD_DEBUG("Kernel test %d: osd_uld_device=%p\n", cmd, oud);
-		ret = 0;
+		ret = do_test_17(&oud->od);
 		break;
 	default:
 		OSD_ERR("Unknown osd_uld_ioctl %d\n", cmd);
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 09/18] libosd: attributes Support
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Support for both List-Mode and Page-Mode osd attributes. One of
these operations may be added to most other operations.

Define the OSD standard's attribute pages constants and structures
(osd_attributes.h)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  573 ++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_attributes.h    |  327 ++++++++++++++++++++++
 2 files changed, 900 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_attributes.h

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 33450b8..da0c53c 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -65,6 +65,50 @@ static unsigned _osd_req_cdb_len(struct osd_request *or)
 	return OSDv1_TOTAL_CDB_LEN;
 }
 
+static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
+{
+	return osdv1_attr_list_elem_size(len);
+}
+
+static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
+{
+	return osdv1_list_size(list_head);
+}
+
+static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
+{
+	return sizeof(struct osdv1_attributes_list_header);
+}
+
+static void _osd_req_set_alist_type(struct osd_request *or,
+	void *list, int list_type)
+{
+	struct osdv1_attributes_list_header *attr_list = list;
+
+	memset(attr_list, 0, sizeof(*attr_list));
+	attr_list->type = list_type;
+}
+
+static bool _osd_req_is_alist_type(struct osd_request *or,
+	void *list, int list_type)
+{
+	if (!list)
+		return false;
+
+	if (1) {
+		struct osdv1_attributes_list_header *attr_list = list;
+
+		return attr_list->type == list_type;
+	}
+}
+
+static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
+	u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
 {
 	memset(osdd, 0, sizeof(*osdd));
@@ -127,10 +171,25 @@ static void _abort_unexecuted_bios(struct request *rq)
 	}
 }
 
+static void _osd_free_seg(struct osd_request *or,
+	struct _osd_req_data_segment *seg)
+{
+	if (!seg->buff || !seg->alloc_size)
+		return;
+
+	kfree(seg->buff);
+	seg->buff = NULL;
+	seg->alloc_size = 0;
+}
+
 void osd_end_request(struct osd_request *or)
 {
 	struct request *rq = or->request;
 
+	_osd_free_seg(or, &or->set_attr);
+	_osd_free_seg(or, &or->enc_get_attr);
+	_osd_free_seg(or, &or->get_attr);
+
 	if (rq) {
 		if (rq->next_rq) {
 			_abort_unexecuted_bios(rq->next_rq);
@@ -178,6 +237,54 @@ int osd_execute_request_async(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_execute_request_async);
 
+u8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+u8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+
+static int _osd_realloc_seg(struct osd_request *or,
+	struct _osd_req_data_segment *seg, unsigned max_bytes)
+{
+	void *buff;
+
+	if (seg->alloc_size >= max_bytes)
+		return 0;
+
+	buff = krealloc(seg->buff, max_bytes, or->alloc_flags);
+	if (!buff) {
+		OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes,
+			seg->alloc_size);
+		return -ENOMEM;
+	}
+
+	memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size);
+	seg->buff = buff;
+	seg->alloc_size = max_bytes;
+	return 0;
+}
+
+static int _alloc_set_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem, unsigned add_bytes)
+{
+	unsigned total_bytes = add_bytes;
+
+	for (; nelem; --nelem, ++oa)
+		total_bytes += _osd_req_alist_elem_size(or, oa->len);
+
+	OSD_DEBUG("total_bytes=%d\n", total_bytes);
+	return _osd_realloc_seg(or, &or->set_attr, total_bytes);
+}
+
+static int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes)
+{
+	OSD_DEBUG("total_bytes=%d\n", max_bytes);
+	return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes);
+}
+
+static int _alloc_get_attr_list(struct osd_request *or)
+{
+	OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes);
+	return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes);
+}
+
 /*
  * Common to all OSD commands
  */
@@ -286,6 +393,409 @@ void osd_req_read(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_read);
 
+void osd_req_get_attributes(struct osd_request *or,
+	const struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_get_attributes);
+
+void osd_req_set_attributes(struct osd_request *or,
+	const struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_set_attributes);
+
+/*
+ * Attributes List-mode
+ */
+
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem)
+{
+	unsigned total_bytes = or->set_attr.total_bytes;
+	void *attr_last;
+	int ret;
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+	if (!total_bytes) { /* first-time: allocate and put list header */
+		total_bytes = _osd_req_sizeof_alist_header(or);
+		ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+		if (ret)
+			return ret;
+		_osd_req_set_alist_type(or, or->set_attr.buff,
+					OSD_ATTR_LIST_SET_RETRIEVE);
+	}
+	attr_last = or->set_attr.buff + total_bytes;
+
+	for (; nelem; --nelem) {
+		struct osd_attributes_list_element *attr;
+		unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
+
+		total_bytes += elem_size;
+		if (unlikely(or->set_attr.alloc_size < total_bytes)) {
+			or->set_attr.total_bytes = total_bytes - elem_size;
+			ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+			if (ret)
+				return ret;
+			attr_last =
+				or->set_attr.buff + or->set_attr.total_bytes;
+		}
+
+		attr = attr_last;
+		attr->page = cpu_to_be32(oa->page);
+		attr->attr_id = cpu_to_be32(oa->attr_id);
+		attr->attr_bytes = cpu_to_be16(oa->len);
+		memcpy(attr->attr_val, oa->val_ptr, oa->len);
+
+		attr_last += elem_size;
+		++oa;
+	}
+
+	or->set_attr.total_bytes = total_bytes;
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_set_attr_list);
+
+static int _append_map_kern(struct request *req,
+	void *buff, unsigned len, gfp_t flags)
+{
+	struct bio *bio;
+	int ret;
+
+	bio = bio_map_kern(req->q, buff, len, flags);
+	if (IS_ERR(bio)) {
+		OSD_ERR("Failed bio_map_kern(%p, %d) => %ld\n", buff, len,
+			PTR_ERR(bio));
+		return PTR_ERR(bio);
+	}
+	ret = blk_rq_append_bio(req->q, req, bio);
+	if (ret) {
+		OSD_ERR("Failed blk_rq_append_bio(%p) => %d\n", bio, ret);
+		bio_put(bio);
+	}
+	return ret;
+}
+
+static int _req_append_segment(struct osd_request *or,
+	int padding, struct _osd_req_data_segment *seg,
+	struct _osd_req_data_segment *last_seg, struct _osd_io_info *io)
+{
+	void *pad_buff;
+	int ret;
+
+	if (padding) {
+		/* check if we can just add it to last buffer */
+		if (last_seg &&
+		    (padding <= last_seg->alloc_size - last_seg->total_bytes))
+			pad_buff = last_seg->buff + last_seg->total_bytes;
+		else
+			pad_buff = io->pad_buff;
+
+		ret = _append_map_kern(io->req, pad_buff, padding,
+				       or->alloc_flags);
+		if (ret)
+			return ret;
+		io->total_bytes += padding;
+	}
+
+	ret = _append_map_kern(io->req, seg->buff, seg->total_bytes,
+			       or->alloc_flags);
+	if (ret)
+		return ret;
+
+	io->total_bytes += seg->total_bytes;
+	OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff,
+		  seg->total_bytes);
+	return 0;
+}
+
+static int _osd_req_finalize_set_attr_list(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	int padding;
+	int ret;
+
+	if (!or->set_attr.total_bytes) {
+		cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED;
+		return 0;
+	}
+
+	cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes);
+	cdbh->attrs_list.set_attr_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &padding);
+
+	ret = _req_append_segment(or, padding, &or->set_attr,
+				  or->out.last_seg, &or->out);
+	if (ret)
+		return ret;
+
+	or->out.last_seg = &or->set_attr;
+	return 0;
+}
+
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem)
+{
+	unsigned total_bytes = or->enc_get_attr.total_bytes;
+	void *attr_last;
+	int ret;
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+	/* first time calc data-in list header size */
+	if (!or->get_attr.total_bytes)
+		or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or);
+
+	/* calc data-out info */
+	if (!total_bytes) { /* first-time: allocate and put list header */
+		unsigned max_bytes;
+
+		total_bytes = _osd_req_sizeof_alist_header(or);
+		max_bytes = total_bytes +
+			nelem * sizeof(struct osd_attributes_list_attrid);
+		ret = _alloc_get_attr_desc(or, max_bytes);
+		if (ret)
+			return ret;
+
+		_osd_req_set_alist_type(or, or->enc_get_attr.buff,
+					OSD_ATTR_LIST_GET);
+	}
+	attr_last = or->enc_get_attr.buff + total_bytes;
+
+	for (; nelem; --nelem) {
+		struct osd_attributes_list_attrid *attrid;
+		const unsigned cur_size = sizeof(*attrid);
+
+		total_bytes += cur_size;
+		if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) {
+			or->enc_get_attr.total_bytes = total_bytes - cur_size;
+			ret = _alloc_get_attr_desc(or,
+					total_bytes + nelem * sizeof(*attrid));
+			if (ret)
+				return ret;
+			attr_last = or->enc_get_attr.buff +
+				or->enc_get_attr.total_bytes;
+		}
+
+		attrid = attr_last;
+		attrid->page = cpu_to_be32(oa->page);
+		attrid->attr_id = cpu_to_be32(oa->attr_id);
+
+		attr_last += cur_size;
+
+		/* calc data-in size */
+		or->get_attr.total_bytes +=
+			_osd_req_alist_elem_size(or, oa->len);
+		++oa;
+	}
+
+	or->enc_get_attr.total_bytes = total_bytes;
+
+	OSD_DEBUG(
+	       "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n",
+	       or->get_attr.total_bytes,
+	       or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or),
+	       or->enc_get_attr.total_bytes,
+	       (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or))
+			/ sizeof(struct osd_attributes_list_attrid));
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_list);
+
+static int _osd_req_finalize_get_attr_list(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	unsigned out_padding;
+	unsigned in_padding;
+	int ret;
+
+	if (!or->enc_get_attr.total_bytes) {
+		cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED;
+		cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED;
+		return 0;
+	}
+
+	ret = _alloc_get_attr_list(or);
+	if (ret)
+		return ret;
+
+	/* The out-going buffer info update */
+	OSD_DEBUG("out-going\n");
+	cdbh->attrs_list.get_attr_desc_bytes =
+		cpu_to_be32(or->enc_get_attr.total_bytes);
+
+	cdbh->attrs_list.get_attr_desc_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+	ret = _req_append_segment(or, out_padding, &or->enc_get_attr,
+				  or->out.last_seg, &or->out);
+	if (ret)
+		return ret;
+	or->out.last_seg = &or->enc_get_attr;
+
+	/* The incoming buffer info update */
+	OSD_DEBUG("in-coming\n");
+	cdbh->attrs_list.get_attr_alloc_length =
+		cpu_to_be32(or->get_attr.total_bytes);
+
+	cdbh->attrs_list.get_attr_offset =
+		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+				  &or->in);
+	if (ret)
+		return ret;
+	or->in.last_seg = &or->get_attr;
+
+	return 0;
+}
+
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *oa, int *nelem, void **iterator)
+{
+	unsigned cur_bytes, returned_bytes, n;
+	const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or);
+	void *cur_p;
+
+	if (!_osd_req_is_alist_type(or, or->get_attr.buff,
+				    OSD_ATTR_LIST_SET_RETRIEVE)) {
+		oa->page = 0;
+		oa->attr_id = 0;
+		oa->val_ptr = NULL;
+		oa->len = 0;
+		*iterator = NULL;
+		return 0;
+	}
+
+	if (*iterator) {
+		BUG_ON((*iterator < or->get_attr.buff) ||
+		     (or->get_attr.buff + or->get_attr.alloc_size < *iterator));
+		cur_p = *iterator;
+		cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list;
+		returned_bytes = or->get_attr.total_bytes;
+	} else { /* first time decode the list header */
+		cur_bytes = sizeof_attr_list;
+		returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) +
+					sizeof_attr_list;
+
+		cur_p = or->get_attr.buff + sizeof_attr_list;
+
+		if (returned_bytes > or->get_attr.alloc_size) {
+			OSD_DEBUG("target report: space was not big enough! "
+				  "Allocate=%u Needed=%u\n",
+				  or->get_attr.alloc_size,
+				  returned_bytes + sizeof_attr_list);
+
+			returned_bytes =
+				or->get_attr.alloc_size - sizeof_attr_list;
+		}
+		or->get_attr.total_bytes = returned_bytes;
+	}
+
+	for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
+		struct osd_attributes_list_element *attr = cur_p;
+		unsigned inc;
+
+		oa->len = be16_to_cpu(attr->attr_bytes);
+		inc = _osd_req_alist_elem_size(or, oa->len);
+		OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n",
+			  oa->len, inc, cur_bytes);
+		cur_bytes += inc;
+		if (cur_bytes > returned_bytes) {
+			OSD_ERR("BAD FOOD from target. list not valid!"
+				"c=%d r=%d n=%d\n",
+				cur_bytes, returned_bytes, n);
+			oa->val_ptr = NULL;
+			break;
+		}
+
+		oa->page = be32_to_cpu(attr->page);
+		oa->attr_id = be32_to_cpu(attr->attr_id);
+		oa->val_ptr = attr->attr_val;
+
+		cur_p += inc;
+		++oa;
+	}
+
+	*iterator = (returned_bytes - cur_bytes) ? cur_p : NULL;
+	*nelem = n;
+	return returned_bytes - cur_bytes;
+}
+EXPORT_SYMBOL(osd_req_decode_get_attr_list);
+
+/*
+ * Attributes Page-mode
+ */
+
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attar_page, unsigned max_page_len,
+	const struct osd_attr *set_one_attr)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE;
+
+	or->get_attr.buff = attar_page;
+	or->get_attr.total_bytes = max_page_len;
+
+	or->set_attr.buff = set_one_attr->val_ptr;
+	or->set_attr.total_bytes = set_one_attr->len;
+
+	cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id);
+	cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len);
+	/* ocdb->attrs_page.get_attr_offset; */
+
+	cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->page);
+	cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id);
+	cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len);
+	/* ocdb->attrs_page.set_attr_offset; */
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_page);
+
+int _osd_req_finalize_attr_page(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	int in_padding, out_padding;
+	int ret;
+
+	/* returned page */
+	cdbh->attrs_page.get_attr_offset =
+		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+				  &or->in);
+	if (ret)
+		return ret;
+
+	/* set one value */
+	cdbh->attrs_page.set_attr_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+	ret = _req_append_segment(or, out_padding, &or->enc_get_attr, NULL,
+				  &or->out);
+	return ret;
+}
+
 /*
  * osd_finalize_request and helpers
  */
@@ -380,9 +890,31 @@ int osd_finalize_request(struct osd_request *or,
 			or->in.total_bytes, or->in.req->data_len);
 	}
 
+	or->out.pad_buff = sg_out_pad_buffer;
+	or->in.pad_buff = sg_in_pad_buffer;
+
 	if (!or->attributes_mode)
 		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
 	cdbh->command_specific_options |= or->attributes_mode;
+	if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+		ret = _osd_req_finalize_attr_page(or);
+	} else {
+		/* TODO: I think that for the GET_ATTR command these 2 should
+		 * be reversed to keep them in execution order (for embeded
+		 * targets with low memory footprint)
+		 */
+		ret = _osd_req_finalize_set_attr_list(or);
+		if (ret) {
+			OSD_DEBUG("_osd_req_finalize_set_attr_list failed\n");
+			return ret;
+		}
+
+		ret = _osd_req_finalize_get_attr_list(or);
+		if (ret) {
+			OSD_DEBUG("_osd_req_finalize_get_attr_list failed\n");
+			return ret;
+		}
+	}
 
 	or->request->cmd = or->cdb.buff;
 	or->request->cmd_len = _osd_req_cdb_len(or);
@@ -448,3 +980,44 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 {
 	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
 }
+
+/*
+ * Declared in osd_protocol.h
+ * 4.12.5 Data-In and Data-Out buffer offsets
+ * byte offset = mantissa * (2^(exponent+8))
+ * Returns the smallest allowed encoded offset that contains given @offset
+ * The actual encoded offset returned is @offset + *@padding.
+ */
+osd_cdb_offset __osd_encode_offset(
+	u64 offset, unsigned *padding, int min_shift, int max_shift)
+{
+	u64 try_offset = -1, mod, align;
+	osd_cdb_offset be32_offset;
+	int shift;
+
+	*padding = 0;
+	if (!offset)
+		return 0;
+
+	for (shift = min_shift; shift < max_shift; ++shift) {
+		try_offset = offset >> shift;
+		if (try_offset < (1 << OSD_OFFSET_MAX_BITS))
+			break;
+	}
+
+	BUG_ON(shift == max_shift);
+
+	align = 1 << shift;
+	mod = offset & (align - 1);
+	if (mod) {
+		*padding = align - mod;
+		try_offset += 1;
+	}
+
+	try_offset |= ((shift - 8) & 0xf) << 28;
+	be32_offset = cpu_to_be32((u32)try_offset);
+
+	OSD_DEBUG("offset=%lld mantissa=%lld exp=%d encoded=%x pad=%d\n",
+		 offset, try_offset & 0x0FFFFFFF, shift, be32_offset, *padding);
+	return be32_offset;
+}
diff --git a/include/scsi/osd_attributes.h b/include/scsi/osd_attributes.h
new file mode 100644
index 0000000..c53f49b
--- /dev/null
+++ b/include/scsi/osd_attributes.h
@@ -0,0 +1,327 @@
+#ifndef __OSD_ATTRIBUTES_H__
+#define __OSD_ATTRIBUTES_H__
+
+#include "osd_protocol.h"
+
+/*
+ * Contains types and constants that define attribute pages and attribute
+ * numbers and their data types.
+ */
+
+#define ATTR_SET(pg, id, l, ptr) \
+	{ .page = pg, .attr_id = id, .len = l, .val_ptr = ptr }
+
+#define ATTR_DEF(pg, id, l) ATTR_SET(pg, id, l, NULL)
+
+/* osd-r10 4.7.3 Attributes pages */
+enum {
+	OSD_APAGE_OBJECT_FIRST		= 0x0,
+	OSD_APAGE_OBJECT_DIRECTORY	= 0,
+	OSD_APAGE_OBJECT_INFORMATION	= 1,
+	OSD_APAGE_OBJECT_QUOTAS		= 2,
+	OSD_APAGE_OBJECT_TIMESTAMP	= 3,
+	OSD_APAGE_OBJECT_COLLECTIONS	= 4,
+	OSD_APAGE_OBJECT_SECURITY	= 5,
+	OSD_APAGE_OBJECT_LAST		= 0x2fffffff,
+
+	OSD_APAGE_PARTITION_FIRST	= 0x30000000,
+	OSD_APAGE_PARTITION_DIRECTORY	= OSD_APAGE_PARTITION_FIRST + 0,
+	OSD_APAGE_PARTITION_INFORMATION = OSD_APAGE_PARTITION_FIRST + 1,
+	OSD_APAGE_PARTITION_QUOTAS	= OSD_APAGE_PARTITION_FIRST + 2,
+	OSD_APAGE_PARTITION_TIMESTAMP	= OSD_APAGE_PARTITION_FIRST + 3,
+	OSD_APAGE_PARTITION_SECURITY	= OSD_APAGE_PARTITION_FIRST + 5,
+	OSD_APAGE_PARTITION_LAST	= 0x5FFFFFFF,
+
+	OSD_APAGE_COLLECTION_FIRST	= 0x60000000,
+	OSD_APAGE_COLLECTION_DIRECTORY	= OSD_APAGE_COLLECTION_FIRST + 0,
+	OSD_APAGE_COLLECTION_INFORMATION = OSD_APAGE_COLLECTION_FIRST + 1,
+	OSD_APAGE_COLLECTION_TIMESTAMP	= OSD_APAGE_COLLECTION_FIRST + 3,
+	OSD_APAGE_COLLECTION_SECURITY	= OSD_APAGE_COLLECTION_FIRST + 5,
+	OSD_APAGE_COLLECTION_LAST	= 0x8FFFFFFF,
+
+	OSD_APAGE_ROOT_FIRST		= 0x90000000,
+	OSD_APAGE_ROOT_DIRECTORY	= OSD_APAGE_ROOT_FIRST + 0,
+	OSD_APAGE_ROOT_INFORMATION	= OSD_APAGE_ROOT_FIRST + 1,
+	OSD_APAGE_ROOT_QUOTAS		= OSD_APAGE_ROOT_FIRST + 2,
+	OSD_APAGE_ROOT_TIMESTAMP	= OSD_APAGE_ROOT_FIRST + 3,
+	OSD_APAGE_ROOT_SECURITY		= OSD_APAGE_ROOT_FIRST + 5,
+	OSD_APAGE_ROOT_LAST		= 0xBFFFFFFF,
+
+	OSD_APAGE_RESERVED_TYPE_FIRST	= 0xC0000000,
+	OSD_APAGE_RESERVED_TYPE_LAST	= 0xEFFFFFFF,
+
+	OSD_APAGE_COMMON_FIRST		= 0xF0000000,
+	OSD_APAGE_COMMON_LAST		= 0xFFFFFFFE,
+
+	OSD_APAGE_REQUEST_ALL		= 0xFFFFFFFF,
+};
+
+/* subcategories of attr pages within each range above */
+enum {
+	OSD_APAGE_STD_FIRST		= 0x0,
+	OSD_APAGE_STD_DIRECTORY		= 0,
+	OSD_APAGE_STD_INFORMATION	= 1,
+	OSD_APAGE_STD_QUOTAS		= 2,
+	OSD_APAGE_STD_TIMESTAMP		= 3,
+	OSD_APAGE_STD_COLLECTIONS	= 4,
+	OSD_APAGE_STD_POLICY_SECURITY	= 5,
+	OSD_APAGE_STD_LAST		= 0x0000007F,
+
+	OSD_APAGE_RESERVED_FIRST	= 0x00000080,
+	OSD_APAGE_RESERVED_LAST		= 0x00007FFF,
+
+	OSD_APAGE_OTHER_STD_FIRST	= 0x00008000,
+	OSD_APAGE_OTHER_STD_LAST	= 0x0000EFFF,
+
+	OSD_APAGE_PUBLIC_FIRST		= 0x0000F000,
+	OSD_APAGE_PUBLIC_LAST		= 0x0000FFFF,
+
+	OSD_APAGE_APP_DEFINED_FIRST	= 0x00010000,
+	OSD_APAGE_APP_DEFINED_LAST	= 0x1FFFFFFF,
+
+	OSD_APAGE_VENDOR_SPECIFIC_FIRST	= 0x20000000,
+	OSD_APAGE_VENDOR_SPECIFIC_LAST	= 0x2FFFFFFF,
+};
+
+enum {
+	OSD_ATTR_PAGE_IDENTIFICATION = 0, /* in all pages 40 bytes */
+};
+
+struct page_identification {
+	u8 vendor_identification[8];
+	u8 page_identification[32];
+}  __packed;
+
+struct osd_attr_page_header {
+	__be32 page_number;
+	__be32 page_length;
+} __packed;
+
+/* 7.1.2.8 Root Information attributes page (OSD_APAGE_ROOT_INFORMATION) */
+enum {
+	OSD_ATTR_RI_OSD_SYSTEM_ID            = 0x3,   /* 20       */
+	OSD_ATTR_RI_VENDOR_IDENTIFICATION    = 0x4,   /* 8        */
+	OSD_ATTR_RI_PRODUCT_IDENTIFICATION   = 0x5,   /* 16       */
+	OSD_ATTR_RI_PRODUCT_MODEL            = 0x6,   /* 32       */
+	OSD_ATTR_RI_PRODUCT_REVISION_LEVEL   = 0x7,   /* 4        */
+	OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER    = 0x8,   /* variable */
+	OSD_ATTR_RI_OSD_NAME                 = 0x9,   /* variable */
+	OSD_ATTR_RI_TOTAL_CAPACITY           = 0x80,  /* 8        */
+	OSD_ATTR_RI_USED_CAPACITY            = 0x81,  /* 8        */
+	OSD_ATTR_RI_NUMBER_OF_PARTITIONS     = 0xC0,  /* 8        */
+	OSD_ATTR_RI_CLOCK                    = 0x100, /* 6        */
+};
+/* Root_Information_attributes_page does not have a get_page structure */
+
+/* 7.1.2.9 Partition Information attributes page
+ * (OSD_APAGE_PARTITION_INFORMATION)
+ */
+enum {
+	OSD_ATTR_PI_PARTITION_ID            = 0x1,     /* 8        */
+	OSD_ATTR_PI_USERNAME                = 0x9,     /* variable */
+	OSD_ATTR_PI_USED_CAPACITY           = 0x81,    /* 8        */
+	OSD_ATTR_PI_NUMBER_OF_OBJECTS       = 0xC1,    /* 8        */
+};
+/* Partition Information attributes page does not have a get_page structure */
+
+/* 7.1.2.10 Collection Information attributes page
+ * (OSD_APAGE_COLLECTION_INFORMATION)
+ */
+enum {
+	OSD_ATTR_CI_PARTITION_ID           = 0x1,       /* 8        */
+	OSD_ATTR_CI_COLLECTION_OBJECT_ID   = 0x2,       /* 8        */
+	OSD_ATTR_CI_USERNAME               = 0x9,       /* variable */
+	OSD_ATTR_CI_USED_CAPACITY          = 0x81,      /* 8        */
+};
+/* Collection Information attributes page does not have a get_page structure */
+
+/* 7.1.2.11 User Object Information attributes page
+ * (OSD_APAGE_OBJECT_INFORMATION)
+ */
+enum {
+	OSD_ATTR_OI_PARTITION_ID         = 0x1,       /* 8        */
+	OSD_ATTR_OI_OBJECT_ID            = 0x2,       /* 8        */
+	OSD_ATTR_OI_USERNAME             = 0x9,       /* variable */
+	OSD_ATTR_OI_USED_CAPACITY        = 0x81,      /* 8        */
+	OSD_ATTR_OI_LOGICAL_LENGTH       = 0x82,      /* 8        */
+};
+/* Object Information attributes page does not have a get_page structure */
+
+/* 7.1.2.12 Root Quotas attributes page (OSD_APAGE_ROOT_QUOTAS) */
+enum {
+	OSD_ATTR_RQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH     = 0x1,      /* 8  */
+	OSD_ATTR_RQ_PARTITION_CAPACITY_QUOTA               = 0x10001,  /* 8  */
+	OSD_ATTR_RQ_PARTITION_OBJECT_COUNT                 = 0x10002,  /* 8  */
+	OSD_ATTR_RQ_PARTITION_COLLECTIONS_PER_USER_OBJECT  = 0x10081,  /* 4  */
+	OSD_ATTR_RQ_PARTITION_COUNT                        = 0x20002,  /* 8  */
+};
+
+struct Root_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+2, size=0x24 */
+	__be64 default_maximum_user_object_length;
+	__be64 partition_capacity_quota;
+	__be64 partition_object_count;
+	__be64 partition_collections_per_user_object;
+	__be64 partition_count;
+}  __packed;
+
+/* 7.1.2.13 Partition Quotas attributes page (OSD_APAGE_PARTITION_QUOTAS)*/
+enum {
+	OSD_ATTR_PQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH  = 0x1,        /* 8 */
+	OSD_ATTR_PQ_CAPACITY_QUOTA                      = 0x10001,    /* 8 */
+	OSD_ATTR_PQ_OBJECT_COUNT                        = 0x10002,    /* 8 */
+	OSD_ATTR_PQ_COLLECTIONS_PER_USER_OBJECT         = 0x10081,    /* 4 */
+};
+
+struct Partition_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=P+2, size=0x1C */
+	__be64 default_maximum_user_object_length;
+	__be64 capacity_quota;
+	__be64 object_count;
+	__be64 collections_per_user_object;
+}  __packed;
+
+/* 7.1.2.14 User Object Quotas attributes page (OSD_APAGE_OBJECT_QUOTAS) */
+enum {
+	OSD_ATTR_OQ_MAXIMUM_LENGTH  = 0x1,        /* 8 */
+};
+
+struct Object_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=U+2, size=0x8 */
+	__be64 maximum_length;
+}  __packed;
+
+/* 7.1.2.15 Root Timestamps attributes page (OSD_APAGE_ROOT_TIMESTAMP) */
+enum {
+	OSD_ATTR_RT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_RT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_RT_TIMESTAMP_BYPASS          = 0xFFFFFFFE, /* 1 */
+};
+
+struct root_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+3, size=0xD */
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	u8 timestamp_bypass;
+}  __packed;
+
+/* 7.1.2.16 Partition Timestamps attributes page
+ * (OSD_APAGE_PARTITION_TIMESTAMP)
+ */
+enum {
+	OSD_ATTR_PT_CREATED_TIME              = 0x1,        /* 6 */
+	OSD_ATTR_PT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_PT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_PT_DATA_ACCESSED_TIME        = 0x4,        /* 6 */
+	OSD_ATTR_PT_DATA_MODIFIED_TIME        = 0x5,        /* 6 */
+	OSD_ATTR_PT_TIMESTAMP_BYPASS          = 0xFFFFFFFE, /* 1 */
+};
+
+struct partition_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=P+3, size=0x1F */
+	struct osd_timestamp created_time;
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	struct osd_timestamp data_accessed_time;
+	struct osd_timestamp data_modified_time;
+	u8 timestamp_bypass;
+}  __packed;
+
+/* 7.1.2.17/18 Collection/Object Timestamps attributes page
+ * (OSD_APAGE_COLLECTION_TIMESTAMP/OSD_APAGE_OBJECT_TIMESTAMP)
+ */
+enum {
+	OSD_ATTR_OT_CREATED_TIME              = 0x1,        /* 6 */
+	OSD_ATTR_OT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_OT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_OT_DATA_ACCESSED_TIME        = 0x4,        /* 6 */
+	OSD_ATTR_OT_DATA_MODIFIED_TIME        = 0x5,        /* 6 */
+};
+
+/* same for collection */
+struct object_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=C+3/3, size=0x1E */
+	struct osd_timestamp created_time;
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	struct osd_timestamp data_accessed_time;
+	struct osd_timestamp data_modified_time;
+}  __packed;
+
+/* 7.1.2.19 Collections attributes page */
+/* TBD */
+
+/* 7.1.2.20 Root Policy/Security attributes page (OSD_APAGE_ROOT_SECURITY) */
+enum {
+	OSD_ATTR_RS_DEFAULT_SECURITY_METHOD           = 0x1,       /* 1      */
+	OSD_ATTR_RS_OLDEST_VALID_NONCE_LIMIT          = 0x2,       /* 6      */
+	OSD_ATTR_RS_NEWEST_VALID_NONCE_LIMIT          = 0x3,       /* 6      */
+	OSD_ATTR_RS_PARTITION_DEFAULT_SECURITY_METHOD = 0x6,       /* 1      */
+	OSD_ATTR_RS_SUPPORTED_SECURITY_METHODS        = 0x7,       /* 2      */
+	OSD_ATTR_RS_ADJUSTABLE_CLOCK                  = 0x9,       /* 6      */
+	OSD_ATTR_RS_MASTER_KEY_IDENTIFIER             = 0x7FFD,    /* 0 or 7 */
+	OSD_ATTR_RS_ROOT_KEY_IDENTIFIER               = 0x7FFE,    /* 0 or 7 */
+	OSD_ATTR_RS_SUPPORTED_INTEGRITY_ALGORITHM_0   = 0x80000000,/* 1,(x16)*/
+	OSD_ATTR_RS_SUPPORTED_DH_GROUP_0              = 0x80000010,/* 1,(x16)*/
+};
+
+struct root_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+5, size=0x3F */
+	u8 default_security_method;
+	u8 partition_default_security_method;
+	__be16 supported_security_methods;
+	u8 mki_valid_rki_valid;
+	struct osd_timestamp oldest_valid_nonce_limit;
+	struct osd_timestamp newest_valid_nonce_limit;
+	struct osd_timestamp adjustable_clock;
+	u8 master_key_identifier[32-25];
+	u8 root_key_identifier[39-32];
+	u8 supported_integrity_algorithm[16];
+	u8 supported_dh_group[16];
+}  __packed;
+
+/* 7.1.2.21 Partition Policy/Security attributes page
+ * (OSD_APAGE_PARTITION_SECURITY)
+ */
+enum {
+	OSD_ATTR_PS_DEFAULT_SECURITY_METHOD        = 0x1,        /* 1      */
+	OSD_ATTR_PS_OLDEST_VALID_NONCE             = 0x2,        /* 6      */
+	OSD_ATTR_PS_NEWEST_VALID_NONCE             = 0x3,        /* 6      */
+	OSD_ATTR_PS_REQUEST_NONCE_LIST_DEPTH       = 0x4,        /* 2      */
+	OSD_ATTR_PS_FROZEN_WORKING_KEY_BIT_MASK    = 0x5,        /* 2      */
+	OSD_ATTR_PS_PARTITION_KEY_IDENTIFIER       = 0x7FFF,     /* 0 or 7 */
+	OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_FIRST   = 0x8000,     /* 0 or 7 */
+	OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_LAST    = 0x800F,     /* 0 or 7 */
+	OSD_ATTR_PS_POLICY_ACCESS_TAG              = 0x40000001, /* 4      */
+	OSD_ATTR_PS_USER_OBJECT_POLICY_ACCESS_TAG  = 0x40000002, /* 4      */
+};
+
+struct partition_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=p+5, size=0x8f */
+	u8 reserved[3];
+	u8 default_security_method;
+	struct osd_timestamp oldest_valid_nonce;
+	struct osd_timestamp newest_valid_nonce;
+	__be16 request_nonce_list_depth;
+	__be16 frozen_working_key_bit_mask;
+	__be32 policy_access_tag;
+	__be32 user_object_policy_access_tag;
+	u8 pki_valid;
+	__be16 wki_00_0f_vld;
+	struct osd_key_identifier partition_key_identifier;
+	struct osd_key_identifier working_key_identifiers[16];
+}  __packed;
+
+/* 7.1.2.22/23 Collection/Object Policy-Security attributes page
+ * (OSD_APAGE_COLLECTION_SECURITY/OSD_APAGE_OBJECT_SECURITY)
+ */
+enum {
+	OSD_ATTR_OS_POLICY_ACCESS_TAG              = 0x40000001, /* 4      */
+};
+
+struct object_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=C+5/5, size=4 */
+	__be32 policy_access_tag;
+}  __packed;
+
+#endif /*ndef __OSD_ATTRIBUTES_H__*/
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 09/18] libosd: attributes Support
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Support for both List-Mode and Page-Mode osd attributes. One of
these operations may be added to most other operations.

Define the OSD standard's attribute pages constants and structures
(osd_attributes.h)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  573 ++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_attributes.h    |  327 ++++++++++++++++++++++
 2 files changed, 900 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_attributes.h

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 33450b8..da0c53c 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -65,6 +65,50 @@ static unsigned _osd_req_cdb_len(struct osd_request *or)
 	return OSDv1_TOTAL_CDB_LEN;
 }
 
+static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
+{
+	return osdv1_attr_list_elem_size(len);
+}
+
+static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
+{
+	return osdv1_list_size(list_head);
+}
+
+static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
+{
+	return sizeof(struct osdv1_attributes_list_header);
+}
+
+static void _osd_req_set_alist_type(struct osd_request *or,
+	void *list, int list_type)
+{
+	struct osdv1_attributes_list_header *attr_list = list;
+
+	memset(attr_list, 0, sizeof(*attr_list));
+	attr_list->type = list_type;
+}
+
+static bool _osd_req_is_alist_type(struct osd_request *or,
+	void *list, int list_type)
+{
+	if (!list)
+		return false;
+
+	if (1) {
+		struct osdv1_attributes_list_header *attr_list = list;
+
+		return attr_list->type == list_type;
+	}
+}
+
+static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
+	u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
 {
 	memset(osdd, 0, sizeof(*osdd));
@@ -127,10 +171,25 @@ static void _abort_unexecuted_bios(struct request *rq)
 	}
 }
 
+static void _osd_free_seg(struct osd_request *or,
+	struct _osd_req_data_segment *seg)
+{
+	if (!seg->buff || !seg->alloc_size)
+		return;
+
+	kfree(seg->buff);
+	seg->buff = NULL;
+	seg->alloc_size = 0;
+}
+
 void osd_end_request(struct osd_request *or)
 {
 	struct request *rq = or->request;
 
+	_osd_free_seg(or, &or->set_attr);
+	_osd_free_seg(or, &or->enc_get_attr);
+	_osd_free_seg(or, &or->get_attr);
+
 	if (rq) {
 		if (rq->next_rq) {
 			_abort_unexecuted_bios(rq->next_rq);
@@ -178,6 +237,54 @@ int osd_execute_request_async(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_execute_request_async);
 
+u8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+u8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+
+static int _osd_realloc_seg(struct osd_request *or,
+	struct _osd_req_data_segment *seg, unsigned max_bytes)
+{
+	void *buff;
+
+	if (seg->alloc_size >= max_bytes)
+		return 0;
+
+	buff = krealloc(seg->buff, max_bytes, or->alloc_flags);
+	if (!buff) {
+		OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes,
+			seg->alloc_size);
+		return -ENOMEM;
+	}
+
+	memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size);
+	seg->buff = buff;
+	seg->alloc_size = max_bytes;
+	return 0;
+}
+
+static int _alloc_set_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem, unsigned add_bytes)
+{
+	unsigned total_bytes = add_bytes;
+
+	for (; nelem; --nelem, ++oa)
+		total_bytes += _osd_req_alist_elem_size(or, oa->len);
+
+	OSD_DEBUG("total_bytes=%d\n", total_bytes);
+	return _osd_realloc_seg(or, &or->set_attr, total_bytes);
+}
+
+static int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes)
+{
+	OSD_DEBUG("total_bytes=%d\n", max_bytes);
+	return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes);
+}
+
+static int _alloc_get_attr_list(struct osd_request *or)
+{
+	OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes);
+	return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes);
+}
+
 /*
  * Common to all OSD commands
  */
@@ -286,6 +393,409 @@ void osd_req_read(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_read);
 
+void osd_req_get_attributes(struct osd_request *or,
+	const struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_get_attributes);
+
+void osd_req_set_attributes(struct osd_request *or,
+	const struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_set_attributes);
+
+/*
+ * Attributes List-mode
+ */
+
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem)
+{
+	unsigned total_bytes = or->set_attr.total_bytes;
+	void *attr_last;
+	int ret;
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+	if (!total_bytes) { /* first-time: allocate and put list header */
+		total_bytes = _osd_req_sizeof_alist_header(or);
+		ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+		if (ret)
+			return ret;
+		_osd_req_set_alist_type(or, or->set_attr.buff,
+					OSD_ATTR_LIST_SET_RETRIEVE);
+	}
+	attr_last = or->set_attr.buff + total_bytes;
+
+	for (; nelem; --nelem) {
+		struct osd_attributes_list_element *attr;
+		unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
+
+		total_bytes += elem_size;
+		if (unlikely(or->set_attr.alloc_size < total_bytes)) {
+			or->set_attr.total_bytes = total_bytes - elem_size;
+			ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+			if (ret)
+				return ret;
+			attr_last =
+				or->set_attr.buff + or->set_attr.total_bytes;
+		}
+
+		attr = attr_last;
+		attr->page = cpu_to_be32(oa->page);
+		attr->attr_id = cpu_to_be32(oa->attr_id);
+		attr->attr_bytes = cpu_to_be16(oa->len);
+		memcpy(attr->attr_val, oa->val_ptr, oa->len);
+
+		attr_last += elem_size;
+		++oa;
+	}
+
+	or->set_attr.total_bytes = total_bytes;
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_set_attr_list);
+
+static int _append_map_kern(struct request *req,
+	void *buff, unsigned len, gfp_t flags)
+{
+	struct bio *bio;
+	int ret;
+
+	bio = bio_map_kern(req->q, buff, len, flags);
+	if (IS_ERR(bio)) {
+		OSD_ERR("Failed bio_map_kern(%p, %d) => %ld\n", buff, len,
+			PTR_ERR(bio));
+		return PTR_ERR(bio);
+	}
+	ret = blk_rq_append_bio(req->q, req, bio);
+	if (ret) {
+		OSD_ERR("Failed blk_rq_append_bio(%p) => %d\n", bio, ret);
+		bio_put(bio);
+	}
+	return ret;
+}
+
+static int _req_append_segment(struct osd_request *or,
+	int padding, struct _osd_req_data_segment *seg,
+	struct _osd_req_data_segment *last_seg, struct _osd_io_info *io)
+{
+	void *pad_buff;
+	int ret;
+
+	if (padding) {
+		/* check if we can just add it to last buffer */
+		if (last_seg &&
+		    (padding <= last_seg->alloc_size - last_seg->total_bytes))
+			pad_buff = last_seg->buff + last_seg->total_bytes;
+		else
+			pad_buff = io->pad_buff;
+
+		ret = _append_map_kern(io->req, pad_buff, padding,
+				       or->alloc_flags);
+		if (ret)
+			return ret;
+		io->total_bytes += padding;
+	}
+
+	ret = _append_map_kern(io->req, seg->buff, seg->total_bytes,
+			       or->alloc_flags);
+	if (ret)
+		return ret;
+
+	io->total_bytes += seg->total_bytes;
+	OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff,
+		  seg->total_bytes);
+	return 0;
+}
+
+static int _osd_req_finalize_set_attr_list(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	int padding;
+	int ret;
+
+	if (!or->set_attr.total_bytes) {
+		cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED;
+		return 0;
+	}
+
+	cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes);
+	cdbh->attrs_list.set_attr_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &padding);
+
+	ret = _req_append_segment(or, padding, &or->set_attr,
+				  or->out.last_seg, &or->out);
+	if (ret)
+		return ret;
+
+	or->out.last_seg = &or->set_attr;
+	return 0;
+}
+
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem)
+{
+	unsigned total_bytes = or->enc_get_attr.total_bytes;
+	void *attr_last;
+	int ret;
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+	/* first time calc data-in list header size */
+	if (!or->get_attr.total_bytes)
+		or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or);
+
+	/* calc data-out info */
+	if (!total_bytes) { /* first-time: allocate and put list header */
+		unsigned max_bytes;
+
+		total_bytes = _osd_req_sizeof_alist_header(or);
+		max_bytes = total_bytes +
+			nelem * sizeof(struct osd_attributes_list_attrid);
+		ret = _alloc_get_attr_desc(or, max_bytes);
+		if (ret)
+			return ret;
+
+		_osd_req_set_alist_type(or, or->enc_get_attr.buff,
+					OSD_ATTR_LIST_GET);
+	}
+	attr_last = or->enc_get_attr.buff + total_bytes;
+
+	for (; nelem; --nelem) {
+		struct osd_attributes_list_attrid *attrid;
+		const unsigned cur_size = sizeof(*attrid);
+
+		total_bytes += cur_size;
+		if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) {
+			or->enc_get_attr.total_bytes = total_bytes - cur_size;
+			ret = _alloc_get_attr_desc(or,
+					total_bytes + nelem * sizeof(*attrid));
+			if (ret)
+				return ret;
+			attr_last = or->enc_get_attr.buff +
+				or->enc_get_attr.total_bytes;
+		}
+
+		attrid = attr_last;
+		attrid->page = cpu_to_be32(oa->page);
+		attrid->attr_id = cpu_to_be32(oa->attr_id);
+
+		attr_last += cur_size;
+
+		/* calc data-in size */
+		or->get_attr.total_bytes +=
+			_osd_req_alist_elem_size(or, oa->len);
+		++oa;
+	}
+
+	or->enc_get_attr.total_bytes = total_bytes;
+
+	OSD_DEBUG(
+	       "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n",
+	       or->get_attr.total_bytes,
+	       or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or),
+	       or->enc_get_attr.total_bytes,
+	       (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or))
+			/ sizeof(struct osd_attributes_list_attrid));
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_list);
+
+static int _osd_req_finalize_get_attr_list(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	unsigned out_padding;
+	unsigned in_padding;
+	int ret;
+
+	if (!or->enc_get_attr.total_bytes) {
+		cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED;
+		cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED;
+		return 0;
+	}
+
+	ret = _alloc_get_attr_list(or);
+	if (ret)
+		return ret;
+
+	/* The out-going buffer info update */
+	OSD_DEBUG("out-going\n");
+	cdbh->attrs_list.get_attr_desc_bytes =
+		cpu_to_be32(or->enc_get_attr.total_bytes);
+
+	cdbh->attrs_list.get_attr_desc_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+	ret = _req_append_segment(or, out_padding, &or->enc_get_attr,
+				  or->out.last_seg, &or->out);
+	if (ret)
+		return ret;
+	or->out.last_seg = &or->enc_get_attr;
+
+	/* The incoming buffer info update */
+	OSD_DEBUG("in-coming\n");
+	cdbh->attrs_list.get_attr_alloc_length =
+		cpu_to_be32(or->get_attr.total_bytes);
+
+	cdbh->attrs_list.get_attr_offset =
+		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+				  &or->in);
+	if (ret)
+		return ret;
+	or->in.last_seg = &or->get_attr;
+
+	return 0;
+}
+
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *oa, int *nelem, void **iterator)
+{
+	unsigned cur_bytes, returned_bytes, n;
+	const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or);
+	void *cur_p;
+
+	if (!_osd_req_is_alist_type(or, or->get_attr.buff,
+				    OSD_ATTR_LIST_SET_RETRIEVE)) {
+		oa->page = 0;
+		oa->attr_id = 0;
+		oa->val_ptr = NULL;
+		oa->len = 0;
+		*iterator = NULL;
+		return 0;
+	}
+
+	if (*iterator) {
+		BUG_ON((*iterator < or->get_attr.buff) ||
+		     (or->get_attr.buff + or->get_attr.alloc_size < *iterator));
+		cur_p = *iterator;
+		cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list;
+		returned_bytes = or->get_attr.total_bytes;
+	} else { /* first time decode the list header */
+		cur_bytes = sizeof_attr_list;
+		returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) +
+					sizeof_attr_list;
+
+		cur_p = or->get_attr.buff + sizeof_attr_list;
+
+		if (returned_bytes > or->get_attr.alloc_size) {
+			OSD_DEBUG("target report: space was not big enough! "
+				  "Allocate=%u Needed=%u\n",
+				  or->get_attr.alloc_size,
+				  returned_bytes + sizeof_attr_list);
+
+			returned_bytes =
+				or->get_attr.alloc_size - sizeof_attr_list;
+		}
+		or->get_attr.total_bytes = returned_bytes;
+	}
+
+	for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
+		struct osd_attributes_list_element *attr = cur_p;
+		unsigned inc;
+
+		oa->len = be16_to_cpu(attr->attr_bytes);
+		inc = _osd_req_alist_elem_size(or, oa->len);
+		OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n",
+			  oa->len, inc, cur_bytes);
+		cur_bytes += inc;
+		if (cur_bytes > returned_bytes) {
+			OSD_ERR("BAD FOOD from target. list not valid!"
+				"c=%d r=%d n=%d\n",
+				cur_bytes, returned_bytes, n);
+			oa->val_ptr = NULL;
+			break;
+		}
+
+		oa->page = be32_to_cpu(attr->page);
+		oa->attr_id = be32_to_cpu(attr->attr_id);
+		oa->val_ptr = attr->attr_val;
+
+		cur_p += inc;
+		++oa;
+	}
+
+	*iterator = (returned_bytes - cur_bytes) ? cur_p : NULL;
+	*nelem = n;
+	return returned_bytes - cur_bytes;
+}
+EXPORT_SYMBOL(osd_req_decode_get_attr_list);
+
+/*
+ * Attributes Page-mode
+ */
+
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attar_page, unsigned max_page_len,
+	const struct osd_attr *set_one_attr)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE;
+
+	or->get_attr.buff = attar_page;
+	or->get_attr.total_bytes = max_page_len;
+
+	or->set_attr.buff = set_one_attr->val_ptr;
+	or->set_attr.total_bytes = set_one_attr->len;
+
+	cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id);
+	cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len);
+	/* ocdb->attrs_page.get_attr_offset; */
+
+	cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->page);
+	cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id);
+	cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len);
+	/* ocdb->attrs_page.set_attr_offset; */
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_page);
+
+int _osd_req_finalize_attr_page(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	int in_padding, out_padding;
+	int ret;
+
+	/* returned page */
+	cdbh->attrs_page.get_attr_offset =
+		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+				  &or->in);
+	if (ret)
+		return ret;
+
+	/* set one value */
+	cdbh->attrs_page.set_attr_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+	ret = _req_append_segment(or, out_padding, &or->enc_get_attr, NULL,
+				  &or->out);
+	return ret;
+}
+
 /*
  * osd_finalize_request and helpers
  */
@@ -380,9 +890,31 @@ int osd_finalize_request(struct osd_request *or,
 			or->in.total_bytes, or->in.req->data_len);
 	}
 
+	or->out.pad_buff = sg_out_pad_buffer;
+	or->in.pad_buff = sg_in_pad_buffer;
+
 	if (!or->attributes_mode)
 		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
 	cdbh->command_specific_options |= or->attributes_mode;
+	if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+		ret = _osd_req_finalize_attr_page(or);
+	} else {
+		/* TODO: I think that for the GET_ATTR command these 2 should
+		 * be reversed to keep them in execution order (for embeded
+		 * targets with low memory footprint)
+		 */
+		ret = _osd_req_finalize_set_attr_list(or);
+		if (ret) {
+			OSD_DEBUG("_osd_req_finalize_set_attr_list failed\n");
+			return ret;
+		}
+
+		ret = _osd_req_finalize_get_attr_list(or);
+		if (ret) {
+			OSD_DEBUG("_osd_req_finalize_get_attr_list failed\n");
+			return ret;
+		}
+	}
 
 	or->request->cmd = or->cdb.buff;
 	or->request->cmd_len = _osd_req_cdb_len(or);
@@ -448,3 +980,44 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 {
 	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
 }
+
+/*
+ * Declared in osd_protocol.h
+ * 4.12.5 Data-In and Data-Out buffer offsets
+ * byte offset = mantissa * (2^(exponent+8))
+ * Returns the smallest allowed encoded offset that contains given @offset
+ * The actual encoded offset returned is @offset + *@padding.
+ */
+osd_cdb_offset __osd_encode_offset(
+	u64 offset, unsigned *padding, int min_shift, int max_shift)
+{
+	u64 try_offset = -1, mod, align;
+	osd_cdb_offset be32_offset;
+	int shift;
+
+	*padding = 0;
+	if (!offset)
+		return 0;
+
+	for (shift = min_shift; shift < max_shift; ++shift) {
+		try_offset = offset >> shift;
+		if (try_offset < (1 << OSD_OFFSET_MAX_BITS))
+			break;
+	}
+
+	BUG_ON(shift == max_shift);
+
+	align = 1 << shift;
+	mod = offset & (align - 1);
+	if (mod) {
+		*padding = align - mod;
+		try_offset += 1;
+	}
+
+	try_offset |= ((shift - 8) & 0xf) << 28;
+	be32_offset = cpu_to_be32((u32)try_offset);
+
+	OSD_DEBUG("offset=%lld mantissa=%lld exp=%d encoded=%x pad=%d\n",
+		 offset, try_offset & 0x0FFFFFFF, shift, be32_offset, *padding);
+	return be32_offset;
+}
diff --git a/include/scsi/osd_attributes.h b/include/scsi/osd_attributes.h
new file mode 100644
index 0000000..c53f49b
--- /dev/null
+++ b/include/scsi/osd_attributes.h
@@ -0,0 +1,327 @@
+#ifndef __OSD_ATTRIBUTES_H__
+#define __OSD_ATTRIBUTES_H__
+
+#include "osd_protocol.h"
+
+/*
+ * Contains types and constants that define attribute pages and attribute
+ * numbers and their data types.
+ */
+
+#define ATTR_SET(pg, id, l, ptr) \
+	{ .page = pg, .attr_id = id, .len = l, .val_ptr = ptr }
+
+#define ATTR_DEF(pg, id, l) ATTR_SET(pg, id, l, NULL)
+
+/* osd-r10 4.7.3 Attributes pages */
+enum {
+	OSD_APAGE_OBJECT_FIRST		= 0x0,
+	OSD_APAGE_OBJECT_DIRECTORY	= 0,
+	OSD_APAGE_OBJECT_INFORMATION	= 1,
+	OSD_APAGE_OBJECT_QUOTAS		= 2,
+	OSD_APAGE_OBJECT_TIMESTAMP	= 3,
+	OSD_APAGE_OBJECT_COLLECTIONS	= 4,
+	OSD_APAGE_OBJECT_SECURITY	= 5,
+	OSD_APAGE_OBJECT_LAST		= 0x2fffffff,
+
+	OSD_APAGE_PARTITION_FIRST	= 0x30000000,
+	OSD_APAGE_PARTITION_DIRECTORY	= OSD_APAGE_PARTITION_FIRST + 0,
+	OSD_APAGE_PARTITION_INFORMATION = OSD_APAGE_PARTITION_FIRST + 1,
+	OSD_APAGE_PARTITION_QUOTAS	= OSD_APAGE_PARTITION_FIRST + 2,
+	OSD_APAGE_PARTITION_TIMESTAMP	= OSD_APAGE_PARTITION_FIRST + 3,
+	OSD_APAGE_PARTITION_SECURITY	= OSD_APAGE_PARTITION_FIRST + 5,
+	OSD_APAGE_PARTITION_LAST	= 0x5FFFFFFF,
+
+	OSD_APAGE_COLLECTION_FIRST	= 0x60000000,
+	OSD_APAGE_COLLECTION_DIRECTORY	= OSD_APAGE_COLLECTION_FIRST + 0,
+	OSD_APAGE_COLLECTION_INFORMATION = OSD_APAGE_COLLECTION_FIRST + 1,
+	OSD_APAGE_COLLECTION_TIMESTAMP	= OSD_APAGE_COLLECTION_FIRST + 3,
+	OSD_APAGE_COLLECTION_SECURITY	= OSD_APAGE_COLLECTION_FIRST + 5,
+	OSD_APAGE_COLLECTION_LAST	= 0x8FFFFFFF,
+
+	OSD_APAGE_ROOT_FIRST		= 0x90000000,
+	OSD_APAGE_ROOT_DIRECTORY	= OSD_APAGE_ROOT_FIRST + 0,
+	OSD_APAGE_ROOT_INFORMATION	= OSD_APAGE_ROOT_FIRST + 1,
+	OSD_APAGE_ROOT_QUOTAS		= OSD_APAGE_ROOT_FIRST + 2,
+	OSD_APAGE_ROOT_TIMESTAMP	= OSD_APAGE_ROOT_FIRST + 3,
+	OSD_APAGE_ROOT_SECURITY		= OSD_APAGE_ROOT_FIRST + 5,
+	OSD_APAGE_ROOT_LAST		= 0xBFFFFFFF,
+
+	OSD_APAGE_RESERVED_TYPE_FIRST	= 0xC0000000,
+	OSD_APAGE_RESERVED_TYPE_LAST	= 0xEFFFFFFF,
+
+	OSD_APAGE_COMMON_FIRST		= 0xF0000000,
+	OSD_APAGE_COMMON_LAST		= 0xFFFFFFFE,
+
+	OSD_APAGE_REQUEST_ALL		= 0xFFFFFFFF,
+};
+
+/* subcategories of attr pages within each range above */
+enum {
+	OSD_APAGE_STD_FIRST		= 0x0,
+	OSD_APAGE_STD_DIRECTORY		= 0,
+	OSD_APAGE_STD_INFORMATION	= 1,
+	OSD_APAGE_STD_QUOTAS		= 2,
+	OSD_APAGE_STD_TIMESTAMP		= 3,
+	OSD_APAGE_STD_COLLECTIONS	= 4,
+	OSD_APAGE_STD_POLICY_SECURITY	= 5,
+	OSD_APAGE_STD_LAST		= 0x0000007F,
+
+	OSD_APAGE_RESERVED_FIRST	= 0x00000080,
+	OSD_APAGE_RESERVED_LAST		= 0x00007FFF,
+
+	OSD_APAGE_OTHER_STD_FIRST	= 0x00008000,
+	OSD_APAGE_OTHER_STD_LAST	= 0x0000EFFF,
+
+	OSD_APAGE_PUBLIC_FIRST		= 0x0000F000,
+	OSD_APAGE_PUBLIC_LAST		= 0x0000FFFF,
+
+	OSD_APAGE_APP_DEFINED_FIRST	= 0x00010000,
+	OSD_APAGE_APP_DEFINED_LAST	= 0x1FFFFFFF,
+
+	OSD_APAGE_VENDOR_SPECIFIC_FIRST	= 0x20000000,
+	OSD_APAGE_VENDOR_SPECIFIC_LAST	= 0x2FFFFFFF,
+};
+
+enum {
+	OSD_ATTR_PAGE_IDENTIFICATION = 0, /* in all pages 40 bytes */
+};
+
+struct page_identification {
+	u8 vendor_identification[8];
+	u8 page_identification[32];
+}  __packed;
+
+struct osd_attr_page_header {
+	__be32 page_number;
+	__be32 page_length;
+} __packed;
+
+/* 7.1.2.8 Root Information attributes page (OSD_APAGE_ROOT_INFORMATION) */
+enum {
+	OSD_ATTR_RI_OSD_SYSTEM_ID            = 0x3,   /* 20       */
+	OSD_ATTR_RI_VENDOR_IDENTIFICATION    = 0x4,   /* 8        */
+	OSD_ATTR_RI_PRODUCT_IDENTIFICATION   = 0x5,   /* 16       */
+	OSD_ATTR_RI_PRODUCT_MODEL            = 0x6,   /* 32       */
+	OSD_ATTR_RI_PRODUCT_REVISION_LEVEL   = 0x7,   /* 4        */
+	OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER    = 0x8,   /* variable */
+	OSD_ATTR_RI_OSD_NAME                 = 0x9,   /* variable */
+	OSD_ATTR_RI_TOTAL_CAPACITY           = 0x80,  /* 8        */
+	OSD_ATTR_RI_USED_CAPACITY            = 0x81,  /* 8        */
+	OSD_ATTR_RI_NUMBER_OF_PARTITIONS     = 0xC0,  /* 8        */
+	OSD_ATTR_RI_CLOCK                    = 0x100, /* 6        */
+};
+/* Root_Information_attributes_page does not have a get_page structure */
+
+/* 7.1.2.9 Partition Information attributes page
+ * (OSD_APAGE_PARTITION_INFORMATION)
+ */
+enum {
+	OSD_ATTR_PI_PARTITION_ID            = 0x1,     /* 8        */
+	OSD_ATTR_PI_USERNAME                = 0x9,     /* variable */
+	OSD_ATTR_PI_USED_CAPACITY           = 0x81,    /* 8        */
+	OSD_ATTR_PI_NUMBER_OF_OBJECTS       = 0xC1,    /* 8        */
+};
+/* Partition Information attributes page does not have a get_page structure */
+
+/* 7.1.2.10 Collection Information attributes page
+ * (OSD_APAGE_COLLECTION_INFORMATION)
+ */
+enum {
+	OSD_ATTR_CI_PARTITION_ID           = 0x1,       /* 8        */
+	OSD_ATTR_CI_COLLECTION_OBJECT_ID   = 0x2,       /* 8        */
+	OSD_ATTR_CI_USERNAME               = 0x9,       /* variable */
+	OSD_ATTR_CI_USED_CAPACITY          = 0x81,      /* 8        */
+};
+/* Collection Information attributes page does not have a get_page structure */
+
+/* 7.1.2.11 User Object Information attributes page
+ * (OSD_APAGE_OBJECT_INFORMATION)
+ */
+enum {
+	OSD_ATTR_OI_PARTITION_ID         = 0x1,       /* 8        */
+	OSD_ATTR_OI_OBJECT_ID            = 0x2,       /* 8        */
+	OSD_ATTR_OI_USERNAME             = 0x9,       /* variable */
+	OSD_ATTR_OI_USED_CAPACITY        = 0x81,      /* 8        */
+	OSD_ATTR_OI_LOGICAL_LENGTH       = 0x82,      /* 8        */
+};
+/* Object Information attributes page does not have a get_page structure */
+
+/* 7.1.2.12 Root Quotas attributes page (OSD_APAGE_ROOT_QUOTAS) */
+enum {
+	OSD_ATTR_RQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH     = 0x1,      /* 8  */
+	OSD_ATTR_RQ_PARTITION_CAPACITY_QUOTA               = 0x10001,  /* 8  */
+	OSD_ATTR_RQ_PARTITION_OBJECT_COUNT                 = 0x10002,  /* 8  */
+	OSD_ATTR_RQ_PARTITION_COLLECTIONS_PER_USER_OBJECT  = 0x10081,  /* 4  */
+	OSD_ATTR_RQ_PARTITION_COUNT                        = 0x20002,  /* 8  */
+};
+
+struct Root_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+2, size=0x24 */
+	__be64 default_maximum_user_object_length;
+	__be64 partition_capacity_quota;
+	__be64 partition_object_count;
+	__be64 partition_collections_per_user_object;
+	__be64 partition_count;
+}  __packed;
+
+/* 7.1.2.13 Partition Quotas attributes page (OSD_APAGE_PARTITION_QUOTAS)*/
+enum {
+	OSD_ATTR_PQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH  = 0x1,        /* 8 */
+	OSD_ATTR_PQ_CAPACITY_QUOTA                      = 0x10001,    /* 8 */
+	OSD_ATTR_PQ_OBJECT_COUNT                        = 0x10002,    /* 8 */
+	OSD_ATTR_PQ_COLLECTIONS_PER_USER_OBJECT         = 0x10081,    /* 4 */
+};
+
+struct Partition_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=P+2, size=0x1C */
+	__be64 default_maximum_user_object_length;
+	__be64 capacity_quota;
+	__be64 object_count;
+	__be64 collections_per_user_object;
+}  __packed;
+
+/* 7.1.2.14 User Object Quotas attributes page (OSD_APAGE_OBJECT_QUOTAS) */
+enum {
+	OSD_ATTR_OQ_MAXIMUM_LENGTH  = 0x1,        /* 8 */
+};
+
+struct Object_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=U+2, size=0x8 */
+	__be64 maximum_length;
+}  __packed;
+
+/* 7.1.2.15 Root Timestamps attributes page (OSD_APAGE_ROOT_TIMESTAMP) */
+enum {
+	OSD_ATTR_RT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_RT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_RT_TIMESTAMP_BYPASS          = 0xFFFFFFFE, /* 1 */
+};
+
+struct root_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+3, size=0xD */
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	u8 timestamp_bypass;
+}  __packed;
+
+/* 7.1.2.16 Partition Timestamps attributes page
+ * (OSD_APAGE_PARTITION_TIMESTAMP)
+ */
+enum {
+	OSD_ATTR_PT_CREATED_TIME              = 0x1,        /* 6 */
+	OSD_ATTR_PT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_PT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_PT_DATA_ACCESSED_TIME        = 0x4,        /* 6 */
+	OSD_ATTR_PT_DATA_MODIFIED_TIME        = 0x5,        /* 6 */
+	OSD_ATTR_PT_TIMESTAMP_BYPASS          = 0xFFFFFFFE, /* 1 */
+};
+
+struct partition_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=P+3, size=0x1F */
+	struct osd_timestamp created_time;
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	struct osd_timestamp data_accessed_time;
+	struct osd_timestamp data_modified_time;
+	u8 timestamp_bypass;
+}  __packed;
+
+/* 7.1.2.17/18 Collection/Object Timestamps attributes page
+ * (OSD_APAGE_COLLECTION_TIMESTAMP/OSD_APAGE_OBJECT_TIMESTAMP)
+ */
+enum {
+	OSD_ATTR_OT_CREATED_TIME              = 0x1,        /* 6 */
+	OSD_ATTR_OT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_OT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_OT_DATA_ACCESSED_TIME        = 0x4,        /* 6 */
+	OSD_ATTR_OT_DATA_MODIFIED_TIME        = 0x5,        /* 6 */
+};
+
+/* same for collection */
+struct object_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=C+3/3, size=0x1E */
+	struct osd_timestamp created_time;
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	struct osd_timestamp data_accessed_time;
+	struct osd_timestamp data_modified_time;
+}  __packed;
+
+/* 7.1.2.19 Collections attributes page */
+/* TBD */
+
+/* 7.1.2.20 Root Policy/Security attributes page (OSD_APAGE_ROOT_SECURITY) */
+enum {
+	OSD_ATTR_RS_DEFAULT_SECURITY_METHOD           = 0x1,       /* 1      */
+	OSD_ATTR_RS_OLDEST_VALID_NONCE_LIMIT          = 0x2,       /* 6      */
+	OSD_ATTR_RS_NEWEST_VALID_NONCE_LIMIT          = 0x3,       /* 6      */
+	OSD_ATTR_RS_PARTITION_DEFAULT_SECURITY_METHOD = 0x6,       /* 1      */
+	OSD_ATTR_RS_SUPPORTED_SECURITY_METHODS        = 0x7,       /* 2      */
+	OSD_ATTR_RS_ADJUSTABLE_CLOCK                  = 0x9,       /* 6      */
+	OSD_ATTR_RS_MASTER_KEY_IDENTIFIER             = 0x7FFD,    /* 0 or 7 */
+	OSD_ATTR_RS_ROOT_KEY_IDENTIFIER               = 0x7FFE,    /* 0 or 7 */
+	OSD_ATTR_RS_SUPPORTED_INTEGRITY_ALGORITHM_0   = 0x80000000,/* 1,(x16)*/
+	OSD_ATTR_RS_SUPPORTED_DH_GROUP_0              = 0x80000010,/* 1,(x16)*/
+};
+
+struct root_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+5, size=0x3F */
+	u8 default_security_method;
+	u8 partition_default_security_method;
+	__be16 supported_security_methods;
+	u8 mki_valid_rki_valid;
+	struct osd_timestamp oldest_valid_nonce_limit;
+	struct osd_timestamp newest_valid_nonce_limit;
+	struct osd_timestamp adjustable_clock;
+	u8 master_key_identifier[32-25];
+	u8 root_key_identifier[39-32];
+	u8 supported_integrity_algorithm[16];
+	u8 supported_dh_group[16];
+}  __packed;
+
+/* 7.1.2.21 Partition Policy/Security attributes page
+ * (OSD_APAGE_PARTITION_SECURITY)
+ */
+enum {
+	OSD_ATTR_PS_DEFAULT_SECURITY_METHOD        = 0x1,        /* 1      */
+	OSD_ATTR_PS_OLDEST_VALID_NONCE             = 0x2,        /* 6      */
+	OSD_ATTR_PS_NEWEST_VALID_NONCE             = 0x3,        /* 6      */
+	OSD_ATTR_PS_REQUEST_NONCE_LIST_DEPTH       = 0x4,        /* 2      */
+	OSD_ATTR_PS_FROZEN_WORKING_KEY_BIT_MASK    = 0x5,        /* 2      */
+	OSD_ATTR_PS_PARTITION_KEY_IDENTIFIER       = 0x7FFF,     /* 0 or 7 */
+	OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_FIRST   = 0x8000,     /* 0 or 7 */
+	OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_LAST    = 0x800F,     /* 0 or 7 */
+	OSD_ATTR_PS_POLICY_ACCESS_TAG              = 0x40000001, /* 4      */
+	OSD_ATTR_PS_USER_OBJECT_POLICY_ACCESS_TAG  = 0x40000002, /* 4      */
+};
+
+struct partition_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=p+5, size=0x8f */
+	u8 reserved[3];
+	u8 default_security_method;
+	struct osd_timestamp oldest_valid_nonce;
+	struct osd_timestamp newest_valid_nonce;
+	__be16 request_nonce_list_depth;
+	__be16 frozen_working_key_bit_mask;
+	__be32 policy_access_tag;
+	__be32 user_object_policy_access_tag;
+	u8 pki_valid;
+	__be16 wki_00_0f_vld;
+	struct osd_key_identifier partition_key_identifier;
+	struct osd_key_identifier working_key_identifiers[16];
+}  __packed;
+
+/* 7.1.2.22/23 Collection/Object Policy-Security attributes page
+ * (OSD_APAGE_COLLECTION_SECURITY/OSD_APAGE_OBJECT_SECURITY)
+ */
+enum {
+	OSD_ATTR_OS_POLICY_ACCESS_TAG              = 0x40000001, /* 4      */
+};
+
+struct object_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=C+5/5, size=4 */
+	__be32 policy_access_tag;
+}  __packed;
+
+#endif /*ndef __OSD_ATTRIBUTES_H__*/
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 10/18] osd_ktests: Test Attribute lists
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Add tests for setting/getting Attribute lists. All combinations
of read/write with set/get attributes are tested.
(6 possibilities), So all but data integrity request structure
layouts are attempted.

This test passes against the IBM-OSD-SIM OSDv1 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_ktests.c |  110 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
index f620915..f0a791f 100644
--- a/drivers/scsi/osd/osd_ktests.c
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -43,6 +43,7 @@
 
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
+#include <scsi/osd_attributes.h>
 
 #include "osd_ktests.h"
 #include "osd_debug.h"
@@ -260,6 +261,91 @@ int ktest_remove_par(struct osd_dev *osd_dev)
 	return 0;
 }
 
+int ktest_write_read_attr(struct osd_dev *osd_dev, void *buff,
+	bool doread, bool doset, bool doget)
+{
+	struct request_queue *req_q = osd_dev->scsi_dev->request_queue;
+	struct osd_request *or;
+	char g_caps[OSD_CAP_LEN];
+	int ret;
+	struct bio *bio;
+	char *domsg;
+	/* set attrs */
+	static char name[] = "ktest_write_read_attr";
+	__be64 max_len = cpu_to_be64(0x80000000L);
+	struct osd_obj_id obj = {
+		.partition = first_par_id,
+		.id = first_obj_id,
+	};
+	struct osd_attr set_attrs[] = {
+		ATTR_SET(OSD_APAGE_OBJECT_QUOTAS, OSD_ATTR_OQ_MAXIMUM_LENGTH,
+			sizeof(max_len), &max_len),
+		ATTR_SET(OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_USERNAME,
+			sizeof(name), name),
+	};
+	struct osd_attr get_attrs[] = {
+		ATTR_DEF(OSD_APAGE_OBJECT_INFORMATION,
+			OSD_ATTR_OI_USED_CAPACITY, sizeof(__be64)),
+		ATTR_DEF(OSD_APAGE_OBJECT_INFORMATION,
+			OSD_ATTR_OI_LOGICAL_LENGTH, sizeof(__be64)),
+	};
+
+	KTEST_START_REQ(osd_dev, or);
+	bio = bio_map_kern(req_q, buff, BUFF_SIZE, GFP_KERNEL);
+	if (!bio) {
+		OSD_ERR("!!! Failed to allocate BIO\n");
+		return -ENOMEM;
+	}
+
+	if (doread) {
+		osd_req_read(or, &obj, bio, 0);
+		domsg = "Read-with-attr";
+	} else {
+		osd_req_write(or, &obj, bio, 0);
+		domsg = "Write-with-attr";
+	}
+
+	if (doset)
+		osd_req_add_set_attr_list(or, set_attrs, 2);
+	if (doget)
+		osd_req_add_get_attr_list(or, get_attrs, 2);
+
+/*	KTEST_EXEC_END(or, &obj, "");*/
+	ret = test_exec(or, g_caps, &obj);
+	if (!ret && doget) {
+		void *iter = NULL, *pFirst, *pSec;
+		int nelem = 2;
+		u64 capacity_len = ~0;
+		u64 logical_len = ~0;
+
+		osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+		/*FIXME: Std does not guaranty order of return attrs */
+		pFirst = get_attrs[0].val_ptr;
+		if (pFirst)
+			capacity_len = get_unaligned_be64(pFirst);
+		else
+			OSD_ERR("failed to read capacity_used\n");
+		pSec = get_attrs[1].val_ptr;
+		if (pSec)
+			logical_len = get_unaligned_be64(pSec);
+		else
+			OSD_ERR("failed to read logical_length\n");
+		OSD_INFO("%s capacity=%llu len=%llu\n",
+			domsg, capacity_len, logical_len);
+	}
+
+	osd_end_request(or);
+	if (ret) {
+		OSD_ERR("!!! Error executing %s => %d doset=%d doget=%d\n",
+			domsg, ret, doset, doget);
+		return ret;
+	}
+	OSD_DEBUG("%s\n", domsg);
+
+	return 0;
+}
+
 int do_test_17(struct osd_dev *od)
 {
 	void *write_buff = NULL;
@@ -304,11 +390,35 @@ int do_test_17(struct osd_dev *od)
 /* List all objects */
 
 /* Write with get_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, false, true);
+	if (ret)
+		goto dev_fini;
+
 /* Write with set_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, true, false);
+	if (ret)
+		goto dev_fini;
+
 /* Write with set_attr + get_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, true, true);
+	if (ret)
+		goto dev_fini;
+
 /* Read with set_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, true, false);
+	if (ret)
+		goto dev_fini;
+
 /* Read with get_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, false, true);
+	if (ret)
+		goto dev_fini;
+
 /* Read with get_attr + set_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, true, true);
+	if (ret)
+		goto dev_fini;
+
 /* remove objects */
 	ret = ktest_remove_obj(od);
 	if (ret)
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 10/18] osd_ktests: Test Attribute lists
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Add tests for setting/getting Attribute lists. All combinations
of read/write with set/get attributes are tested.
(6 possibilities), So all but data integrity request structure
layouts are attempted.

This test passes against the IBM-OSD-SIM OSDv1 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_ktests.c |  110 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
index f620915..f0a791f 100644
--- a/drivers/scsi/osd/osd_ktests.c
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -43,6 +43,7 @@
 
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
+#include <scsi/osd_attributes.h>
 
 #include "osd_ktests.h"
 #include "osd_debug.h"
@@ -260,6 +261,91 @@ int ktest_remove_par(struct osd_dev *osd_dev)
 	return 0;
 }
 
+int ktest_write_read_attr(struct osd_dev *osd_dev, void *buff,
+	bool doread, bool doset, bool doget)
+{
+	struct request_queue *req_q = osd_dev->scsi_dev->request_queue;
+	struct osd_request *or;
+	char g_caps[OSD_CAP_LEN];
+	int ret;
+	struct bio *bio;
+	char *domsg;
+	/* set attrs */
+	static char name[] = "ktest_write_read_attr";
+	__be64 max_len = cpu_to_be64(0x80000000L);
+	struct osd_obj_id obj = {
+		.partition = first_par_id,
+		.id = first_obj_id,
+	};
+	struct osd_attr set_attrs[] = {
+		ATTR_SET(OSD_APAGE_OBJECT_QUOTAS, OSD_ATTR_OQ_MAXIMUM_LENGTH,
+			sizeof(max_len), &max_len),
+		ATTR_SET(OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_USERNAME,
+			sizeof(name), name),
+	};
+	struct osd_attr get_attrs[] = {
+		ATTR_DEF(OSD_APAGE_OBJECT_INFORMATION,
+			OSD_ATTR_OI_USED_CAPACITY, sizeof(__be64)),
+		ATTR_DEF(OSD_APAGE_OBJECT_INFORMATION,
+			OSD_ATTR_OI_LOGICAL_LENGTH, sizeof(__be64)),
+	};
+
+	KTEST_START_REQ(osd_dev, or);
+	bio = bio_map_kern(req_q, buff, BUFF_SIZE, GFP_KERNEL);
+	if (!bio) {
+		OSD_ERR("!!! Failed to allocate BIO\n");
+		return -ENOMEM;
+	}
+
+	if (doread) {
+		osd_req_read(or, &obj, bio, 0);
+		domsg = "Read-with-attr";
+	} else {
+		osd_req_write(or, &obj, bio, 0);
+		domsg = "Write-with-attr";
+	}
+
+	if (doset)
+		osd_req_add_set_attr_list(or, set_attrs, 2);
+	if (doget)
+		osd_req_add_get_attr_list(or, get_attrs, 2);
+
+/*	KTEST_EXEC_END(or, &obj, "");*/
+	ret = test_exec(or, g_caps, &obj);
+	if (!ret && doget) {
+		void *iter = NULL, *pFirst, *pSec;
+		int nelem = 2;
+		u64 capacity_len = ~0;
+		u64 logical_len = ~0;
+
+		osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+		/*FIXME: Std does not guaranty order of return attrs */
+		pFirst = get_attrs[0].val_ptr;
+		if (pFirst)
+			capacity_len = get_unaligned_be64(pFirst);
+		else
+			OSD_ERR("failed to read capacity_used\n");
+		pSec = get_attrs[1].val_ptr;
+		if (pSec)
+			logical_len = get_unaligned_be64(pSec);
+		else
+			OSD_ERR("failed to read logical_length\n");
+		OSD_INFO("%s capacity=%llu len=%llu\n",
+			domsg, capacity_len, logical_len);
+	}
+
+	osd_end_request(or);
+	if (ret) {
+		OSD_ERR("!!! Error executing %s => %d doset=%d doget=%d\n",
+			domsg, ret, doset, doget);
+		return ret;
+	}
+	OSD_DEBUG("%s\n", domsg);
+
+	return 0;
+}
+
 int do_test_17(struct osd_dev *od)
 {
 	void *write_buff = NULL;
@@ -304,11 +390,35 @@ int do_test_17(struct osd_dev *od)
 /* List all objects */
 
 /* Write with get_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, false, true);
+	if (ret)
+		goto dev_fini;
+
 /* Write with set_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, true, false);
+	if (ret)
+		goto dev_fini;
+
 /* Write with set_attr + get_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, true, true);
+	if (ret)
+		goto dev_fini;
+
 /* Read with set_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, true, false);
+	if (ret)
+		goto dev_fini;
+
 /* Read with get_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, false, true);
+	if (ret)
+		goto dev_fini;
+
 /* Read with get_attr + set_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, true, true);
+	if (ret)
+		goto dev_fini;
+
 /* remove objects */
 	ret = ktest_remove_obj(od);
 	if (ret)
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 11/18] libosd: OSD Security processing stubs
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Layout the signing of OSD's CDB and all-data security modes. The actual
code for signing the data and CDB is missing, but the code flow and the extra
buffer segments are all in place.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   85 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 85 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index da0c53c..2ed0429 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -109,6 +109,14 @@ static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
 }
 
+static struct osd_security_parameters *
+_osd_req_sec_params(struct osd_request *or)
+{
+	struct osd_cdb *ocdb = &or->cdb;
+
+	return &ocdb->v1.sec_params;
+}
+
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
 {
 	memset(osdd, 0, sizeof(*osdd));
@@ -796,6 +804,64 @@ int _osd_req_finalize_attr_page(struct osd_request *or)
 	return ret;
 }
 
+int _osd_req_finalize_data_integrity(struct osd_request *or,
+	bool has_in, bool has_out, const u8 *cap_key)
+{
+	struct osd_security_parameters *sec_parms = _osd_req_sec_params(or);
+	int ret;
+
+	if (!osd_is_sec_alldata(sec_parms))
+		return 0;
+
+	if (has_out) {
+		struct _osd_req_data_segment seg = {
+			.buff = &or->out_data_integ,
+			.total_bytes = sizeof(or->out_data_integ),
+		};
+		int pad;
+
+		or->out_data_integ.data_bytes = cpu_to_be64(
+			or->out.bio ? or->out.bio->bi_size : 0);
+		or->out_data_integ.set_attributes_bytes = cpu_to_be64(
+			or->set_attr.total_bytes);
+		or->out_data_integ.get_attributes_bytes = cpu_to_be64(
+			or->enc_get_attr.total_bytes);
+
+		sec_parms->data_out_integrity_check_offset =
+			osd_req_encode_offset(or, or->out.total_bytes, &pad);
+
+		ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
+					  &or->out);
+		if (ret)
+			return ret;
+		or->out.last_seg = NULL;
+
+		/* they are now all chained to request sign them all together */
+		osd_sec_sign_data(&or->out_data_integ, or->out.req->bio,
+				  cap_key);
+	}
+
+	if (has_in) {
+		struct _osd_req_data_segment seg = {
+			.buff = &or->in_data_integ,
+			.total_bytes = sizeof(or->in_data_integ),
+		};
+		int pad;
+
+		sec_parms->data_in_integrity_check_offset =
+			osd_req_encode_offset(or, or->in.total_bytes, &pad);
+
+		ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
+					  &or->in);
+		if (ret)
+			return ret;
+
+		or->in.last_seg = NULL;
+	}
+
+	return 0;
+}
+
 /*
  * osd_finalize_request and helpers
  */
@@ -916,6 +982,12 @@ int osd_finalize_request(struct osd_request *or,
 		}
 	}
 
+	ret = _osd_req_finalize_data_integrity(or, has_in, has_out, cap_key);
+	if (ret)
+		return ret;
+
+	osd_sec_sign_cdb(&or->cdb, cap_key);
+
 	or->request->cmd = or->cdb.buff;
 	or->request->cmd_len = _osd_req_cdb_len(or);
 
@@ -981,6 +1053,19 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
 }
 
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms)
+{
+	return false;
+}
+
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key)
+{
+}
+
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key)
+{
+}
+
 /*
  * Declared in osd_protocol.h
  * 4.12.5 Data-In and Data-Out buffer offsets
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 11/18] libosd: OSD Security processing stubs
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Layout the signing of OSD's CDB and all-data security modes. The actual
code for signing the data and CDB is missing, but the code flow and the extra
buffer segments are all in place.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   85 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 85 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index da0c53c..2ed0429 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -109,6 +109,14 @@ static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
 }
 
+static struct osd_security_parameters *
+_osd_req_sec_params(struct osd_request *or)
+{
+	struct osd_cdb *ocdb = &or->cdb;
+
+	return &ocdb->v1.sec_params;
+}
+
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
 {
 	memset(osdd, 0, sizeof(*osdd));
@@ -796,6 +804,64 @@ int _osd_req_finalize_attr_page(struct osd_request *or)
 	return ret;
 }
 
+int _osd_req_finalize_data_integrity(struct osd_request *or,
+	bool has_in, bool has_out, const u8 *cap_key)
+{
+	struct osd_security_parameters *sec_parms = _osd_req_sec_params(or);
+	int ret;
+
+	if (!osd_is_sec_alldata(sec_parms))
+		return 0;
+
+	if (has_out) {
+		struct _osd_req_data_segment seg = {
+			.buff = &or->out_data_integ,
+			.total_bytes = sizeof(or->out_data_integ),
+		};
+		int pad;
+
+		or->out_data_integ.data_bytes = cpu_to_be64(
+			or->out.bio ? or->out.bio->bi_size : 0);
+		or->out_data_integ.set_attributes_bytes = cpu_to_be64(
+			or->set_attr.total_bytes);
+		or->out_data_integ.get_attributes_bytes = cpu_to_be64(
+			or->enc_get_attr.total_bytes);
+
+		sec_parms->data_out_integrity_check_offset =
+			osd_req_encode_offset(or, or->out.total_bytes, &pad);
+
+		ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
+					  &or->out);
+		if (ret)
+			return ret;
+		or->out.last_seg = NULL;
+
+		/* they are now all chained to request sign them all together */
+		osd_sec_sign_data(&or->out_data_integ, or->out.req->bio,
+				  cap_key);
+	}
+
+	if (has_in) {
+		struct _osd_req_data_segment seg = {
+			.buff = &or->in_data_integ,
+			.total_bytes = sizeof(or->in_data_integ),
+		};
+		int pad;
+
+		sec_parms->data_in_integrity_check_offset =
+			osd_req_encode_offset(or, or->in.total_bytes, &pad);
+
+		ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
+					  &or->in);
+		if (ret)
+			return ret;
+
+		or->in.last_seg = NULL;
+	}
+
+	return 0;
+}
+
 /*
  * osd_finalize_request and helpers
  */
@@ -916,6 +982,12 @@ int osd_finalize_request(struct osd_request *or,
 		}
 	}
 
+	ret = _osd_req_finalize_data_integrity(or, has_in, has_out, cap_key);
+	if (ret)
+		return ret;
+
+	osd_sec_sign_cdb(&or->cdb, cap_key);
+
 	or->request->cmd = or->cdb.buff;
 	or->request->cmd_len = _osd_req_cdb_len(or);
 
@@ -981,6 +1053,19 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
 }
 
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms)
+{
+	return false;
+}
+
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key)
+{
+}
+
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key)
+{
+}
+
 /*
  * Declared in osd_protocol.h
  * 4.12.5 Data-In and Data-Out buffer offsets
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 12/18] libosd: Add Flush and List-objects support
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Add support for the various List-objects commands. List-partitions-in-device,
List-collections-in-partition, List-objects-in-partition,
List-objects-in-collection. All these support partial listing and continuation.

Add support for the different Flush commands and options.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  124 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 124 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 2ed0429..23f7e95 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -102,6 +102,16 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
 	}
 }
 
+/* This is for List-objects not Attributes-Lists */
+static void _osd_req_encode_olist(struct osd_request *or,
+	struct osd_obj_id_list *list)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+	cdbh->v1.list_identifier = list->list_identifier;
+	cdbh->v1.start_address = list->continuation_id;
+}
+
 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 	u64 offset, unsigned *padding)
 {
@@ -338,6 +348,29 @@ void osd_req_format(struct osd_request *or, u64 tot_capacity)
 }
 EXPORT_SYMBOL(osd_req_format);
 
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem)
+{
+	return osd_req_list_partition_objects(or, 0, initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_dev_partitions);
+
+static void _osd_req_encode_flush(struct osd_request *or,
+	enum osd_options_flush_scope_values op)
+{
+	struct osd_cdb_head *ocdb = osd_cdb_head(&or->cdb);
+
+	ocdb->command_specific_options = op;
+}
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH_OSD, &osd_root_object, 0, 0);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_obsd);
+
 /*
  * Partition commands
  */
@@ -364,6 +397,88 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition)
 }
 EXPORT_SYMBOL(osd_req_remove_partition);
 
+static int _osd_req_list_objects(struct osd_request *or,
+	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem)
+{
+	struct request_queue *q = or->osd_dev->scsi_dev->request_queue;
+	u64 len = nelem * sizeof(osd_id) + sizeof(*list);
+	struct bio *bio;
+
+	_osd_req_encode_common(or, action, obj, (u64)initial_id, len);
+
+	if (list->list_identifier)
+		_osd_req_encode_olist(or, list);
+
+	WARN_ON(or->in.bio);
+	bio = bio_map_kern(q, list, len, or->alloc_flags);
+	if (!bio) {
+		OSD_ERR("!!! Failed to allocate list_objects BIO\n");
+		return -ENOMEM;
+	}
+
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+	return 0;
+}
+
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	return osd_req_list_collection_objects(or, &par, initial_id, list,
+					       nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_collections);
+
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	return _osd_req_list_objects(or, OSD_ACT_LIST, &par, initial_id, list,
+				     nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_objects);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_partition(or, OSD_ACT_FLUSH_PARTITION, partition);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_partition);
+
+/*
+ * Collection commands
+ */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *obj, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem)
+{
+	return _osd_req_list_objects(or, OSD_ACT_LIST_COLLECTION, obj,
+				     initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_collection_objects);
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH_PARTITION, obj, 0, 0);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_collection);
+
 /*
  * Object commands
  */
@@ -390,6 +505,15 @@ void osd_req_write(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_write);
 
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
+	/*V2*/ u64 offset, /*V2*/ u64 len)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_object);
+
 void osd_req_read(struct osd_request *or,
 	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
 {
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 12/18] libosd: Add Flush and List-objects support
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Add support for the various List-objects commands. List-partitions-in-device,
List-collections-in-partition, List-objects-in-partition,
List-objects-in-collection. All these support partial listing and continuation.

Add support for the different Flush commands and options.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  124 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 124 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 2ed0429..23f7e95 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -102,6 +102,16 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
 	}
 }
 
+/* This is for List-objects not Attributes-Lists */
+static void _osd_req_encode_olist(struct osd_request *or,
+	struct osd_obj_id_list *list)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+	cdbh->v1.list_identifier = list->list_identifier;
+	cdbh->v1.start_address = list->continuation_id;
+}
+
 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 	u64 offset, unsigned *padding)
 {
@@ -338,6 +348,29 @@ void osd_req_format(struct osd_request *or, u64 tot_capacity)
 }
 EXPORT_SYMBOL(osd_req_format);
 
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem)
+{
+	return osd_req_list_partition_objects(or, 0, initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_dev_partitions);
+
+static void _osd_req_encode_flush(struct osd_request *or,
+	enum osd_options_flush_scope_values op)
+{
+	struct osd_cdb_head *ocdb = osd_cdb_head(&or->cdb);
+
+	ocdb->command_specific_options = op;
+}
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH_OSD, &osd_root_object, 0, 0);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_obsd);
+
 /*
  * Partition commands
  */
@@ -364,6 +397,88 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition)
 }
 EXPORT_SYMBOL(osd_req_remove_partition);
 
+static int _osd_req_list_objects(struct osd_request *or,
+	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem)
+{
+	struct request_queue *q = or->osd_dev->scsi_dev->request_queue;
+	u64 len = nelem * sizeof(osd_id) + sizeof(*list);
+	struct bio *bio;
+
+	_osd_req_encode_common(or, action, obj, (u64)initial_id, len);
+
+	if (list->list_identifier)
+		_osd_req_encode_olist(or, list);
+
+	WARN_ON(or->in.bio);
+	bio = bio_map_kern(q, list, len, or->alloc_flags);
+	if (!bio) {
+		OSD_ERR("!!! Failed to allocate list_objects BIO\n");
+		return -ENOMEM;
+	}
+
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+	return 0;
+}
+
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	return osd_req_list_collection_objects(or, &par, initial_id, list,
+					       nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_collections);
+
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	return _osd_req_list_objects(or, OSD_ACT_LIST, &par, initial_id, list,
+				     nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_objects);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_partition(or, OSD_ACT_FLUSH_PARTITION, partition);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_partition);
+
+/*
+ * Collection commands
+ */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *obj, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem)
+{
+	return _osd_req_list_objects(or, OSD_ACT_LIST_COLLECTION, obj,
+				     initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_collection_objects);
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH_PARTITION, obj, 0, 0);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_collection);
+
 /*
  * Object commands
  */
@@ -390,6 +505,15 @@ void osd_req_write(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_write);
 
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
+	/*V2*/ u64 offset, /*V2*/ u64 len)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_object);
+
 void osd_req_read(struct osd_request *or,
 	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
 {
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 13/18] libosd: Not implemented commands
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Some commands declared in header are not yet implemented. Put them
as stubs in .c file, just so they take their place in the file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   35 +++++++++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 23f7e95..567a2c6 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -341,6 +341,9 @@ static void _osd_req_encode_common(struct osd_request *or,
 /*
  * Device commands
  */
+/*TODO: void osd_req_set_master_seed_xchg(struct osd_request *, ...); */
+/*TODO: void osd_req_set_master_key(struct osd_request *, ...); */
+
 void osd_req_format(struct osd_request *or, u64 tot_capacity)
 {
 	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
@@ -371,6 +374,10 @@ void osd_req_flush_obsd(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_flush_obsd);
 
+/*TODO: void osd_req_perform_scsi_command(struct osd_request *,
+	const u8 *cdb, ...); */
+/*TODO: void osd_req_task_management(struct osd_request *, ...); */
+
 /*
  * Partition commands
  */
@@ -397,6 +404,10 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition)
 }
 EXPORT_SYMBOL(osd_req_remove_partition);
 
+/*TODO: void osd_req_set_partition_key(struct osd_request *,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]); */
+
 static int _osd_req_list_objects(struct osd_request *or,
 	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
 	struct osd_obj_id_list *list, unsigned nelem)
@@ -462,6 +473,11 @@ EXPORT_SYMBOL(osd_req_flush_partition);
 /*
  * Collection commands
  */
+/*TODO: void osd_req_create_collection(struct osd_request *,
+	const struct osd_obj_id *); */
+/*TODO: void osd_req_remove_collection(struct osd_request *,
+	const struct osd_obj_id *); */
+
 int osd_req_list_collection_objects(struct osd_request *or,
 	const struct osd_obj_id *obj, osd_id initial_id,
 	struct osd_obj_id_list *list, unsigned nelem)
@@ -471,6 +487,8 @@ int osd_req_list_collection_objects(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_list_collection_objects);
 
+/*TODO: void query(struct osd_request *, ...); V2 */
+
 void osd_req_flush_collection(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
 {
@@ -479,6 +497,9 @@ void osd_req_flush_collection(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_flush_collection);
 
+/*TODO: void get_member_attrs(struct osd_request *, ...); V2 */
+/*TODO: void set_member_attrs(struct osd_request *, ...); V2 */
+
 /*
  * Object commands
  */
@@ -494,6 +515,11 @@ void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
 }
 EXPORT_SYMBOL(osd_req_remove_object);
 
+
+/*TODO: void osd_req_create_multi(struct osd_request *or,
+	struct osd_obj_id *first, struct osd_obj_id_list *list, unsigned nelem);
+*/
+
 void osd_req_write(struct osd_request *or,
 	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
 {
@@ -505,6 +531,15 @@ void osd_req_write(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_write);
 
+/*TODO: void osd_req_append(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out); */
+/*TODO: void osd_req_create_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset); */
+/*TODO: void osd_req_clear(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len); */
+/*TODO: void osd_req_punch(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len); V2 */
+
 void osd_req_flush_object(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
 	/*V2*/ u64 offset, /*V2*/ u64 len)
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 13/18] libosd: Not implemented commands
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Some commands declared in header are not yet implemented. Put them
as stubs in .c file, just so they take their place in the file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   35 +++++++++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 23f7e95..567a2c6 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -341,6 +341,9 @@ static void _osd_req_encode_common(struct osd_request *or,
 /*
  * Device commands
  */
+/*TODO: void osd_req_set_master_seed_xchg(struct osd_request *, ...); */
+/*TODO: void osd_req_set_master_key(struct osd_request *, ...); */
+
 void osd_req_format(struct osd_request *or, u64 tot_capacity)
 {
 	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
@@ -371,6 +374,10 @@ void osd_req_flush_obsd(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_flush_obsd);
 
+/*TODO: void osd_req_perform_scsi_command(struct osd_request *,
+	const u8 *cdb, ...); */
+/*TODO: void osd_req_task_management(struct osd_request *, ...); */
+
 /*
  * Partition commands
  */
@@ -397,6 +404,10 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition)
 }
 EXPORT_SYMBOL(osd_req_remove_partition);
 
+/*TODO: void osd_req_set_partition_key(struct osd_request *,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]); */
+
 static int _osd_req_list_objects(struct osd_request *or,
 	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
 	struct osd_obj_id_list *list, unsigned nelem)
@@ -462,6 +473,11 @@ EXPORT_SYMBOL(osd_req_flush_partition);
 /*
  * Collection commands
  */
+/*TODO: void osd_req_create_collection(struct osd_request *,
+	const struct osd_obj_id *); */
+/*TODO: void osd_req_remove_collection(struct osd_request *,
+	const struct osd_obj_id *); */
+
 int osd_req_list_collection_objects(struct osd_request *or,
 	const struct osd_obj_id *obj, osd_id initial_id,
 	struct osd_obj_id_list *list, unsigned nelem)
@@ -471,6 +487,8 @@ int osd_req_list_collection_objects(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_list_collection_objects);
 
+/*TODO: void query(struct osd_request *, ...); V2 */
+
 void osd_req_flush_collection(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
 {
@@ -479,6 +497,9 @@ void osd_req_flush_collection(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_flush_collection);
 
+/*TODO: void get_member_attrs(struct osd_request *, ...); V2 */
+/*TODO: void set_member_attrs(struct osd_request *, ...); V2 */
+
 /*
  * Object commands
  */
@@ -494,6 +515,11 @@ void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
 }
 EXPORT_SYMBOL(osd_req_remove_object);
 
+
+/*TODO: void osd_req_create_multi(struct osd_request *or,
+	struct osd_obj_id *first, struct osd_obj_id_list *list, unsigned nelem);
+*/
+
 void osd_req_write(struct osd_request *or,
 	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
 {
@@ -505,6 +531,15 @@ void osd_req_write(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_write);
 
+/*TODO: void osd_req_append(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out); */
+/*TODO: void osd_req_create_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset); */
+/*TODO: void osd_req_clear(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len); */
+/*TODO: void osd_req_punch(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len); V2 */
+
 void osd_req_flush_object(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
 	/*V2*/ u64 offset, /*V2*/ u64 len)
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 14/18] libosd: OSD version 2 Support
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 13917 bytes --]

Add support for OSD2 at run time. It is now possible to run with
both OSDv1 and OSDv2 targets at the same time. The actual detection
should be preformed by the security manager, as the version is encoded
in the capability structure.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   94 ++++++++++++++++++++++++++++++++------
 include/scsi/osd_initiator.h     |   39 ++++++++++++++++
 include/scsi/osd_protocol.h      |   86 +++++++++++++++++++++++++++++++++--
 3 files changed, 201 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 567a2c6..9127fc4 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -57,36 +57,50 @@ static inline void build_test(void)
 {
 	/* structures were not packed */
 	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
 	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
 }
 
 static unsigned _osd_req_cdb_len(struct osd_request *or)
 {
-	return OSDv1_TOTAL_CDB_LEN;
+	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
 }
 
 static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
 {
-	return osdv1_attr_list_elem_size(len);
+	return osd_req_is_ver1(or) ?
+		osdv1_attr_list_elem_size(len) :
+		osdv2_attr_list_elem_size(len);
 }
 
 static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
 {
-	return osdv1_list_size(list_head);
+	return osd_req_is_ver1(or) ?
+		osdv1_list_size(list_head) :
+		osdv2_list_size(list_head);
 }
 
 static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
 {
-	return sizeof(struct osdv1_attributes_list_header);
+	return osd_req_is_ver1(or) ?
+		sizeof(struct osdv1_attributes_list_header) :
+		sizeof(struct osdv2_attributes_list_header);
 }
 
 static void _osd_req_set_alist_type(struct osd_request *or,
 	void *list, int list_type)
 {
-	struct osdv1_attributes_list_header *attr_list = list;
+	if (osd_req_is_ver1(or)) {
+		struct osdv1_attributes_list_header *attr_list = list;
+
+		memset(attr_list, 0, sizeof(*attr_list));
+		attr_list->type = list_type;
+	} else {
+		struct osdv2_attributes_list_header *attr_list = list;
 
-	memset(attr_list, 0, sizeof(*attr_list));
-	attr_list->type = list_type;
+		memset(attr_list, 0, sizeof(*attr_list));
+		attr_list->type = list_type;
+	}
 }
 
 static bool _osd_req_is_alist_type(struct osd_request *or,
@@ -95,10 +109,14 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
 	if (!list)
 		return false;
 
-	if (1) {
+	if (osd_req_is_ver1(or)) {
 		struct osdv1_attributes_list_header *attr_list = list;
 
 		return attr_list->type == list_type;
+	} else {
+		struct osdv2_attributes_list_header *attr_list = list;
+
+		return attr_list->type == list_type;
 	}
 }
 
@@ -108,15 +126,22 @@ static void _osd_req_encode_olist(struct osd_request *or,
 {
 	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
 
-	cdbh->v1.list_identifier = list->list_identifier;
-	cdbh->v1.start_address = list->continuation_id;
+	if (osd_req_is_ver1(or)) {
+		cdbh->v1.list_identifier = list->list_identifier;
+		cdbh->v1.start_address = list->continuation_id;
+	} else {
+		cdbh->v2.list_identifier = list->list_identifier;
+		cdbh->v2.start_address = list->continuation_id;
+	}
 }
 
 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 	u64 offset, unsigned *padding)
 {
 	return __osd_encode_offset(offset, padding,
-				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+			osd_req_is_ver1(or) ?
+				OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT,
+			OSD_OFFSET_MAX_SHIFT);
 }
 
 static struct osd_security_parameters *
@@ -124,7 +149,10 @@ _osd_req_sec_params(struct osd_request *or)
 {
 	struct osd_cdb *ocdb = &or->cdb;
 
-	return &ocdb->v1.sec_params;
+	if (osd_req_is_ver1(or))
+		return &ocdb->v1.sec_params;
+	else
+		return &ocdb->v2.sec_params;
 }
 
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
@@ -132,6 +160,9 @@ void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
 	memset(osdd, 0, sizeof(*osdd));
 	osdd->scsi_dev = scsi_dev;
 	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+#ifdef OSD_VER1_SUPPORT
+	osdd->version = OSD_VER2;
+#endif
 	/* TODO: Allocate pools for osd_request attributes ... */
 }
 EXPORT_SYMBOL(osd_dev_init);
@@ -332,10 +363,30 @@ static void _osdv1_req_encode_common(struct osd_request *or,
 	ocdb->h.v1.start_address = cpu_to_be64(offset);
 }
 
+static void _osdv2_req_encode_common(struct osd_request *or,
+	 __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv2_cdb *ocdb = &or->cdb.v2;
+
+	OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v2.length = cpu_to_be64(len);
+	ocdb->h.v2.start_address = cpu_to_be64(offset);
+}
+
 static void _osd_req_encode_common(struct osd_request *or,
 	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
 {
-	_osdv1_req_encode_common(or, act, obj, offset, len);
+	if (osd_req_is_ver1(or))
+		_osdv1_req_encode_common(or, act, obj, offset, len);
+	else
+		_osdv2_req_encode_common(or, act, obj, offset, len);
 }
 
 /*
@@ -544,6 +595,12 @@ void osd_req_flush_object(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
 	/*V2*/ u64 offset, /*V2*/ u64 len)
 {
+	if (unlikely(osd_req_is_ver1(or) && (offset || len))) {
+		OSD_DEBUG("OSD Ver1 flush on specific range ignored\n");
+		offset = 0;
+		len = 0;
+	}
+
 	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
 	_osd_req_encode_flush(or, op);
 }
@@ -1166,6 +1223,10 @@ enum { OSD_SEC_CAP_V1_ALL_CAPS =
 	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
 };
 
+enum { OSD_SEC_CAP_V2_ALL_CAPS =
+	OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT
+};
+
 void osd_sec_init_nosec_doall_caps(void *caps,
 	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
 {
@@ -1207,9 +1268,14 @@ void osd_sec_init_nosec_doall_caps(void *caps,
 }
 EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
 
+/* FIXME: Extract version from caps pointer.
+ *        Also Pete's target only supports caps from OSDv1 for now
+ */
 void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 {
-	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+	bool is_ver1 = true;
+	/* NOTE: They start at same address */
+	memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN);
 }
 
 bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms)
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 0004df1..738312f 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -21,6 +21,23 @@
 
 /* Note: "NI" in comments below means "Not Implemented yet" */
 
+/* Configure of code:
+ * #undef if you *don't* want OSD v1 support in runtime.
+ * If #defined the initiator will dynamically configure to encode OSD v1
+ * CDB's if the target is detected to be OSD v1 only.
+ * OSD v2 only commands, options, and attributes will be ignored if target
+ * is v1 only.
+ * If #defined will result in bigger/slower code (OK Slower maybe not)
+ * Q: Should this be CONFIG_SCSI_OSD_VER1_SUPPORT and set from Kconfig?
+ */
+#define OSD_VER1_SUPPORT y
+
+enum osd_std_version {
+	OSD_VER_NONE = 0,
+	OSD_VER1 = 1,
+	OSD_VER2 = 2,
+};
+
 /*
  * Object-based Storage Device.
  * This object represents an OSD device.
@@ -31,6 +48,10 @@
 struct osd_dev {
 	struct scsi_device *scsi_dev;
 	unsigned def_timeout;
+
+#ifdef OSD_VER1_SUPPORT
+	enum osd_std_version version;
+#endif
 };
 
 /* Retrieve/return osd_dev(s) for use by Kernel clients */
@@ -41,6 +62,14 @@ void osduld_put_device(struct osd_dev *od);
 void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
 void osd_dev_fini(struct osd_dev *);
 
+/* we might want to use function vector in the future */
+static inline void osd_dev_set_ver(struct osd_dev *dev, enum osd_std_version v)
+{
+#ifdef OSD_VER1_SUPPORT
+	dev->version = v;
+#endif
+}
+
 struct osd_request;
 typedef void (osd_req_done_fn)(struct osd_request *, void *);
 
@@ -77,6 +106,16 @@ struct osd_request {
 	int async_error;
 };
 
+/* OSD Version control */
+static inline bool osd_req_is_ver1(struct osd_request *or)
+{
+#ifdef OSD_VER1_SUPPORT
+	return or->osd_dev->version == OSD_VER1;
+#else
+	return false;
+#endif
+}
+
 /**
  * How to use the osd library:
  *
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
index 77a74a3..ef7505e 100644
--- a/include/scsi/osd_protocol.h
+++ b/include/scsi/osd_protocol.h
@@ -25,9 +25,12 @@ enum {
 	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
 	OSDv1_CAP_LEN = 80,
 	/* Latest supported version */
-	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
-	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
-	OSD_CAP_LEN = OSDv1_CAP_LEN,
+/* 	OSD_ADDITIONAL_CDB_LENGTH = 216,*/
+	OSD_ADDITIONAL_CDB_LENGTH =
+		OSDv1_ADDITIONAL_CDB_LENGTH, /* FIXME: Pete rev-001 sup */
+	OSD_TOTAL_CDB_LEN = OSD_ADDITIONAL_CDB_LENGTH + 8,
+/* 	OSD_CAP_LEN = 104,*/
+	OSD_CAP_LEN = OSDv1_CAP_LEN,/* FIXME: Pete rev-001 sup */
 
 	OSD_SYSTEMID_LEN = 20,
 	OSD_CRYPTO_KEYID_SIZE = 20,
@@ -108,6 +111,7 @@ enum {
 	OSD_OFFSET_MAX_BITS = 28,
 
 	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MIN_SHIFT = 3,
 	OSD_OFFSET_MAX_SHIFT = 16,
 };
 
@@ -129,6 +133,16 @@ static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
 				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
 }
 
+/* Minimum 8 bytes alignment
+ * Same as v1 but since exponent can be signed than a less than
+ * 256 alignment can be reached with small offsets (<2GB)
+ */
+static inline osd_cdb_offset osd_encode_offset_v2(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				   OSD_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
 /* osd2r03: 5.2.1 Overview */
 struct osd_cdb_head {
 	struct scsi_varlen_cdb_hdr varlen_cdb;
@@ -144,6 +158,13 @@ struct osd_cdb_head {
 /*36*/			__be64		length;
 /*44*/			__be64		start_address;
 		} __packed v1;
+
+		struct __osdv2_cdb_addr_len {
+			/* called allocation_length in some commands */
+/*32*/			__be64	length;
+/*40*/			__be64	start_address;
+/*48*/			__be32 list_identifier;/* Rarely used */
+		} __packed v2;
 	};
 /*52*/	union { /* selected attributes mode Page/List/Single */
 		struct osd_attributes_page_mode {
@@ -182,6 +203,7 @@ struct osd_cdb_head {
 /*80*/
 
 /*160 v1*/
+/*184 v2*/
 struct osd_security_parameters {
 /*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
 /*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
@@ -189,6 +211,7 @@ struct osd_security_parameters {
 /*196*/osd_cdb_offset	data_out_integrity_check_offset;
 } __packed;
 /*200 v1*/
+/*224 v2*/
 
 struct osdv1_cdb {
 	struct osd_cdb_head h;
@@ -196,9 +219,16 @@ struct osdv1_cdb {
 	struct osd_security_parameters sec_params;
 } __packed;
 
+struct osdv2_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSD_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
 struct osd_cdb {
 	union {
 		struct osdv1_cdb v1;
+		struct osdv2_cdb v2;
 		u8 buff[OSD_TOTAL_CDB_LEN];
 	};
 } __packed;
@@ -269,6 +299,7 @@ struct osd_attributes_list_attrid {
 /*
  * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
  *                  for setting attributes
+ * NOTE: v2 is 8-bytes aligned, v1 is not aligned.
  */
 struct osd_attributes_list_element {
 	__be32 page;
@@ -279,6 +310,7 @@ struct osd_attributes_list_element {
 
 enum {
 	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+	OSD_ATTRIBUTES_ELEM_ALIGN = 8,
 };
 
 enum {
@@ -292,6 +324,12 @@ static inline unsigned osdv1_attr_list_elem_size(unsigned len)
 		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
 }
 
+static inline unsigned osdv2_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSD_ATTRIBUTES_ELEM_ALIGN);
+}
+
 /*
  * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
  */
@@ -326,6 +364,21 @@ static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
 	return be16_to_cpu(h->list_bytes);
 }
 
+struct osdv2_attributes_list_header {
+	u8 type;	/* lower 4-bits only */
+	u8 pad[3];
+/*4*/	__be32 list_bytes; /* Initiator shall set to zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv2_list_size(struct osdv2_attributes_list_header *h)
+{
+	return be32_to_cpu(h->list_bytes);
+}
+
 /* (osd-r10 6.13)
  * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
  *	for root_lstchg below
@@ -469,11 +522,36 @@ struct osdv1_cap_object_descriptor {
 } __packed;
 /*80 v1*/
 
-struct osd_capability {
+/*56 v2*/
+struct osd_cap_object_descriptor {
+	union {
+		struct {
+			__be32 allowed_attributes_access;
+/*60*/			__be32 policy_access_tag;
+/*64*/			__be16 boot_epoch;
+/*66*/			u8 reserved[72-66];
+/*72*/			__be64 allowed_partition_id;
+/*80*/			__be64 allowed_object_id;
+/*88*/			__be64 allowed_range_length;
+/*96*/			__be64 allowed_range_start;
+		} __packed obj_desc;
+
+		u8 object_descriptor[104-56]; /*48*/
+	};
+} __packed;
+/*104 v2*/
+
+struct osdv1_capability {
 	struct osd_capability_head h;
 	struct osdv1_cap_object_descriptor od;
 } __packed;
 
+struct osd_capability {
+	struct osd_capability_head h;
+/* 	struct osd_cap_object_descriptor od;*/
+	struct osdv1_cap_object_descriptor od; /* FIXME: Pete rev-001 sup */
+} __packed;
+
 /**
  * osd_sec_set_caps - set cap-bits into the capabilities header
  *
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 15/18] libosd: OSDv2 auto detection
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Auto detect an OSDv2 or OSDv1 target at run time. Note how none
of the OSD API calls change. The tests do not know what device
version it is.

This test now passes against both the IBM-OSD-SIM OSD1 target
as well as OSC's OSD2 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  125 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/osd/osd_uld.c       |    5 ++
 include/scsi/osd_initiator.h     |    3 +
 3 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 9127fc4..8e59cdc 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -41,6 +41,7 @@
 
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
+#include <scsi/osd_attributes.h>
 #include <scsi/scsi_device.h>
 
 #include "osd_debug.h"
@@ -61,6 +62,130 @@ static inline void build_test(void)
 	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
 }
 
+static char *_osd_ver_desc(struct osd_request *or)
+{
+	return osd_req_is_ver1(or) ? "OSD1" : "OSD2";
+}
+
+#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
+
+static int _osd_print_system_info(struct osd_dev *od, void *caps)
+{
+	struct osd_request *or;
+	struct osd_attr get_attrs[] = {
+		ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/),
+		ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/),
+		ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6),
+		/* IBM-OSD-SIM Has a bug with this one put it last */
+		ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20),
+	};
+	void *iter = NULL, *pFirst;
+	int nelem = ARRAY_SIZE(get_attrs), a = 0;
+	int ret;
+
+	or = osd_start_request(od, GFP_KERNEL);
+	if (!or)
+		return -ENOMEM;
+
+	/* get attrs */
+	osd_req_get_attributes(or, &osd_root_object);
+	osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs));
+
+	ret = osd_finalize_request(or, 0, caps, NULL);
+	if (ret)
+		goto out;
+
+	ret = osd_execute_request(or);
+	if (ret) {
+		OSD_ERR("Failed to detect %s => %d\n", _osd_ver_desc(or), ret);
+		goto out;
+	}
+
+	osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+	OSD_INFO("Detected %s device\n",
+		_osd_ver_desc(or));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_VENDOR_IDENTIFICATION [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_IDENTIFICATION [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_MODEL [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_REVISION_LEVEL [%u]\n",
+		get_unaligned_be32(pFirst));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_OSD_NAME [%s]\n", (char *)pFirst);
+	a++;
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_TOTAL_CAPACITY [0x%llx]\n",
+		get_unaligned_be64(pFirst));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_USED_CAPACITY [0x%llx]\n",
+		get_unaligned_be64(pFirst));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_NUMBER_OF_PARTITIONS [%lld]\n",
+		get_unaligned_be64(pFirst));
+
+	/* FIXME: Where are the time utilities */
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_CLOCK [0x%02x%02x%02x%02x%02x%02x]\n",
+		((char *)pFirst)[0], ((char *)pFirst)[1],
+		((char *)pFirst)[2], ((char *)pFirst)[3],
+		((char *)pFirst)[4], ((char *)pFirst)[5]);
+
+	if (a < nelem) { /* IBM-OSD-SIM bug, Might not have it */
+		int len = get_attrs[a].len;
+		u8 sid_dump[32*4 + 2]; /* 2nibbles+space+ASCII */
+
+		hex_dump_to_buffer(get_attrs[a].val_ptr, len, 32, 1,
+				   sid_dump, sizeof(sid_dump), true);
+		OSD_INFO("OSD_ATTR_RI_OSD_SYSTEM_ID(%d) [%s]\n", len, sid_dump);
+		a++;
+	}
+out:
+	osd_end_request(or);
+	return ret;
+}
+
+int osd_auto_detect_ver(struct osd_dev *od, void *caps)
+{
+	int ret;
+
+	/* Auto-detect the osd version */
+	ret = _osd_print_system_info(od, caps);
+	if (ret) {
+		osd_dev_set_ver(od, OSD_VER1);
+		OSD_DEBUG("converting to OSD1\n");
+		ret = _osd_print_system_info(od, caps);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(osd_auto_detect_ver);
+
 static unsigned _osd_req_cdb_len(struct osd_request *or)
 {
 	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 1ce5eba..0f2bea7 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -201,6 +201,7 @@ EXPORT_SYMBOL(osduld_put_device);
 static int __detect_osd(struct osd_uld_device *oud)
 {
 	struct scsi_device *scsi_dev = oud->od.scsi_dev;
+	char caps[OSD_CAP_LEN];
 	int error;
 
 	/* sending a test_unit_ready as first command seems to be needed
@@ -212,6 +213,10 @@ static int __detect_osd(struct osd_uld_device *oud)
 	if (error)
 		OSD_ERR("warning: scsi_test_unit_ready failed\n");
 
+	osd_sec_init_nosec_doall_caps(caps, &osd_root_object, false, true);
+	if (osd_auto_detect_ver(&oud->od, caps))
+		return -ENODEV;
+
 	return 0;
 }
 
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 738312f..4fd5099 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -62,6 +62,9 @@ void osduld_put_device(struct osd_dev *od);
 void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
 void osd_dev_fini(struct osd_dev *);
 
+/* some hi level device operations */
+int osd_auto_detect_ver(struct osd_dev *, void *caps);    /* GFP_KERNEL */
+
 /* we might want to use function vector in the future */
 static inline void osd_dev_set_ver(struct osd_dev *dev, enum osd_std_version v)
 {
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 14/18] libosd: OSD version 2 Support
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Add support for OSD2 at run time. It is now possible to run with
both OSDv1 and OSDv2 targets at the same time. The actual detection
should be preformed by the security manager, as the version is encoded
in the capability structure.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   94 ++++++++++++++++++++++++++++++++------
 include/scsi/osd_initiator.h     |   39 ++++++++++++++++
 include/scsi/osd_protocol.h      |   86 +++++++++++++++++++++++++++++++++--
 3 files changed, 201 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 567a2c6..9127fc4 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -57,36 +57,50 @@ static inline void build_test(void)
 {
 	/* structures were not packed */
 	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
 	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
 }
 
 static unsigned _osd_req_cdb_len(struct osd_request *or)
 {
-	return OSDv1_TOTAL_CDB_LEN;
+	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
 }
 
 static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
 {
-	return osdv1_attr_list_elem_size(len);
+	return osd_req_is_ver1(or) ?
+		osdv1_attr_list_elem_size(len) :
+		osdv2_attr_list_elem_size(len);
 }
 
 static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
 {
-	return osdv1_list_size(list_head);
+	return osd_req_is_ver1(or) ?
+		osdv1_list_size(list_head) :
+		osdv2_list_size(list_head);
 }
 
 static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
 {
-	return sizeof(struct osdv1_attributes_list_header);
+	return osd_req_is_ver1(or) ?
+		sizeof(struct osdv1_attributes_list_header) :
+		sizeof(struct osdv2_attributes_list_header);
 }
 
 static void _osd_req_set_alist_type(struct osd_request *or,
 	void *list, int list_type)
 {
-	struct osdv1_attributes_list_header *attr_list = list;
+	if (osd_req_is_ver1(or)) {
+		struct osdv1_attributes_list_header *attr_list = list;
+
+		memset(attr_list, 0, sizeof(*attr_list));
+		attr_list->type = list_type;
+	} else {
+		struct osdv2_attributes_list_header *attr_list = list;
 
-	memset(attr_list, 0, sizeof(*attr_list));
-	attr_list->type = list_type;
+		memset(attr_list, 0, sizeof(*attr_list));
+		attr_list->type = list_type;
+	}
 }
 
 static bool _osd_req_is_alist_type(struct osd_request *or,
@@ -95,10 +109,14 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
 	if (!list)
 		return false;
 
-	if (1) {
+	if (osd_req_is_ver1(or)) {
 		struct osdv1_attributes_list_header *attr_list = list;
 
 		return attr_list->type == list_type;
+	} else {
+		struct osdv2_attributes_list_header *attr_list = list;
+
+		return attr_list->type == list_type;
 	}
 }
 
@@ -108,15 +126,22 @@ static void _osd_req_encode_olist(struct osd_request *or,
 {
 	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
 
-	cdbh->v1.list_identifier = list->list_identifier;
-	cdbh->v1.start_address = list->continuation_id;
+	if (osd_req_is_ver1(or)) {
+		cdbh->v1.list_identifier = list->list_identifier;
+		cdbh->v1.start_address = list->continuation_id;
+	} else {
+		cdbh->v2.list_identifier = list->list_identifier;
+		cdbh->v2.start_address = list->continuation_id;
+	}
 }
 
 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 	u64 offset, unsigned *padding)
 {
 	return __osd_encode_offset(offset, padding,
-				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+			osd_req_is_ver1(or) ?
+				OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT,
+			OSD_OFFSET_MAX_SHIFT);
 }
 
 static struct osd_security_parameters *
@@ -124,7 +149,10 @@ _osd_req_sec_params(struct osd_request *or)
 {
 	struct osd_cdb *ocdb = &or->cdb;
 
-	return &ocdb->v1.sec_params;
+	if (osd_req_is_ver1(or))
+		return &ocdb->v1.sec_params;
+	else
+		return &ocdb->v2.sec_params;
 }
 
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
@@ -132,6 +160,9 @@ void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
 	memset(osdd, 0, sizeof(*osdd));
 	osdd->scsi_dev = scsi_dev;
 	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+#ifdef OSD_VER1_SUPPORT
+	osdd->version = OSD_VER2;
+#endif
 	/* TODO: Allocate pools for osd_request attributes ... */
 }
 EXPORT_SYMBOL(osd_dev_init);
@@ -332,10 +363,30 @@ static void _osdv1_req_encode_common(struct osd_request *or,
 	ocdb->h.v1.start_address = cpu_to_be64(offset);
 }
 
+static void _osdv2_req_encode_common(struct osd_request *or,
+	 __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv2_cdb *ocdb = &or->cdb.v2;
+
+	OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v2.length = cpu_to_be64(len);
+	ocdb->h.v2.start_address = cpu_to_be64(offset);
+}
+
 static void _osd_req_encode_common(struct osd_request *or,
 	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
 {
-	_osdv1_req_encode_common(or, act, obj, offset, len);
+	if (osd_req_is_ver1(or))
+		_osdv1_req_encode_common(or, act, obj, offset, len);
+	else
+		_osdv2_req_encode_common(or, act, obj, offset, len);
 }
 
 /*
@@ -544,6 +595,12 @@ void osd_req_flush_object(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
 	/*V2*/ u64 offset, /*V2*/ u64 len)
 {
+	if (unlikely(osd_req_is_ver1(or) && (offset || len))) {
+		OSD_DEBUG("OSD Ver1 flush on specific range ignored\n");
+		offset = 0;
+		len = 0;
+	}
+
 	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
 	_osd_req_encode_flush(or, op);
 }
@@ -1166,6 +1223,10 @@ enum { OSD_SEC_CAP_V1_ALL_CAPS =
 	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
 };
 
+enum { OSD_SEC_CAP_V2_ALL_CAPS =
+	OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT
+};
+
 void osd_sec_init_nosec_doall_caps(void *caps,
 	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
 {
@@ -1207,9 +1268,14 @@ void osd_sec_init_nosec_doall_caps(void *caps,
 }
 EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
 
+/* FIXME: Extract version from caps pointer.
+ *        Also Pete's target only supports caps from OSDv1 for now
+ */
 void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 {
-	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+	bool is_ver1 = true;
+	/* NOTE: They start at same address */
+	memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN);
 }
 
 bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms)
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 0004df1..738312f 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -21,6 +21,23 @@
 
 /* Note: "NI" in comments below means "Not Implemented yet" */
 
+/* Configure of code:
+ * #undef if you *don't* want OSD v1 support in runtime.
+ * If #defined the initiator will dynamically configure to encode OSD v1
+ * CDB's if the target is detected to be OSD v1 only.
+ * OSD v2 only commands, options, and attributes will be ignored if target
+ * is v1 only.
+ * If #defined will result in bigger/slower code (OK Slower maybe not)
+ * Q: Should this be CONFIG_SCSI_OSD_VER1_SUPPORT and set from Kconfig?
+ */
+#define OSD_VER1_SUPPORT y
+
+enum osd_std_version {
+	OSD_VER_NONE = 0,
+	OSD_VER1 = 1,
+	OSD_VER2 = 2,
+};
+
 /*
  * Object-based Storage Device.
  * This object represents an OSD device.
@@ -31,6 +48,10 @@
 struct osd_dev {
 	struct scsi_device *scsi_dev;
 	unsigned def_timeout;
+
+#ifdef OSD_VER1_SUPPORT
+	enum osd_std_version version;
+#endif
 };
 
 /* Retrieve/return osd_dev(s) for use by Kernel clients */
@@ -41,6 +62,14 @@ void osduld_put_device(struct osd_dev *od);
 void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
 void osd_dev_fini(struct osd_dev *);
 
+/* we might want to use function vector in the future */
+static inline void osd_dev_set_ver(struct osd_dev *dev, enum osd_std_version v)
+{
+#ifdef OSD_VER1_SUPPORT
+	dev->version = v;
+#endif
+}
+
 struct osd_request;
 typedef void (osd_req_done_fn)(struct osd_request *, void *);
 
@@ -77,6 +106,16 @@ struct osd_request {
 	int async_error;
 };
 
+/* OSD Version control */
+static inline bool osd_req_is_ver1(struct osd_request *or)
+{
+#ifdef OSD_VER1_SUPPORT
+	return or->osd_dev->version == OSD_VER1;
+#else
+	return false;
+#endif
+}
+
 /**
  * How to use the osd library:
  *
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
index 77a74a3..ef7505e 100644
--- a/include/scsi/osd_protocol.h
+++ b/include/scsi/osd_protocol.h
@@ -25,9 +25,12 @@ enum {
 	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
 	OSDv1_CAP_LEN = 80,
 	/* Latest supported version */
-	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
-	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
-	OSD_CAP_LEN = OSDv1_CAP_LEN,
+/* 	OSD_ADDITIONAL_CDB_LENGTH = 216,*/
+	OSD_ADDITIONAL_CDB_LENGTH =
+		OSDv1_ADDITIONAL_CDB_LENGTH, /* FIXME: Pete rev-001 sup */
+	OSD_TOTAL_CDB_LEN = OSD_ADDITIONAL_CDB_LENGTH + 8,
+/* 	OSD_CAP_LEN = 104,*/
+	OSD_CAP_LEN = OSDv1_CAP_LEN,/* FIXME: Pete rev-001 sup */
 
 	OSD_SYSTEMID_LEN = 20,
 	OSD_CRYPTO_KEYID_SIZE = 20,
@@ -108,6 +111,7 @@ enum {
 	OSD_OFFSET_MAX_BITS = 28,
 
 	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MIN_SHIFT = 3,
 	OSD_OFFSET_MAX_SHIFT = 16,
 };
 
@@ -129,6 +133,16 @@ static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
 				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
 }
 
+/* Minimum 8 bytes alignment
+ * Same as v1 but since exponent can be signed than a less than
+ * 256 alignment can be reached with small offsets (<2GB)
+ */
+static inline osd_cdb_offset osd_encode_offset_v2(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				   OSD_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
 /* osd2r03: 5.2.1 Overview */
 struct osd_cdb_head {
 	struct scsi_varlen_cdb_hdr varlen_cdb;
@@ -144,6 +158,13 @@ struct osd_cdb_head {
 /*36*/			__be64		length;
 /*44*/			__be64		start_address;
 		} __packed v1;
+
+		struct __osdv2_cdb_addr_len {
+			/* called allocation_length in some commands */
+/*32*/			__be64	length;
+/*40*/			__be64	start_address;
+/*48*/			__be32 list_identifier;/* Rarely used */
+		} __packed v2;
 	};
 /*52*/	union { /* selected attributes mode Page/List/Single */
 		struct osd_attributes_page_mode {
@@ -182,6 +203,7 @@ struct osd_cdb_head {
 /*80*/
 
 /*160 v1*/
+/*184 v2*/
 struct osd_security_parameters {
 /*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
 /*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
@@ -189,6 +211,7 @@ struct osd_security_parameters {
 /*196*/osd_cdb_offset	data_out_integrity_check_offset;
 } __packed;
 /*200 v1*/
+/*224 v2*/
 
 struct osdv1_cdb {
 	struct osd_cdb_head h;
@@ -196,9 +219,16 @@ struct osdv1_cdb {
 	struct osd_security_parameters sec_params;
 } __packed;
 
+struct osdv2_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSD_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
 struct osd_cdb {
 	union {
 		struct osdv1_cdb v1;
+		struct osdv2_cdb v2;
 		u8 buff[OSD_TOTAL_CDB_LEN];
 	};
 } __packed;
@@ -269,6 +299,7 @@ struct osd_attributes_list_attrid {
 /*
  * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
  *                  for setting attributes
+ * NOTE: v2 is 8-bytes aligned, v1 is not aligned.
  */
 struct osd_attributes_list_element {
 	__be32 page;
@@ -279,6 +310,7 @@ struct osd_attributes_list_element {
 
 enum {
 	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+	OSD_ATTRIBUTES_ELEM_ALIGN = 8,
 };
 
 enum {
@@ -292,6 +324,12 @@ static inline unsigned osdv1_attr_list_elem_size(unsigned len)
 		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
 }
 
+static inline unsigned osdv2_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSD_ATTRIBUTES_ELEM_ALIGN);
+}
+
 /*
  * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
  */
@@ -326,6 +364,21 @@ static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
 	return be16_to_cpu(h->list_bytes);
 }
 
+struct osdv2_attributes_list_header {
+	u8 type;	/* lower 4-bits only */
+	u8 pad[3];
+/*4*/	__be32 list_bytes; /* Initiator shall set to zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv2_list_size(struct osdv2_attributes_list_header *h)
+{
+	return be32_to_cpu(h->list_bytes);
+}
+
 /* (osd-r10 6.13)
  * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
  *	for root_lstchg below
@@ -469,11 +522,36 @@ struct osdv1_cap_object_descriptor {
 } __packed;
 /*80 v1*/
 
-struct osd_capability {
+/*56 v2*/
+struct osd_cap_object_descriptor {
+	union {
+		struct {
+			__be32 allowed_attributes_access;
+/*60*/			__be32 policy_access_tag;
+/*64*/			__be16 boot_epoch;
+/*66*/			u8 reserved[72-66];
+/*72*/			__be64 allowed_partition_id;
+/*80*/			__be64 allowed_object_id;
+/*88*/			__be64 allowed_range_length;
+/*96*/			__be64 allowed_range_start;
+		} __packed obj_desc;
+
+		u8 object_descriptor[104-56]; /*48*/
+	};
+} __packed;
+/*104 v2*/
+
+struct osdv1_capability {
 	struct osd_capability_head h;
 	struct osdv1_cap_object_descriptor od;
 } __packed;
 
+struct osd_capability {
+	struct osd_capability_head h;
+/* 	struct osd_cap_object_descriptor od;*/
+	struct osdv1_cap_object_descriptor od; /* FIXME: Pete rev-001 sup */
+} __packed;
+
 /**
  * osd_sec_set_caps - set cap-bits into the capabilities header
  *
-- 
1.6.0.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 15/18] libosd: OSDv2 auto detection
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Auto detect an OSDv2 or OSDv1 target at run time. Note how none
of the OSD API calls change. The tests do not know what device
version it is.

This test now passes against both the IBM-OSD-SIM OSD1 target
as well as OSC's OSD2 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  125 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/osd/osd_uld.c       |    5 ++
 include/scsi/osd_initiator.h     |    3 +
 3 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 9127fc4..8e59cdc 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -41,6 +41,7 @@
 
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
+#include <scsi/osd_attributes.h>
 #include <scsi/scsi_device.h>
 
 #include "osd_debug.h"
@@ -61,6 +62,130 @@ static inline void build_test(void)
 	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
 }
 
+static char *_osd_ver_desc(struct osd_request *or)
+{
+	return osd_req_is_ver1(or) ? "OSD1" : "OSD2";
+}
+
+#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
+
+static int _osd_print_system_info(struct osd_dev *od, void *caps)
+{
+	struct osd_request *or;
+	struct osd_attr get_attrs[] = {
+		ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/),
+		ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/),
+		ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6),
+		/* IBM-OSD-SIM Has a bug with this one put it last */
+		ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20),
+	};
+	void *iter = NULL, *pFirst;
+	int nelem = ARRAY_SIZE(get_attrs), a = 0;
+	int ret;
+
+	or = osd_start_request(od, GFP_KERNEL);
+	if (!or)
+		return -ENOMEM;
+
+	/* get attrs */
+	osd_req_get_attributes(or, &osd_root_object);
+	osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs));
+
+	ret = osd_finalize_request(or, 0, caps, NULL);
+	if (ret)
+		goto out;
+
+	ret = osd_execute_request(or);
+	if (ret) {
+		OSD_ERR("Failed to detect %s => %d\n", _osd_ver_desc(or), ret);
+		goto out;
+	}
+
+	osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+	OSD_INFO("Detected %s device\n",
+		_osd_ver_desc(or));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_VENDOR_IDENTIFICATION [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_IDENTIFICATION [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_MODEL [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_REVISION_LEVEL [%u]\n",
+		get_unaligned_be32(pFirst));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_OSD_NAME [%s]\n", (char *)pFirst);
+	a++;
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_TOTAL_CAPACITY [0x%llx]\n",
+		get_unaligned_be64(pFirst));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_USED_CAPACITY [0x%llx]\n",
+		get_unaligned_be64(pFirst));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_NUMBER_OF_PARTITIONS [%lld]\n",
+		get_unaligned_be64(pFirst));
+
+	/* FIXME: Where are the time utilities */
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_CLOCK [0x%02x%02x%02x%02x%02x%02x]\n",
+		((char *)pFirst)[0], ((char *)pFirst)[1],
+		((char *)pFirst)[2], ((char *)pFirst)[3],
+		((char *)pFirst)[4], ((char *)pFirst)[5]);
+
+	if (a < nelem) { /* IBM-OSD-SIM bug, Might not have it */
+		int len = get_attrs[a].len;
+		u8 sid_dump[32*4 + 2]; /* 2nibbles+space+ASCII */
+
+		hex_dump_to_buffer(get_attrs[a].val_ptr, len, 32, 1,
+				   sid_dump, sizeof(sid_dump), true);
+		OSD_INFO("OSD_ATTR_RI_OSD_SYSTEM_ID(%d) [%s]\n", len, sid_dump);
+		a++;
+	}
+out:
+	osd_end_request(or);
+	return ret;
+}
+
+int osd_auto_detect_ver(struct osd_dev *od, void *caps)
+{
+	int ret;
+
+	/* Auto-detect the osd version */
+	ret = _osd_print_system_info(od, caps);
+	if (ret) {
+		osd_dev_set_ver(od, OSD_VER1);
+		OSD_DEBUG("converting to OSD1\n");
+		ret = _osd_print_system_info(od, caps);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(osd_auto_detect_ver);
+
 static unsigned _osd_req_cdb_len(struct osd_request *or)
 {
 	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 1ce5eba..0f2bea7 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -201,6 +201,7 @@ EXPORT_SYMBOL(osduld_put_device);
 static int __detect_osd(struct osd_uld_device *oud)
 {
 	struct scsi_device *scsi_dev = oud->od.scsi_dev;
+	char caps[OSD_CAP_LEN];
 	int error;
 
 	/* sending a test_unit_ready as first command seems to be needed
@@ -212,6 +213,10 @@ static int __detect_osd(struct osd_uld_device *oud)
 	if (error)
 		OSD_ERR("warning: scsi_test_unit_ready failed\n");
 
+	osd_sec_init_nosec_doall_caps(caps, &osd_root_object, false, true);
+	if (osd_auto_detect_ver(&oud->od, caps))
+		return -ENODEV;
+
 	return 0;
 }
 
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 738312f..4fd5099 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -62,6 +62,9 @@ void osduld_put_device(struct osd_dev *od);
 void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
 void osd_dev_fini(struct osd_dev *);
 
+/* some hi level device operations */
+int osd_auto_detect_ver(struct osd_dev *, void *caps);    /* GFP_KERNEL */
+
 /* we might want to use function vector in the future */
 static inline void osd_dev_set_ver(struct osd_dev *dev, enum osd_std_version v)
 {
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 16/18] osd: Documentation for OSD library
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Add osd.txt to Documentation/scsi/

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 Documentation/scsi/osd.txt |  198 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 198 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/scsi/osd.txt

diff --git a/Documentation/scsi/osd.txt b/Documentation/scsi/osd.txt
new file mode 100644
index 0000000..a6735ae
--- /dev/null
+++ b/Documentation/scsi/osd.txt
@@ -0,0 +1,198 @@
+The OSD Standard
+================
+OSD (Object-Based Storage Device) is a T10 SCSI command set that is designed
+to provide efficient operation of input/output logical units that manage the
+allocation, placement, and accessing of variable-size data-storage containers,
+called objects. Objects are intended to contain operating system and application
+constructs. Each object has associated attributes attached to it, which are
+integral part of the object and provide metadata about the object. The standard
+defines some common obligatory attributes, but user attributes can be added as
+needed.
+
+See: http://www.t10.org/ftp/t10/drafts/osd2/ for the latest draft for OSD 2
+or search the web for "OSD SCSI"
+
+OSD in the Linux Kernel
+=======================
+osd-initiator:
+  The main component of OSD in Kernel is the osd-initiator library. Its main
+user is intended to be the pNFS-over-objects layout driver, which uses objects
+as its back-end data storage. Other clients are the other osd parts listed below.
+
+osd-uld:
+  This is a SCSI ULD that registers for OSD type devices and provides a testing
+platform, both for the in-kernel initiator as well as connected targets. It
+currently has no useful user-mode API, though it could have if need be.
+
+osdfs:
+  Is an OSD based Linux file system. It uses the osd-initiator and osd-uld,
+to export a usable file system for users.
+See Documentation/filesystems/osdfs.txt for more details
+
+osd target:
+  There are no current plans for an OSD target implementation in kernel. For all
+needs, a user-mode target that is based on the scsi tgt target framework is
+available from Ohio Supercomputer Center (OSC) at:
+http://www.open-osd.org/bin/view/Main/OscOsdProject
+There are several other target implementations. See http://open-osd.org for more
+links.
+
+Files and Folders
+=================
+This is the complete list of files included in this work:
+include/scsi/
+	osd_initiator.h   Main API for the initiator library
+	osd_types.h	  Common OSD types
+	osd_sec.h	  Security Manager API
+	osd_protocol.h	  Wire definitions of the OSD standard protocol
+	osd_attributes.h  Wire definitions of OSD attributes
+
+drivers/scsi/osd/
+	osd_initiator.c   OSD-Initiator library implementation
+	osd_uld.c	  The OSD scsi ULD
+	osd_ktest.{h,c}	  In-kernel test suite (called by osd_uld)
+	osd_debug.h	  Some printk macros
+	Makefile	  For both in-tree and out-of-tree compilation
+	Kconfig		  Enables inclusion of the different pieces
+	osd_test.c	  User-mode application to call the kernel tests
+
+The OSD-Initiator Library
+=========================
+osd_initiator is a low level implementation of an osd initiator encoder.
+But even though, it should be intuitive and easy to use. Perhaps over time an
+higher lever will form that automates some of the more common recipes.
+
+init/fini:
+- osd_dev_init() associates a scsi_device with an osd_dev structure
+  and initializes some global pools. This should be done once per scsi_device
+  (OSD LUN). The osd_dev structure is needed for calling osd_start_request().
+
+- osd_dev_fini() cleans up before a osd_dev/scsi_device destruction.
+
+OSD commands encoding, execution, and decoding of results:
+
+struct osd_request's is used to iteratively encode an OSD command and carry
+its state throughout execution. Each request goes through these stages:
+
+a. osd_start_request() allocates the request.
+
+b. Any of the osd_req_* methods is used to encode a request of the specified
+   type.
+
+c. osd_req_add_{get,set}_attr_* may be called to add get/set attributes to the
+   CDB. "List" or "Page" mode can be used exclusively. The attribute-list API
+   can be called multiple times on the same request. However, only one
+   attribute-page can be read, as mandated by the OSD standard.
+
+d. osd_finalize_request() computes offsets into the data-in and data-out buffers
+   and signs the request using the provided capability key and integrity-
+   check parameters.
+
+e. osd_execute_request() may be called to execute the request via the block
+   layer and wait for its completion.  The request can be executed
+   asynchronously by calling the block layer API directly.
+
+f. After execution, osd_req_decode_sense() can be called to decode the request's
+   sense information.
+
+g. osd_req_decode_get_attr() may be called to retrieve osd_add_get_attr_list()
+   values.
+
+h. osd_end_request() must be called to deallocate the request and any resource
+   associated with it. Note that osd_end_request cleans up the request at any
+   stage and it must always be called after a successful osd_start_request().
+
+osd_request's structure:
+
+The OSD standard defines a complex structure of IO segments pointed to by
+members in the CDB. Up to 3 segments can be deployed in the IN-Buffer and up to
+4 in the OUT-Buffer. The ASCII illustration below depicts a secure-read with
+associated get+set of attributes-lists. Other combinations very on the same
+basic theme. From no-segments-used up to all-segments-used.
+
+|________OSD-CDB__________|
+|                         |
+|read_len (offset=0)     -|---------\
+|                         |         |
+|get_attrs_list_length    |         |
+|get_attrs_list_offset   -|----\    |
+|                         |    |    |
+|retrieved_attrs_alloc_len|    |    |
+|retrieved_attrs_offset  -|----|----|-\
+|                         |    |    | |
+|set_attrs_list_length    |    |    | |
+|set_attrs_list_offset   -|-\  |    | |
+|                         | |  |    | |
+|in_data_integ_offset    -|-|--|----|-|-\
+|out_data_integ_offset   -|-|--|--\ | | |
+\_________________________/ |  |  | | | |
+                            |  |  | | | |
+|_______OUT-BUFFER________| |  |  | | | |
+|      Set attr list      |</  |  | | | |
+|                         |    |  | | | |
+|-------------------------|    |  | | | |
+|   Get attr descriptors  |<---/  | | | |
+|                         |       | | | |
+|-------------------------|       | | | |
+|    Out-data integrity   |<------/ | | |
+|                         |         | | |
+\_________________________/         | | |
+                                    | | |
+|________IN-BUFFER________|         | | |
+|      In-Data read       |<--------/ | |
+|                         |           | |
+|-------------------------|           | |
+|      Get attr list      |<----------/ |
+|                         |             |
+|-------------------------|             |
+|    In-data integrity    |<------------/
+|                         |
+\_________________________/
+
+A block device request can carry bidirectional payload by means of associating
+a bidi_read request with a main write-request. Each in/out request is described
+by a chain of BIOs associated with each request.
+The CDB is of a SCSI VARLEN CDB format, as described by OSD standard.
+The OSD standard also mandates alignment restrictions at start of each segment.
+
+In the code, in struct osd_request, there are two _osd_io_info structures to
+describe the IN/OUT buffers above, two BIOs for the data payload and up to five
+_osd_req_data_segment structures to hold the different segments allocation and
+information.
+
+Important: We have chosen to disregard the assumption that a BIO-chain (and
+the resulting sg-list) describes a linear memory buffer. Meaning only first and
+last scatter chain can be incomplete and all the middle chains are of PAGE_SIZE.
+For us, a scatter-gather-list, as its name implies and as used by the Networking
+layer, is to describe a vector of buffers that will be transferred to/from the
+wire. It works very well with current iSCSI transport. iSCSI is currently the
+only deployed OSD transport. In the future we anticipate SAS and FC attached OSD
+devices as well.
+
+The OSD Testing ULD
+===================
+TODO: More user-mode control on tests.
+
+Authors, Mailing list
+=====================
+Please communicate with us on any deployment of osd, whether using this code
+or not.
+
+Any problems, questions, bug reports, lonely OSD nights, please email:
+   OSD Dev List <osd-dev@open-osd.org>
+
+More up-to-date information can be found on:
+http://open-osd.org
+
+Boaz Harrosh <bharrosh@panasas.com>
+Benny Halevy <bhalevy@panasas.com>
+
+References
+==========
+Weber, R., "SCSI Object-Based Storage Device Commands",
+T10/1355-D ANSI/INCITS 400-2004,
+http://www.t10.org/ftp/t10/drafts/osd/osd-r10.pdf
+
+Weber, R., "SCSI Object-Based Storage Device Commands -2 (OSD-2)"
+T10/1729-D, Working Draft, rev. 3
+http://www.t10.org/ftp/t10/drafts/osd2/osd2r03.pdf
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 16/18] osd: Documentation for OSD library
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Add osd.txt to Documentation/scsi/

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 Documentation/scsi/osd.txt |  198 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 198 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/scsi/osd.txt

diff --git a/Documentation/scsi/osd.txt b/Documentation/scsi/osd.txt
new file mode 100644
index 0000000..a6735ae
--- /dev/null
+++ b/Documentation/scsi/osd.txt
@@ -0,0 +1,198 @@
+The OSD Standard
+================
+OSD (Object-Based Storage Device) is a T10 SCSI command set that is designed
+to provide efficient operation of input/output logical units that manage the
+allocation, placement, and accessing of variable-size data-storage containers,
+called objects. Objects are intended to contain operating system and application
+constructs. Each object has associated attributes attached to it, which are
+integral part of the object and provide metadata about the object. The standard
+defines some common obligatory attributes, but user attributes can be added as
+needed.
+
+See: http://www.t10.org/ftp/t10/drafts/osd2/ for the latest draft for OSD 2
+or search the web for "OSD SCSI"
+
+OSD in the Linux Kernel
+=======================
+osd-initiator:
+  The main component of OSD in Kernel is the osd-initiator library. Its main
+user is intended to be the pNFS-over-objects layout driver, which uses objects
+as its back-end data storage. Other clients are the other osd parts listed below.
+
+osd-uld:
+  This is a SCSI ULD that registers for OSD type devices and provides a testing
+platform, both for the in-kernel initiator as well as connected targets. It
+currently has no useful user-mode API, though it could have if need be.
+
+osdfs:
+  Is an OSD based Linux file system. It uses the osd-initiator and osd-uld,
+to export a usable file system for users.
+See Documentation/filesystems/osdfs.txt for more details
+
+osd target:
+  There are no current plans for an OSD target implementation in kernel. For all
+needs, a user-mode target that is based on the scsi tgt target framework is
+available from Ohio Supercomputer Center (OSC) at:
+http://www.open-osd.org/bin/view/Main/OscOsdProject
+There are several other target implementations. See http://open-osd.org for more
+links.
+
+Files and Folders
+=================
+This is the complete list of files included in this work:
+include/scsi/
+	osd_initiator.h   Main API for the initiator library
+	osd_types.h	  Common OSD types
+	osd_sec.h	  Security Manager API
+	osd_protocol.h	  Wire definitions of the OSD standard protocol
+	osd_attributes.h  Wire definitions of OSD attributes
+
+drivers/scsi/osd/
+	osd_initiator.c   OSD-Initiator library implementation
+	osd_uld.c	  The OSD scsi ULD
+	osd_ktest.{h,c}	  In-kernel test suite (called by osd_uld)
+	osd_debug.h	  Some printk macros
+	Makefile	  For both in-tree and out-of-tree compilation
+	Kconfig		  Enables inclusion of the different pieces
+	osd_test.c	  User-mode application to call the kernel tests
+
+The OSD-Initiator Library
+=========================
+osd_initiator is a low level implementation of an osd initiator encoder.
+But even though, it should be intuitive and easy to use. Perhaps over time an
+higher lever will form that automates some of the more common recipes.
+
+init/fini:
+- osd_dev_init() associates a scsi_device with an osd_dev structure
+  and initializes some global pools. This should be done once per scsi_device
+  (OSD LUN). The osd_dev structure is needed for calling osd_start_request().
+
+- osd_dev_fini() cleans up before a osd_dev/scsi_device destruction.
+
+OSD commands encoding, execution, and decoding of results:
+
+struct osd_request's is used to iteratively encode an OSD command and carry
+its state throughout execution. Each request goes through these stages:
+
+a. osd_start_request() allocates the request.
+
+b. Any of the osd_req_* methods is used to encode a request of the specified
+   type.
+
+c. osd_req_add_{get,set}_attr_* may be called to add get/set attributes to the
+   CDB. "List" or "Page" mode can be used exclusively. The attribute-list API
+   can be called multiple times on the same request. However, only one
+   attribute-page can be read, as mandated by the OSD standard.
+
+d. osd_finalize_request() computes offsets into the data-in and data-out buffers
+   and signs the request using the provided capability key and integrity-
+   check parameters.
+
+e. osd_execute_request() may be called to execute the request via the block
+   layer and wait for its completion.  The request can be executed
+   asynchronously by calling the block layer API directly.
+
+f. After execution, osd_req_decode_sense() can be called to decode the request's
+   sense information.
+
+g. osd_req_decode_get_attr() may be called to retrieve osd_add_get_attr_list()
+   values.
+
+h. osd_end_request() must be called to deallocate the request and any resource
+   associated with it. Note that osd_end_request cleans up the request at any
+   stage and it must always be called after a successful osd_start_request().
+
+osd_request's structure:
+
+The OSD standard defines a complex structure of IO segments pointed to by
+members in the CDB. Up to 3 segments can be deployed in the IN-Buffer and up to
+4 in the OUT-Buffer. The ASCII illustration below depicts a secure-read with
+associated get+set of attributes-lists. Other combinations very on the same
+basic theme. From no-segments-used up to all-segments-used.
+
+|________OSD-CDB__________|
+|                         |
+|read_len (offset=0)     -|---------\
+|                         |         |
+|get_attrs_list_length    |         |
+|get_attrs_list_offset   -|----\    |
+|                         |    |    |
+|retrieved_attrs_alloc_len|    |    |
+|retrieved_attrs_offset  -|----|----|-\
+|                         |    |    | |
+|set_attrs_list_length    |    |    | |
+|set_attrs_list_offset   -|-\  |    | |
+|                         | |  |    | |
+|in_data_integ_offset    -|-|--|----|-|-\
+|out_data_integ_offset   -|-|--|--\ | | |
+\_________________________/ |  |  | | | |
+                            |  |  | | | |
+|_______OUT-BUFFER________| |  |  | | | |
+|      Set attr list      |</  |  | | | |
+|                         |    |  | | | |
+|-------------------------|    |  | | | |
+|   Get attr descriptors  |<---/  | | | |
+|                         |       | | | |
+|-------------------------|       | | | |
+|    Out-data integrity   |<------/ | | |
+|                         |         | | |
+\_________________________/         | | |
+                                    | | |
+|________IN-BUFFER________|         | | |
+|      In-Data read       |<--------/ | |
+|                         |           | |
+|-------------------------|           | |
+|      Get attr list      |<----------/ |
+|                         |             |
+|-------------------------|             |
+|    In-data integrity    |<------------/
+|                         |
+\_________________________/
+
+A block device request can carry bidirectional payload by means of associating
+a bidi_read request with a main write-request. Each in/out request is described
+by a chain of BIOs associated with each request.
+The CDB is of a SCSI VARLEN CDB format, as described by OSD standard.
+The OSD standard also mandates alignment restrictions at start of each segment.
+
+In the code, in struct osd_request, there are two _osd_io_info structures to
+describe the IN/OUT buffers above, two BIOs for the data payload and up to five
+_osd_req_data_segment structures to hold the different segments allocation and
+information.
+
+Important: We have chosen to disregard the assumption that a BIO-chain (and
+the resulting sg-list) describes a linear memory buffer. Meaning only first and
+last scatter chain can be incomplete and all the middle chains are of PAGE_SIZE.
+For us, a scatter-gather-list, as its name implies and as used by the Networking
+layer, is to describe a vector of buffers that will be transferred to/from the
+wire. It works very well with current iSCSI transport. iSCSI is currently the
+only deployed OSD transport. In the future we anticipate SAS and FC attached OSD
+devices as well.
+
+The OSD Testing ULD
+===================
+TODO: More user-mode control on tests.
+
+Authors, Mailing list
+=====================
+Please communicate with us on any deployment of osd, whether using this code
+or not.
+
+Any problems, questions, bug reports, lonely OSD nights, please email:
+   OSD Dev List <osd-dev@open-osd.org>
+
+More up-to-date information can be found on:
+http://open-osd.org
+
+Boaz Harrosh <bharrosh@panasas.com>
+Benny Halevy <bhalevy@panasas.com>
+
+References
+==========
+Weber, R., "SCSI Object-Based Storage Device Commands",
+T10/1355-D ANSI/INCITS 400-2004,
+http://www.t10.org/ftp/t10/drafts/osd/osd-r10.pdf
+
+Weber, R., "SCSI Object-Based Storage Device Commands -2 (OSD-2)"
+T10/1729-D, Working Draft, rev. 3
+http://www.t10.org/ftp/t10/drafts/osd2/osd2r03.pdf
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 17/18] osd: Kconfig file for in-tree builds
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Kconfig file for the drivers/scsi/osd subdirectory.
Adds the following config items:
	config SCSI_OSD_INITIATOR
	config SCSI_OSD_ULD
	config SCSI_OSD_DEBUG

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kconfig |   41 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 41 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kconfig

diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
new file mode 100644
index 0000000..ac3be8a
--- /dev/null
+++ b/drivers/scsi/osd/Kconfig
@@ -0,0 +1,41 @@
+#
+# Kernel configuration file for the OSD scsi protocol
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public version 2 License as
+# published by the Free Software Foundation
+#
+# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
+#        How is it done properly?
+#
+
+config SCSI_OSD_INITIATOR
+	tristate "OSD-Initiator library"
+	depends on SCSI
+	help
+		Enable the OSD-Initiator library (libosd.ko).
+		NOTE: You must also select CRYPTO_SHA1 + CRYPTO_HMAC and their
+		dependencies
+
+config SCSI_OSD_ULD
+	tristate "OSD Upper Level driver"
+	depends on SCSI_OSD_INITIATOR
+	help
+		Build a SCSI upper layer driver that exports /dev/osdX devices
+		to user-mode for testing and controlling OSD devices. It is also
+		needed by osdfs, for mounting an OSD based file system.
+
+config SCSI_OSD_DEBUG
+	bool "Compile All OSD modules with lots of DEBUG prints"
+	default n
+	depends on SCSI_OSD_INITIATOR
+	help
+		OSD Code is populated with lots of OSD_DEBUG(..) printouts to
+		dmesg. Enable this if you found a bug and you want to help us
+		track the problem (see also MAINTAINERS).
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 17/18] osd: Kconfig file for in-tree builds
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

Kconfig file for the drivers/scsi/osd subdirectory.
Adds the following config items:
	config SCSI_OSD_INITIATOR
	config SCSI_OSD_ULD
	config SCSI_OSD_DEBUG

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kconfig |   41 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 41 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kconfig

diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
new file mode 100644
index 0000000..ac3be8a
--- /dev/null
+++ b/drivers/scsi/osd/Kconfig
@@ -0,0 +1,41 @@
+#
+# Kernel configuration file for the OSD scsi protocol
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public version 2 License as
+# published by the Free Software Foundation
+#
+# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
+#        How is it done properly?
+#
+
+config SCSI_OSD_INITIATOR
+	tristate "OSD-Initiator library"
+	depends on SCSI
+	help
+		Enable the OSD-Initiator library (libosd.ko).
+		NOTE: You must also select CRYPTO_SHA1 + CRYPTO_HMAC and their
+		dependencies
+
+config SCSI_OSD_ULD
+	tristate "OSD Upper Level driver"
+	depends on SCSI_OSD_INITIATOR
+	help
+		Build a SCSI upper layer driver that exports /dev/osdX devices
+		to user-mode for testing and controlling OSD devices. It is also
+		needed by osdfs, for mounting an OSD based file system.
+
+config SCSI_OSD_DEBUG
+	bool "Compile All OSD modules with lots of DEBUG prints"
+	default n
+	depends on SCSI_OSD_INITIATOR
+	help
+		OSD Code is populated with lots of OSD_DEBUG(..) printouts to
+		dmesg. Enable this if you found a bug and you want to help us
+		track the problem (see also MAINTAINERS).
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 18/18] scsi: Add osd library to build system
  2008-11-04 16:09   ` Boaz Harrosh
@ 2008-11-04 16:44     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

OSD in kernel source code is assumed to be at:
drivers/scsi/osd/ with its own Makefile and Kconfig

Add includes to them from drivers/scsi Makefile and Kconfig
Add OSD to MAINTAINERS file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 MAINTAINERS           |   10 ++++++++++
 drivers/scsi/Kconfig  |    2 ++
 drivers/scsi/Makefile |    2 ++
 3 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 355c192..03da1e7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3153,6 +3153,16 @@ L:	orinoco-devel@lists.sourceforge.net
 W:	http://www.nongnu.org/orinoco/
 S:	Maintained
 
+OSD LIBRARY
+P:	Boaz Harrosh
+M:	bharrosh@panasas.com
+P:	Benny Halevy
+M:	bhalevy@panasas.com
+L:	osd-dev@open-osd.org
+W:	http://open-osd.org
+T:	git://git.open-osd.org/osd-lib.git
+S:	Maintained
+
 P54 WIRELESS DRIVER
 P:	Michael Wu
 M:	flamingice@sourmilk.net
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 403ecad..e6af21c 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1780,4 +1780,6 @@ source "drivers/scsi/pcmcia/Kconfig"
 
 source "drivers/scsi/device_handler/Kconfig"
 
+source "drivers/scsi/osd/Kconfig"
+
 endmenu
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 72fd504..1e49632 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -135,6 +135,8 @@ obj-$(CONFIG_CHR_DEV_SG)	+= sg.o
 obj-$(CONFIG_CHR_DEV_SCH)	+= ch.o
 obj-$(CONFIG_SCSI_ENCLOSURE)	+= ses.o
 
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += osd/
+
 # This goes last, so that "real" scsi devices probe earlier
 obj-$(CONFIG_SCSI_DEBUG)	+= scsi_debug.o
 
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 18/18] scsi: Add osd library to build system
@ 2008-11-04 16:44     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-04 16:44 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori
  Cc: linux-kernel, Sami.Iren, Pete Wyckoff

OSD in kernel source code is assumed to be at:
drivers/scsi/osd/ with its own Makefile and Kconfig

Add includes to them from drivers/scsi Makefile and Kconfig
Add OSD to MAINTAINERS file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 MAINTAINERS           |   10 ++++++++++
 drivers/scsi/Kconfig  |    2 ++
 drivers/scsi/Makefile |    2 ++
 3 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 355c192..03da1e7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3153,6 +3153,16 @@ L:	orinoco-devel@lists.sourceforge.net
 W:	http://www.nongnu.org/orinoco/
 S:	Maintained
 
+OSD LIBRARY
+P:	Boaz Harrosh
+M:	bharrosh@panasas.com
+P:	Benny Halevy
+M:	bhalevy@panasas.com
+L:	osd-dev@open-osd.org
+W:	http://open-osd.org
+T:	git://git.open-osd.org/osd-lib.git
+S:	Maintained
+
 P54 WIRELESS DRIVER
 P:	Michael Wu
 M:	flamingice@sourmilk.net
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 403ecad..e6af21c 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1780,4 +1780,6 @@ source "drivers/scsi/pcmcia/Kconfig"
 
 source "drivers/scsi/device_handler/Kconfig"
 
+source "drivers/scsi/osd/Kconfig"
+
 endmenu
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 72fd504..1e49632 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -135,6 +135,8 @@ obj-$(CONFIG_CHR_DEV_SG)	+= sg.o
 obj-$(CONFIG_CHR_DEV_SCH)	+= ch.o
 obj-$(CONFIG_SCSI_ENCLOSURE)	+= ses.o
 
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += osd/
+
 # This goes last, so that "real" scsi devices probe earlier
 obj-$(CONFIG_SCSI_DEBUG)	+= scsi_debug.o
 
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* Re: [PATCH 04/18] libosd: OSDv1 preliminary implementation
  2008-11-04 16:44   ` [PATCH 04/18] libosd: OSDv1 preliminary implementation Boaz Harrosh
@ 2008-11-04 18:03     ` Sam Ravnborg
  2008-11-05 13:12       ` Boaz Harrosh
  2008-11-05 16:39       ` [Patch] Always include <linux/types.h> Jörn Engel
  2008-11-04 19:16     ` [PATCH 04/18] libosd: OSDv1 preliminary implementation Andrew Morton
  2008-11-09 14:50     ` [PATCH 04/18 ver2] " Boaz Harrosh
  2 siblings, 2 replies; 183+ messages in thread
From: Sam Ravnborg @ 2008-11-04 18:03 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi, linux-kernel, Sami.Iren,
	Pete Wyckoff

On Tue, Nov 04, 2008 at 06:44:29PM +0200, Boaz Harrosh wrote:
> Implementation of the most basic OSD functionality and
> infrastructure. Mainly Format, Create/Remove Partition,
> Create/Remove Object, and read/write.
> 
> - Add Makefile and Kbuild to compile libosd.ko
> - osd_initiator.c Implementation file for osd_initiator.h
>   and osd_sec.h APIs
> - osd_debug.h - Some kprintf macro definitions

A few comments below.

	Sam


> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> Reviewed-by: Benny Halevy <bhalevy@panasas.com>
> ---
>  drivers/scsi/osd/Kbuild          |   26 +++
>  drivers/scsi/osd/Makefile        |   37 +++
>  drivers/scsi/osd/osd_debug.h     |   27 +++
>  drivers/scsi/osd/osd_initiator.c |  450 ++++++++++++++++++++++++++++++++++++++
>  4 files changed, 540 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/scsi/osd/Kbuild
>  create mode 100755 drivers/scsi/osd/Makefile
>  create mode 100644 drivers/scsi/osd/osd_debug.h
>  create mode 100644 drivers/scsi/osd/osd_initiator.c
> 
> diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
> new file mode 100644
> index 0000000..b4678e0
> --- /dev/null
> +++ b/drivers/scsi/osd/Kbuild
> @@ -0,0 +1,26 @@
> +#
> +# Kbuild for the OSD modules
> +#
> +# Copyright (C) 2008 Panasas Inc.  All rights reserved.
> +#
> +# Authors:
> +#   Boaz Harrosh <bharrosh@panasas.com>
> +#   Benny Halevy <bhalevy@panasas.com>
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License version 2
> +#
> +
> +ifneq ($(OSD_INC),)
> +# we are built out-of-tree Kconfigure everything as on
> +
> +CONFIG_SCSI_OSD_INITIATOR=m
> +EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
> +
> +EXTRA_CFLAGS += -I$(OSD_INC)
> +# EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_DEBUG
> +
> +endif
> +
> +libosd-objs := osd_initiator.o
> +obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o

When you submit for inclusion please clean this up.
1) use ccflags-y as replacement for EXTRA_CFLAGS
2) use libosd-y as replacement for libosd-objs

> +
> +#ifdef CONFIG_SCSI_OSD_INITIATOR_MODULE
> +MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
> +MODULE_DESCRIPTION("open-osd initiator library libosd.ko");
> +MODULE_LICENSE("GPL");
> +#endif

no ifdef around here.

> +void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
> +{
> +	memset(osdd, 0, sizeof(*osdd));
> +	osdd->scsi_dev = scsi_dev;
> +	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
> +	/* TODO: Allocate pools for osd_request attributes ... */
> +}
> +EXPORT_SYMBOL(osd_dev_init);
kernel-doc comments for all exported funtions / variables.



^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18] libosd: OSDv1 Headers
  2008-11-04 16:44     ` Boaz Harrosh
  (?)
@ 2008-11-04 19:10     ` Andrew Morton
  2008-11-04 19:42         ` Jörn Engel
  2008-11-05 12:54         ` Boaz Harrosh
  -1 siblings, 2 replies; 183+ messages in thread
From: Andrew Morton @ 2008-11-04 19:10 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James.Bottomley, michaelc, fujita.tomonori, jeff, osd-dev,
	linux-scsi, linux-kernel, Sami.Iren, pw

On Tue,  4 Nov 2008 18:44:06 +0200
Boaz Harrosh <bharrosh@panasas.com> wrote:

> Headers only patch.
> 
> osd_protocol.h
> 	Contains a C-fied definition of the T10 OSD standard
> osd_types.h
> 	Contains CPU order common used types
> osd_initiator.h
> 	API definition of the osd_initiator library
> osd_sec.h
> 	Contains High level API for the security manager.
> 
> [Note that checkpatch spews errors on things that are valid in this context
> and will not be fixed]
> 
> --- /dev/null
> +++ b/include/scsi/osd_initiator.h

This header uses quite a few things without including the header files
which define them.  That's a bit risky - it causes compile breakage
across architectures, across config changes and across time.

> @@ -0,0 +1,332 @@
> +/*
> + * osd_initiator.h - OSD initiator API definition
> + *
> + * Copyright (C) 2008 Panasas Inc.  All rights reserved.
> + *
> + * Authors:
> + *   Boaz Harrosh <bharrosh@panasas.com>
> + *   Benny Halevy <bhalevy@panasas.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + *
> + */
> +#ifndef __OSD_INITIATOR_H__
> +#define __OSD_INITIATOR_H__
> +
> +#include <linux/blkdev.h>
> +
> +#include "osd_protocol.h"
> +#include "osd_types.h"
> +
> +/* Note: "NI" in comments below means "Not Implemented yet" */
> +
> +/*
> + * Object-based Storage Device.
> + * This object represents an OSD device.
> + * It is not a full linux device in any way. It is only
> + * a place to hang resources associated with a Linux
> + * request Q and some default properties.
> + */
> +struct osd_dev {
> +	struct scsi_device *scsi_dev;

scsi_device

> +	unsigned def_timeout;
> +};
> +
> +void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
> +void osd_dev_fini(struct osd_dev *);
> +
> +struct osd_request;
> +typedef void (osd_req_done_fn)(struct osd_request *, void *);
> +
> +struct osd_request {
> +	struct osd_cdb cdb;
> +	struct osd_data_out_integrity_info out_data_integ;
> +	struct osd_data_in_integrity_info in_data_integ;
> +
> +	struct osd_dev *osd_dev;
> +	struct request *request;
> +
> +	struct _osd_req_data_segment {
> +		void *buff;
> +		unsigned alloc_size; /* 0 here means not allocated by us */
> +		unsigned total_bytes;
> +	} set_attr, enc_get_attr, get_attr;
> +
> +	struct _osd_io_info {
> +		struct bio *bio;
> +		u64 total_bytes;

u64(!)

> +		struct request *req;
> +		struct _osd_req_data_segment *last_seg;
> +		u8 *pad_buff;
> +	} out, in;
> +
> +	gfp_t alloc_flags;

gfp_t

> +	unsigned timeout;
> +	unsigned retries;
> +	u8 sense[OSD_MAX_SENSE_LEN];
> +	enum osd_attributes_mode attributes_mode;
> +
> +	osd_req_done_fn *async_done;
> +	void *async_private;
> +	int async_error;
> +};

etc, etc, etc.   Please review all that.

> +struct osd_request *osd_start_request(struct osd_dev *, gfp_t gfp);
> +int osd_finalize_request(struct osd_request *or,
> +	u8 options, const void *cap, const u8 *cap_key);
> +void osd_req_set_master_seed_xchg(struct osd_request *, ...);/* NI */
> +void osd_req_set_master_key(struct osd_request *, ...);/* NI */
> +void osd_req_format(struct osd_request *, u64 tot_capacity);
> +int osd_req_list_dev_partitions(struct osd_request *,
> +	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);

hm.  It appears that someone made the decision to omit the name from
the `struct osd_request *' parameter in the prototypes and to include
the argument names for all other arguments.

Not a bad idea, really.


^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 04/18] libosd: OSDv1 preliminary implementation
  2008-11-04 16:44   ` [PATCH 04/18] libosd: OSDv1 preliminary implementation Boaz Harrosh
  2008-11-04 18:03     ` Sam Ravnborg
@ 2008-11-04 19:16     ` Andrew Morton
  2008-11-05 13:44       ` Boaz Harrosh
  2008-11-09 14:50     ` [PATCH 04/18 ver2] " Boaz Harrosh
  2 siblings, 1 reply; 183+ messages in thread
From: Andrew Morton @ 2008-11-04 19:16 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James.Bottomley, michaelc, fujita.tomonori, jeff, osd-dev,
	linux-scsi, linux-kernel, Sami.Iren, pw

On Tue,  4 Nov 2008 18:44:29 +0200
Boaz Harrosh <bharrosh@panasas.com> wrote:

> Implementation of the most basic OSD functionality and
> infrastructure. Mainly Format, Create/Remove Partition,
> Create/Remove Object, and read/write.
> 
>
> ...
>
> +struct osd_request *_osd_request_alloc(gfp_t gfp)
> +{
> +	struct osd_request *or;
> +
> +	/* TODO: Use mempool with one saved request */
> +	or = kzalloc(sizeof(*or), gfp);
> +	return or;
> +}
> +
> +void _osd_request_free(struct osd_request *or)
> +{
> +	kfree(or);
> +}

These two functions can/should be made static.  Please generally check
for this.

Also it'd probably make sense to declare both these inline.  The
compiler _shoudl_ get it right, but stranger things have happened...

>
> ...
>
> +/*
> + * If osd_finalize_request() was called but the request was not executed through
> + * the block layer, then we must release BIOs.
> + */
> +static void _abort_unexecuted_bios(struct request *rq)
> +{
> +	struct bio *bio;
> +
> +	while ((bio = rq->bio) != NULL) {
> +		rq->bio = bio->bi_next;
> +		bio_endio(bio, 0);
> +	}
> +}

Boy, that's a scary function.  bye-bye data.



^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCHSET 00/18] open-osd: OSD Initiator library for Linux
  2008-11-04 16:09   ` Boaz Harrosh
                     ` (20 preceding siblings ...)
  (?)
@ 2008-11-04 19:19   ` Andrew Morton
  2008-11-05 13:56     ` Boaz Harrosh
  2008-11-09 14:58     ` Boaz Harrosh
  -1 siblings, 2 replies; 183+ messages in thread
From: Andrew Morton @ 2008-11-04 19:19 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James.Bottomley, michaelc, fujita.tomonori, jeff, osd-dev,
	linux-scsi, Sami.Iren, pw, linux-kernel, linux-next

On Tue, 04 Nov 2008 18:09:31 +0200
Boaz Harrosh <bharrosh@panasas.com> wrote:

> 
> Please consider for inclusion, an in-kernel OSD initiator
> library. Its main users are planned to be various OSD based file
> systems and the pNFS-Objects Layout Driver. (To be submitted soon)
>  
> To try out and run the library please visit
> http://open-osd.org and follow the instructions there.
> 
> The submitted patchset is also available via git at:
>    git://git.open-osd.org/linux-open-osd.git osd
>    http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=osd
> 
> Or a compact out-of-tree repository that includes sources 
> and some extras:
>    git://git.open-osd.org/open-osd.git master
>    http://git.open-osd.org/gitweb.cgi?p=open-osd.git;a=summary
> 
> ...
>
> We would like this to sit in -mm tree for a while to make sure it is compilable
> on all platform.

The best way to do that is to include your git tree in linux-next.  If
this code has a probably-will-be-merged-in-2.6.29 status then please
prepare a branch for Stephen to include in the linux-next lineup.


^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18] libosd: OSDv1 Headers
  2008-11-04 19:10     ` Andrew Morton
@ 2008-11-04 19:42         ` Jörn Engel
  2008-11-05 12:54         ` Boaz Harrosh
  1 sibling, 0 replies; 183+ messages in thread
From: Jörn Engel @ 2008-11-04 19:42 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Boaz Harrosh, James.Bottomley, michaelc, fujita.tomonori, jeff,
	osd-dev, linux-scsi, linux-kernel, Sami.Iren, pw

On Tue, 4 November 2008 11:10:37 -0800, Andrew Morton wrote:
> 
> etc, etc, etc.   Please review all that.

One easy way to review 98% is to include the header in an otherwise
empty foo.c and compile that.  The remaining 2% are hidden behind
different config options and architectures.  Although your header may be
fine on that front.

Jörn

-- 
He who knows others is wise.
He who knows himself is enlightened.
-- Lao Tsu

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18] libosd: OSDv1 Headers
@ 2008-11-04 19:42         ` Jörn Engel
  0 siblings, 0 replies; 183+ messages in thread
From: Jörn Engel @ 2008-11-04 19:42 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Boaz Harrosh, James.Bottomley, michaelc, fujita.tomonori, jeff,
	osd-dev, linux-scsi, linux-kernel, Sami.Iren, pw

On Tue, 4 November 2008 11:10:37 -0800, Andrew Morton wrote:
> 
> etc, etc, etc.   Please review all that.

One easy way to review 98% is to include the header in an otherwise
empty foo.c and compile that.  The remaining 2% are hidden behind
different config options and architectures.  Although your header may be
fine on that front.

Jörn

-- 
He who knows others is wise.
He who knows himself is enlightened.
-- Lao Tsu
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18] libosd: OSDv1 Headers
  2008-11-04 19:42         ` Jörn Engel
  (?)
@ 2008-11-04 20:29         ` Jörn Engel
  -1 siblings, 0 replies; 183+ messages in thread
From: Jörn Engel @ 2008-11-04 20:29 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Boaz Harrosh, James.Bottomley, michaelc, fujita.tomonori, jeff,
	osd-dev, linux-scsi, linux-kernel, Sami.Iren, pw

On Tue, 4 November 2008 20:42:40 +0100, Jörn Engel wrote:
> On Tue, 4 November 2008 11:10:37 -0800, Andrew Morton wrote:
> > 
> > etc, etc, etc.   Please review all that.
> 
> One easy way to review 98% is to include the header in an otherwise
> empty foo.c and compile that.  The remaining 2% are hidden behind
> different config options and architectures.  Although your header may be
> fine on that front.

Btw, running such a script on include/linux detects a lot of trouble
even with i386 allnoconfig.  Most of which looks it could be 'fixed' by
a drunken monkey inserting #includes.  But some of those #includes may
be fs.h and pull the kitchensink, adding tons of dependencies and some
compile time.

Unsure.

Jörn

-- 
Rules of Optimization:
Rule 1: Don't do it.
Rule 2 (for experts only): Don't do it yet.
-- M.A. Jackson

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18] libosd: OSDv1 Headers
  2008-11-04 19:10     ` Andrew Morton
@ 2008-11-05 12:54         ` Boaz Harrosh
  2008-11-05 12:54         ` Boaz Harrosh
  1 sibling, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-05 12:54 UTC (permalink / raw)
  To: Andrew Morton
  Cc: James.Bottomley, michaelc, fujita.tomonori, jeff, osd-dev,
	linux-scsi, linux-kernel, Sami.Iren, pw

Andrew Morton wrote:
> On Tue,  4 Nov 2008 18:44:06 +0200
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> Headers only patch.
>>
>> osd_protocol.h
>> 	Contains a C-fied definition of the T10 OSD standard
>> osd_types.h
>> 	Contains CPU order common used types
>> osd_initiator.h
>> 	API definition of the osd_initiator library
>> osd_sec.h
>> 	Contains High level API for the security manager.
>>
>> [Note that checkpatch spews errors on things that are valid in this context
>> and will not be fixed]
>>
>> --- /dev/null
>> +++ b/include/scsi/osd_initiator.h
> 
> This header uses quite a few things without including the header files
> which define them.  That's a bit risky - it causes compile breakage
> across architectures, across config changes and across time.
> 

It's OK. I'm very pedantic about these things.

The first header included at osd_initiator.c is this header precisely
for the check Jörn has suggested. What happens is that all the types
in osd_initiator.h are actually derived from osd_protocol.h below.
osd_protocol.h does include exactly what it needs. (Also checked)

The only new definitions used by this header are from linux/blkdev.h
hence included here.

(I will re-check that osd_protocol.h is self-sustained) 

>> @@ -0,0 +1,332 @@
>> +/*
>> + * osd_initiator.h - OSD initiator API definition
>> + *
>> + * Copyright (C) 2008 Panasas Inc.  All rights reserved.
>> + *
>> + * Authors:
>> + *   Boaz Harrosh <bharrosh@panasas.com>
>> + *   Benny Halevy <bhalevy@panasas.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2
>> + *
>> + */
>> +#ifndef __OSD_INITIATOR_H__
>> +#define __OSD_INITIATOR_H__
>> +
>> +#include <linux/blkdev.h>
>> +
>> +#include "osd_protocol.h"
>> +#include "osd_types.h"
>> +
>> +/* Note: "NI" in comments below means "Not Implemented yet" */
>> +
>> +/*
>> + * Object-based Storage Device.
>> + * This object represents an OSD device.
>> + * It is not a full linux device in any way. It is only
>> + * a place to hang resources associated with a Linux
>> + * request Q and some default properties.
>> + */
>> +struct osd_dev {
>> +	struct scsi_device *scsi_dev;
> 
> scsi_device
> 
>> +	unsigned def_timeout;
>> +};
>> +
>> +void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
>> +void osd_dev_fini(struct osd_dev *);
>> +
>> +struct osd_request;
>> +typedef void (osd_req_done_fn)(struct osd_request *, void *);
>> +
>> +struct osd_request {
>> +	struct osd_cdb cdb;
>> +	struct osd_data_out_integrity_info out_data_integ;
>> +	struct osd_data_in_integrity_info in_data_integ;
>> +
>> +	struct osd_dev *osd_dev;
>> +	struct request *request;
>> +
>> +	struct _osd_req_data_segment {
>> +		void *buff;
>> +		unsigned alloc_size; /* 0 here means not allocated by us */
>> +		unsigned total_bytes;
>> +	} set_attr, enc_get_attr, get_attr;
>> +
>> +	struct _osd_io_info {
>> +		struct bio *bio;
>> +		u64 total_bytes;
> 
> u64(!)
> 

Do you mean that I need to use __u64? or what do you mean?

I will change it. but just for curiosity, I have seen this mentioned
once before, but never understood. What's wrong with the uXX types?
I include linux/types.h and I get them as well as the __uXX set.
Why are we not suppose to use them? And if we are not, then why do
they exist? And also why the u8 is used everywhere but the u{16-64}
are not?

(Please for give me for attacking so strongly I just personally like
 them, style wise. I'm just sad to see them go ;) )

>> +		struct request *req;
>> +		struct _osd_req_data_segment *last_seg;
>> +		u8 *pad_buff;
>> +	} out, in;
>> +
>> +	gfp_t alloc_flags;
> 
> gfp_t
> 

I prefer my name. I've seen the gfp_t use in Kernel, but I needed
that name while thinking the code. But now it's OK I'll change it.
 
>> +	unsigned timeout;
>> +	unsigned retries;
>> +	u8 sense[OSD_MAX_SENSE_LEN];
>> +	enum osd_attributes_mode attributes_mode;
>> +
>> +	osd_req_done_fn *async_done;
>> +	void *async_private;
>> +	int async_error;
>> +};
> 
> etc, etc, etc.   Please review all that.
> 

You mean the uXX => __uXX? I'll change all that.

>> +struct osd_request *osd_start_request(struct osd_dev *, gfp_t gfp);
>> +int osd_finalize_request(struct osd_request *or,
>> +	u8 options, const void *cap, const u8 *cap_key);
>> +void osd_req_set_master_seed_xchg(struct osd_request *, ...);/* NI */
>> +void osd_req_set_master_key(struct osd_request *, ...);/* NI */
>> +void osd_req_format(struct osd_request *, u64 tot_capacity);
>> +int osd_req_list_dev_partitions(struct osd_request *,
>> +	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
> 
> hm.  It appears that someone made the decision to omit the name from
> the `struct osd_request *' parameter in the prototypes and to include
> the argument names for all other arguments.
> 
> Not a bad idea, really.
> 

It's a programing style thing. The "this" parameter name is dropped
for been obvious and redundant. I like to keep the Header files
most readable and self-documenting. I know that in C, the style is
to look at .c files for answers, but I borrowed the C++ way of
making it as easy as possible on the user and summarizing all exported
types and services at the header file. Not just for the sake of the compiler
but also for the reader.

Note that I put the kernel-doc comments in the header and not in the
source file.

Thank you for your comments
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18] libosd: OSDv1 Headers
@ 2008-11-05 12:54         ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-05 12:54 UTC (permalink / raw)
  To: Andrew Morton
  Cc: James.Bottomley, michaelc, fujita.tomonori, jeff, osd-dev,
	linux-scsi, linux-kernel, Sami.Iren, pw

Andrew Morton wrote:
> On Tue,  4 Nov 2008 18:44:06 +0200
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> Headers only patch.
>>
>> osd_protocol.h
>> 	Contains a C-fied definition of the T10 OSD standard
>> osd_types.h
>> 	Contains CPU order common used types
>> osd_initiator.h
>> 	API definition of the osd_initiator library
>> osd_sec.h
>> 	Contains High level API for the security manager.
>>
>> [Note that checkpatch spews errors on things that are valid in this context
>> and will not be fixed]
>>
>> --- /dev/null
>> +++ b/include/scsi/osd_initiator.h
> 
> This header uses quite a few things without including the header files
> which define them.  That's a bit risky - it causes compile breakage
> across architectures, across config changes and across time.
> 

It's OK. I'm very pedantic about these things.

The first header included at osd_initiator.c is this header precisely
for the check Jörn has suggested. What happens is that all the types
in osd_initiator.h are actually derived from osd_protocol.h below.
osd_protocol.h does include exactly what it needs. (Also checked)

The only new definitions used by this header are from linux/blkdev.h
hence included here.

(I will re-check that osd_protocol.h is self-sustained) 

>> @@ -0,0 +1,332 @@
>> +/*
>> + * osd_initiator.h - OSD initiator API definition
>> + *
>> + * Copyright (C) 2008 Panasas Inc.  All rights reserved.
>> + *
>> + * Authors:
>> + *   Boaz Harrosh <bharrosh@panasas.com>
>> + *   Benny Halevy <bhalevy@panasas.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2
>> + *
>> + */
>> +#ifndef __OSD_INITIATOR_H__
>> +#define __OSD_INITIATOR_H__
>> +
>> +#include <linux/blkdev.h>
>> +
>> +#include "osd_protocol.h"
>> +#include "osd_types.h"
>> +
>> +/* Note: "NI" in comments below means "Not Implemented yet" */
>> +
>> +/*
>> + * Object-based Storage Device.
>> + * This object represents an OSD device.
>> + * It is not a full linux device in any way. It is only
>> + * a place to hang resources associated with a Linux
>> + * request Q and some default properties.
>> + */
>> +struct osd_dev {
>> +	struct scsi_device *scsi_dev;
> 
> scsi_device
> 
>> +	unsigned def_timeout;
>> +};
>> +
>> +void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
>> +void osd_dev_fini(struct osd_dev *);
>> +
>> +struct osd_request;
>> +typedef void (osd_req_done_fn)(struct osd_request *, void *);
>> +
>> +struct osd_request {
>> +	struct osd_cdb cdb;
>> +	struct osd_data_out_integrity_info out_data_integ;
>> +	struct osd_data_in_integrity_info in_data_integ;
>> +
>> +	struct osd_dev *osd_dev;
>> +	struct request *request;
>> +
>> +	struct _osd_req_data_segment {
>> +		void *buff;
>> +		unsigned alloc_size; /* 0 here means not allocated by us */
>> +		unsigned total_bytes;
>> +	} set_attr, enc_get_attr, get_attr;
>> +
>> +	struct _osd_io_info {
>> +		struct bio *bio;
>> +		u64 total_bytes;
> 
> u64(!)
> 

Do you mean that I need to use __u64? or what do you mean?

I will change it. but just for curiosity, I have seen this mentioned
once before, but never understood. What's wrong with the uXX types?
I include linux/types.h and I get them as well as the __uXX set.
Why are we not suppose to use them? And if we are not, then why do
they exist? And also why the u8 is used everywhere but the u{16-64}
are not?

(Please for give me for attacking so strongly I just personally like
 them, style wise. I'm just sad to see them go ;) )

>> +		struct request *req;
>> +		struct _osd_req_data_segment *last_seg;
>> +		u8 *pad_buff;
>> +	} out, in;
>> +
>> +	gfp_t alloc_flags;
> 
> gfp_t
> 

I prefer my name. I've seen the gfp_t use in Kernel, but I needed
that name while thinking the code. But now it's OK I'll change it.
 
>> +	unsigned timeout;
>> +	unsigned retries;
>> +	u8 sense[OSD_MAX_SENSE_LEN];
>> +	enum osd_attributes_mode attributes_mode;
>> +
>> +	osd_req_done_fn *async_done;
>> +	void *async_private;
>> +	int async_error;
>> +};
> 
> etc, etc, etc.   Please review all that.
> 

You mean the uXX => __uXX? I'll change all that.

>> +struct osd_request *osd_start_request(struct osd_dev *, gfp_t gfp);
>> +int osd_finalize_request(struct osd_request *or,
>> +	u8 options, const void *cap, const u8 *cap_key);
>> +void osd_req_set_master_seed_xchg(struct osd_request *, ...);/* NI */
>> +void osd_req_set_master_key(struct osd_request *, ...);/* NI */
>> +void osd_req_format(struct osd_request *, u64 tot_capacity);
>> +int osd_req_list_dev_partitions(struct osd_request *,
>> +	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
> 
> hm.  It appears that someone made the decision to omit the name from
> the `struct osd_request *' parameter in the prototypes and to include
> the argument names for all other arguments.
> 
> Not a bad idea, really.
> 

It's a programing style thing. The "this" parameter name is dropped
for been obvious and redundant. I like to keep the Header files
most readable and self-documenting. I know that in C, the style is
to look at .c files for answers, but I borrowed the C++ way of
making it as easy as possible on the user and summarizing all exported
types and services at the header file. Not just for the sake of the compiler
but also for the reader.

Note that I put the kernel-doc comments in the header and not in the
source file.

Thank you for your comments
Boaz
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18] libosd: OSDv1 Headers
  2008-11-04 19:42         ` Jörn Engel
@ 2008-11-05 13:00           ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-05 13:00 UTC (permalink / raw)
  To: Jörn Engel
  Cc: Andrew Morton, James.Bottomley, michaelc, fujita.tomonori, jeff,
	osd-dev, linux-scsi, linux-kernel, Sami.Iren, pw

Jörn Engel wrote:
> On Tue, 4 November 2008 11:10:37 -0800, Andrew Morton wrote:
>> etc, etc, etc.   Please review all that.
> 
> One easy way to review 98% is to include the header in an otherwise
> empty foo.c and compile that.  The remaining 2% are hidden behind
> different config options and architectures.  Although your header may be
> fine on that front.
> 
> Jörn
> 

I have done just that. It's an old habit of mine. The very first
#include in osd_initiator.c is osd_initiator.h precisely for that.
So it's not just a one time test it's always tested.

Thanks
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18] libosd: OSDv1 Headers
@ 2008-11-05 13:00           ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-05 13:00 UTC (permalink / raw)
  To: Jörn Engel
  Cc: Andrew Morton, James.Bottomley, michaelc, fujita.tomonori, jeff,
	osd-dev, linux-scsi, linux-kernel, Sami.Iren, pw

Jörn Engel wrote:
> On Tue, 4 November 2008 11:10:37 -0800, Andrew Morton wrote:
>> etc, etc, etc.   Please review all that.
> 
> One easy way to review 98% is to include the header in an otherwise
> empty foo.c and compile that.  The remaining 2% are hidden behind
> different config options and architectures.  Although your header may be
> fine on that front.
> 
> Jörn
> 

I have done just that. It's an old habit of mine. The very first
#include in osd_initiator.c is osd_initiator.h precisely for that.
So it's not just a one time test it's always tested.

Thanks
Boaz
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18] libosd: OSDv1 Headers
  2008-11-05 12:54         ` Boaz Harrosh
  (?)
@ 2008-11-05 13:09         ` James Bottomley
  2008-11-05 13:29           ` Boaz Harrosh
  -1 siblings, 1 reply; 183+ messages in thread
From: James Bottomley @ 2008-11-05 13:09 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: Andrew Morton, michaelc, fujita.tomonori, jeff, osd-dev,
	linux-scsi, linux-kernel, Sami.Iren, pw

On Wed, 2008-11-05 at 14:54 +0200, Boaz Harrosh wrote:
> >> +    struct _osd_io_info {
> >> +            struct bio *bio;
> >> +            u64 total_bytes;
> > 
> > u64(!)
> > 
> 
> Do you mean that I need to use __u64? or what do you mean?

He means you've used u64 in a header without actually including any file
that defines the typedef.  Linux header files aren't supposed to depend
on include order.  They're supposed to stand alone.  The point is that
if I include just #include osd_initiator.h into an empty kernel file
it's not supposed to spit undefined errors.

Right at the moment the u64 probably works because blkdev.h #includes
the file which defines it, but you're not supposed to rely on that.

James



^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 04/18] libosd: OSDv1 preliminary implementation
  2008-11-04 18:03     ` Sam Ravnborg
@ 2008-11-05 13:12       ` Boaz Harrosh
  2008-11-09 14:55         ` [osd-dev] " Boaz Harrosh
  2008-11-05 16:39       ` [Patch] Always include <linux/types.h> Jörn Engel
  1 sibling, 1 reply; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-05 13:12 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: James Bottomley, Andrew Morton, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, open-osd ml, linux-scsi, linux-kernel, Sami.Iren,
	Pete Wyckoff

Sam Ravnborg wrote:

> On Tue, Nov 04, 2008 at 06:44:29PM +0200, Boaz Harrosh wrote:
>> Implementation of the most basic OSD functionality and
>> infrastructure. Mainly Format, Create/Remove Partition,
>> Create/Remove Object, and read/write.
>>
>> - Add Makefile and Kbuild to compile libosd.ko
>> - osd_initiator.c Implementation file for osd_initiator.h
>>   and osd_sec.h APIs
>> - osd_debug.h - Some kprintf macro definitions
> 
> A few comments below.
> 
> 	Sam
> 

Thanks Sam for looking

> 
>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>> Reviewed-by: Benny Halevy <bhalevy@panasas.com>
>> ---
>>  drivers/scsi/osd/Kbuild          |   26 +++
>>  drivers/scsi/osd/Makefile        |   37 +++
>>  drivers/scsi/osd/osd_debug.h     |   27 +++
>>  drivers/scsi/osd/osd_initiator.c |  450 ++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 540 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/scsi/osd/Kbuild
>>  create mode 100755 drivers/scsi/osd/Makefile
>>  create mode 100644 drivers/scsi/osd/osd_debug.h
>>  create mode 100644 drivers/scsi/osd/osd_initiator.c
>>
>> diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
>> new file mode 100644
>> index 0000000..b4678e0
>> --- /dev/null
>> +++ b/drivers/scsi/osd/Kbuild
>> @@ -0,0 +1,26 @@
>> +#
>> +# Kbuild for the OSD modules
>> +#
>> +# Copyright (C) 2008 Panasas Inc.  All rights reserved.
>> +#
>> +# Authors:
>> +#   Boaz Harrosh <bharrosh@panasas.com>
>> +#   Benny Halevy <bhalevy@panasas.com>
>> +#
>> +# This program is free software; you can redistribute it and/or modify
>> +# it under the terms of the GNU General Public License version 2
>> +#
>> +
>> +ifneq ($(OSD_INC),)
>> +# we are built out-of-tree Kconfigure everything as on
>> +
>> +CONFIG_SCSI_OSD_INITIATOR=m
>> +EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
>> +
>> +EXTRA_CFLAGS += -I$(OSD_INC)
>> +# EXTRA_CFLAGS += -DCONFIG_SCSI_OSD_DEBUG
>> +
>> +endif
>> +
>> +libosd-objs := osd_initiator.o
>> +obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
> 
> When you submit for inclusion please clean this up.
> 1) use ccflags-y as replacement for EXTRA_CFLAGS
> 2) use libosd-y as replacement for libosd-objs
> 

This is a most valuable information thanks. I have copy
pasted these stuff, while learning. I guess from the wrong
example. Thanks it looks much more logical that way.

>> +
>> +#ifdef CONFIG_SCSI_OSD_INITIATOR_MODULE
>> +MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
>> +MODULE_DESCRIPTION("open-osd initiator library libosd.ko");
>> +MODULE_LICENSE("GPL");
>> +#endif
> 
> no ifdef around here.
> 

Grate, thanks. Again the wrong copy-paste.

>> +void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_dev)
>> +{
>> +	memset(osdd, 0, sizeof(*osdd));
>> +	osdd->scsi_dev = scsi_dev;
>> +	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
>> +	/* TODO: Allocate pools for osd_request attributes ... */
>> +}
>> +EXPORT_SYMBOL(osd_dev_init);
> kernel-doc comments for all exported funtions / variables.
> 

I have some kernel-doc comments of exported functions in the Header
file. I have not yet finished all of them. (Laziness on my part).

Are kernel-doc comments in headers a big NO-NO. I like it this way,
so when I have to learn a new Library all the information
I need to know is in the header. Also the header is a much better place
when you do programing by shopping, that is you don't know what you need
and you look for what's available.

Thanks
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18] libosd: OSDv1 Headers
  2008-11-05 13:09         ` James Bottomley
@ 2008-11-05 13:29           ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-05 13:29 UTC (permalink / raw)
  To: James Bottomley
  Cc: Andrew Morton, michaelc, fujita.tomonori, jeff, osd-dev,
	linux-scsi, linux-kernel, Sami.Iren, pw

James Bottomley wrote:
> On Wed, 2008-11-05 at 14:54 +0200, Boaz Harrosh wrote:
>>>> +    struct _osd_io_info {
>>>> +            struct bio *bio;
>>>> +            u64 total_bytes;
>>> u64(!)
>>>
>> Do you mean that I need to use __u64? or what do you mean?
> 
> He means you've used u64 in a header without actually including any file
> that defines the typedef.  Linux header files aren't supposed to depend
> on include order.  They're supposed to stand alone.  The point is that
> if I include just #include osd_initiator.h into an empty kernel file
> it's not supposed to spit undefined errors.
> 
> Right at the moment the u64 probably works because blkdev.h #includes
> the file which defines it, but you're not supposed to rely on that.
> 
> James
> 

I have addressed that issue. The osd_initiator.h includes the
osd_protocol.h file. osd_protocol.h does include all the types
needed. All of the osd_initiator.h types are derived from
osd_protocol.h, the only added definitions are from blkdev.h.

The very first #include in osd_initiator.c is osd_initiator.h
which preforms exactly the check you suggest.

Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 04/18] libosd: OSDv1 preliminary implementation
  2008-11-04 19:16     ` [PATCH 04/18] libosd: OSDv1 preliminary implementation Andrew Morton
@ 2008-11-05 13:44       ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-05 13:44 UTC (permalink / raw)
  To: Andrew Morton
  Cc: James.Bottomley, michaelc, fujita.tomonori, jeff, osd-dev,
	linux-scsi, linux-kernel, Sami.Iren, pw

Andrew Morton wrote:
> On Tue,  4 Nov 2008 18:44:29 +0200
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> Implementation of the most basic OSD functionality and
>> infrastructure. Mainly Format, Create/Remove Partition,
>> Create/Remove Object, and read/write.
>>
>>
>> ...
>>
>> +struct osd_request *_osd_request_alloc(gfp_t gfp)
>> +{
>> +	struct osd_request *or;
>> +
>> +	/* TODO: Use mempool with one saved request */
>> +	or = kzalloc(sizeof(*or), gfp);
>> +	return or;
>> +}
>> +
>> +void _osd_request_free(struct osd_request *or)
>> +{
>> +	kfree(or);
>> +}
> 
> These two functions can/should be made static.  Please generally check
> for this.
> 

Thanks, I usually do, but these are from the last iteration and were
rushed in. Will fix.

> Also it'd probably make sense to declare both these inline.  The
> compiler _shoudl_ get it right, but stranger things have happened...
> 

I do not inline them, because one - I will use mem_pools very soon they
are just place holders for now. two - I let the compiler
do that, I made sure the only user is below the definition and I let
the compiler decide. I like to leave these things controlled from outside,
so when I compile a UML kernel and finally need to fire up a debugger,
I can un-inline them very easily.

(This is why I hate forward declarations. If they are not used
 it is a proof that inlineing of single callers will always happen.)

>> ...
>>
>> +/*
>> + * If osd_finalize_request() was called but the request was not executed through
>> + * the block layer, then we must release BIOs.
>> + */
>> +static void _abort_unexecuted_bios(struct request *rq)
>> +{
>> +	struct bio *bio;
>> +
>> +	while ((bio = rq->bio) != NULL) {
>> +		rq->bio = bio->bi_next;
>> +		bio_endio(bio, 0);
>> +	}
>> +}
> 
> Boy, that's a scary function.  bye-bye data.
> 

Thank's for mentioning that. I use it at the very end just before
the de-allocation of the block request. What happens today is: that
if for some reason the driver failed to call blk_end_request, 
or in this case the driver was never called, the last blk_put_request()
will leak BIOs. There are currently corner cases and bugs in the Kernel
that cause exactly that.

That loop above should be moved from here to inside blk_put_request().
if some one needs to hold the BIOs longer then the life span of the request they
should simply inc-ref them.

Note that here it is totally safe since It's only called just before
blk_put_request().

This code is actually a bug fix, for the error cases when a request is allocated
but is never executed do to other error returns.

Thanks
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCHSET 00/18] open-osd: OSD Initiator library for Linux
  2008-11-04 19:19   ` [PATCHSET 00/18] open-osd: OSD Initiator library for Linux Andrew Morton
@ 2008-11-05 13:56     ` Boaz Harrosh
  2008-11-09 14:58     ` Boaz Harrosh
  1 sibling, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-05 13:56 UTC (permalink / raw)
  To: Andrew Morton
  Cc: James.Bottomley, michaelc, fujita.tomonori, jeff, osd-dev,
	linux-scsi, Sami.Iren, pw, linux-kernel, linux-next

Andrew Morton wrote:
> On Tue, 04 Nov 2008 18:09:31 +0200
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> Please consider for inclusion, an in-kernel OSD initiator
>> library. Its main users are planned to be various OSD based file
>> systems and the pNFS-Objects Layout Driver. (To be submitted soon)
>>  
>> To try out and run the library please visit
>> http://open-osd.org and follow the instructions there.
>>
>> The submitted patchset is also available via git at:
>>    git://git.open-osd.org/linux-open-osd.git osd
>>    http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=osd
>>
>> Or a compact out-of-tree repository that includes sources 
>> and some extras:
>>    git://git.open-osd.org/open-osd.git master
>>    http://git.open-osd.org/gitweb.cgi?p=open-osd.git;a=summary
>>
>> ...
>>
>> We would like this to sit in -mm tree for a while to make sure it is compilable
>> on all platform.
> 
> The best way to do that is to include your git tree in linux-next.  If
> this code has a probably-will-be-merged-in-2.6.29 status then please
> prepare a branch for Stephen to include in the linux-next lineup.
> 

Thanks Andrew
I was thinking this code would eventually go into Linux-next threw
James tree. But thought if there was a way for some exposure, so to
give James some confidence in the code before he commits to it. But
this way it could be perfect, thanks.

Stephen Hi
I have just that branch ready it is:
git://git.open-osd.org/linux-open-osd.git osd
Note the "osd" branch. Do I need to call it something special like
"linux-next"? (Give me 24 hours to fix all current comments)

Also one more question. This tree is based on latest scsi-misc-2.6.git,
Because it is destined to go threw James tree at the end. Do I need
to prepare a special tree based on Linus-latest?

Thanks in advance
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* [Patch] Always include <linux/types.h>
  2008-11-04 18:03     ` Sam Ravnborg
  2008-11-05 13:12       ` Boaz Harrosh
@ 2008-11-05 16:39       ` Jörn Engel
  2008-11-05 17:23         ` Alexey Dobriyan
  2008-11-05 17:48         ` Boaz Harrosh
  1 sibling, 2 replies; 183+ messages in thread
From: Jörn Engel @ 2008-11-05 16:39 UTC (permalink / raw)
  To: Sam Ravnborg; +Cc: Andrew Morton, linux-kernel

Hardly any file in the kernel can be compiled without including
<linux/types.h>, directly or indirectly.  And I'd wager a beer that
noone can find a non-trivial example.  I couldn't.

So instead of sprinkling even more #include <linux/types.h> everywhere -
140 headers in include/linux/ would need that to compile standalone -
let us just pass it automatically.

The existing 4000 odd includes for types.h, plus some 300 each for
compiler.h and stddef.h, which get pulled through types.h, can get
removed at leasure.

diff --git a/Makefile b/Makefile
index 6192922..8a3fb66 100644
--- a/Makefile
+++ b/Makefile
@@ -326,7 +326,8 @@ AFLAGS_KERNEL	=
 # Needed to be compatible with the O= option
 LINUXINCLUDE    := -Iinclude \
                    $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
-		   -include include/linux/autoconf.h
+		   -include include/linux/autoconf.h \
+		   -include include/linux/types.h
 
 KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
 

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* Re: [Patch] Always include <linux/types.h>
  2008-11-05 16:39       ` [Patch] Always include <linux/types.h> Jörn Engel
@ 2008-11-05 17:23         ` Alexey Dobriyan
  2008-11-05 19:16           ` Jörn Engel
  2008-11-05 17:48         ` Boaz Harrosh
  1 sibling, 1 reply; 183+ messages in thread
From: Alexey Dobriyan @ 2008-11-05 17:23 UTC (permalink / raw)
  To: Jörn Engel; +Cc: Sam Ravnborg, Andrew Morton, linux-kernel

On Wed, Nov 05, 2008 at 05:39:41PM +0100, Jörn Engel wrote:
> Hardly any file in the kernel can be compiled without including
> <linux/types.h>, directly or indirectly.  And I'd wager a beer that
> noone can find a non-trivial example.  I couldn't.
> 
> So instead of sprinkling even more #include <linux/types.h> everywhere -
> 140 headers in include/linux/ would need that to compile standalone -
> let us just pass it automatically.
> 
> The existing 4000 odd includes for types.h, plus some 300 each for
> compiler.h and stddef.h, which get pulled through types.h, can get
> removed at leasure.
> 
> --- a/Makefile
> +++ b/Makefile
> @@ -326,7 +326,8 @@ AFLAGS_KERNEL	=
>  # Needed to be compatible with the O= option
>  LINUXINCLUDE    := -Iinclude \
>                     $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
> -		   -include include/linux/autoconf.h
> +		   -include include/linux/autoconf.h \
> +		   -include include/linux/types.h

This is only going to slow down compilation and types.h is not causing much
compilation problems, in fact, I can't recall a compilation problem due to
types.h. Contary to config.h situation which was a pain.

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [Patch] Always include <linux/types.h>
  2008-11-05 16:39       ` [Patch] Always include <linux/types.h> Jörn Engel
  2008-11-05 17:23         ` Alexey Dobriyan
@ 2008-11-05 17:48         ` Boaz Harrosh
  1 sibling, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-05 17:48 UTC (permalink / raw)
  To: Jörn Engel; +Cc: Sam Ravnborg, Andrew Morton, linux-kernel

Jörn Engel wrote:
> Hardly any file in the kernel can be compiled without including
> <linux/types.h>, directly or indirectly.  And I'd wager a beer that
> noone can find a non-trivial example.  I couldn't.
> 
> So instead of sprinkling even more #include <linux/types.h> everywhere -
> 140 headers in include/linux/ would need that to compile standalone -
> let us just pass it automatically.
> 
> The existing 4000 odd includes for types.h, plus some 300 each for
> compiler.h and stddef.h, which get pulled through types.h, can get
> removed at leasure.
> 
> diff --git a/Makefile b/Makefile
> index 6192922..8a3fb66 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -326,7 +326,8 @@ AFLAGS_KERNEL	=
>  # Needed to be compatible with the O= option
>  LINUXINCLUDE    := -Iinclude \
>                     $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
> -		   -include include/linux/autoconf.h
> +		   -include include/linux/autoconf.h \
> +		   -include include/linux/types.h
>  
>  KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
>  
> --

I think that if:
[A]
<header1.h>
/* no includes pure level A header */
</header1.h>

[B]
<header2.h>
#include "header1.h"
/* Level B header depends on level A */
</header2.h>

[C]
<header3.h>
#include "header2.h"
use some types of header1.h
/* Level C header depends on level B */
</header3.h>

[D]
<source.c>
#include "header3.h"
use types from A, B, C
</source.c>

Then that's fine any other file that includes any one of A, B, or C will have
no problem compiling and headers include order does not matter. Actually it is
nice, since the reader of header3.h knows that it is derived/dependent work of
header2.h.

Now what happens in the future when at B #include "header1.h" is removed.
At C header3.h stops compiling. So here I think it is the programmer's decision.
If he thinks that usage of A types used at C are do to B and if B's implementation
changes to use another set of types, then also C should change with it. Then leave
it as above. If the programmer decides that there is independent use of A types
in C unrelated to B, then he should also include A directly. If in doubt just don't
include it.

In any case I'm still not breaking the self-contained / order-independent headers
rule.

So please don't do that, Most of these places you found are the A-B-C case

Just my $0.017
Boaz


^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [Patch] Always include <linux/types.h>
  2008-11-05 17:23         ` Alexey Dobriyan
@ 2008-11-05 19:16           ` Jörn Engel
  2008-11-05 19:48             ` Andreas Schwab
                               ` (2 more replies)
  0 siblings, 3 replies; 183+ messages in thread
From: Jörn Engel @ 2008-11-05 19:16 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: Sam Ravnborg, Andrew Morton, linux-kernel

[ Threading should have been broken.  Doh! ]

On Wed, 5 November 2008 20:23:12 +0300, Alexey Dobriyan wrote:
> On Wed, Nov 05, 2008 at 05:39:41PM +0100, Jörn Engel wrote:
> > Hardly any file in the kernel can be compiled without including
> > <linux/types.h>, directly or indirectly.  And I'd wager a beer that
> > noone can find a non-trivial example.  I couldn't.
> 
> This is only going to slow down compilation and types.h is not causing much
> compilation problems, in fact, I can't recall a compilation problem due to
> types.h. Contary to config.h situation which was a pain.

My hope was actually to speed up compilation.  If the average c file
includes 10 headers, on types.h will get included by most of them,
possibly multiple times.  Each run after the first still has to parse
the whole file, just to drop everything between  #ifndef _LINUX_TYPES_H
and #endif.

By passing types.h on the command line we can drop it from all headers
and only have to parse it once.  Just the intermediate step of parsing
types.h 11 times instead of 10 will slow things down.  By about .4% on
my not very beefy notebook.

Before:
real    4m33.241s
user    3m58.524s
sys     0m18.539s

After:
real    4m29.707s
user    3m59.674s
sys     0m18.182s

And while testing this I noticed that a_flags shouldn't include the
file.  Updated patch below.

Jörn

-- 
to show off how geeky they were.
-- Rob Enderle

diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index ea48b82..328f345 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -121,7 +121,8 @@ endif
 
 c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \
 		 $(__c_flags) $(modkern_cflags) \
-		 -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
+		 -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) \
+                 -include include/linux/types.h
 
 a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \
 		 $(__a_flags) $(modkern_aflags)

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* Re: [Patch] Always include <linux/types.h>
  2008-11-05 19:16           ` Jörn Engel
@ 2008-11-05 19:48             ` Andreas Schwab
  2008-11-05 20:02             ` Jörn Engel
  2008-11-05 20:20             ` Alexey Dobriyan
  2 siblings, 0 replies; 183+ messages in thread
From: Andreas Schwab @ 2008-11-05 19:48 UTC (permalink / raw)
  To: Jörn Engel
  Cc: Alexey Dobriyan, Sam Ravnborg, Andrew Morton, linux-kernel

Jörn Engel <joern@logfs.org> writes:

> My hope was actually to speed up compilation.  If the average c file
> includes 10 headers, on types.h will get included by most of them,
> possibly multiple times.  Each run after the first still has to parse
> the whole file, just to drop everything between  #ifndef _LINUX_TYPES_H
> and #endif.

Actually GCC is smart enought to note the bracketing and avoid even
looking at it a second time.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [Patch] Always include <linux/types.h>
  2008-11-05 19:16           ` Jörn Engel
  2008-11-05 19:48             ` Andreas Schwab
@ 2008-11-05 20:02             ` Jörn Engel
  2008-11-05 20:32               ` Alexey Dobriyan
  2008-11-05 20:20             ` Alexey Dobriyan
  2 siblings, 1 reply; 183+ messages in thread
From: Jörn Engel @ 2008-11-05 20:02 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: Sam Ravnborg, Andrew Morton, linux-kernel

On Wed, 5 November 2008 20:16:28 +0100, Jörn Engel wrote:
> 
> My hope was actually to speed up compilation.  If the average c file
> includes 10 headers, on types.h will get included by most of them,
> possibly multiple times.  Each run after the first still has to parse
> the whole file, just to drop everything between  #ifndef _LINUX_TYPES_H
> and #endif.
> 
> By passing types.h on the command line we can drop it from all headers
> and only have to parse it once.  Just the intermediate step of parsing
> types.h 11 times instead of 10 will slow things down.  By about .4% on
> my not very beefy notebook.
> 
> Before:
> real    4m33.241s
> user    3m58.524s
> sys     0m18.539s
> 
> After:
> real    4m29.707s
> user    3m59.674s
> sys     0m18.182s

And after removing all explicit #include <linux/types.h> from headers:
real    4m31.946s
user    3m59.521s
sys     0m18.752s

All this may be lost in the noise.  The build machine wasn't completely
idle and the variation in system time is rather random.  So it neither
helps nor hurts much.  Nor does it solve any real problem.

We might just as well drop it, I guess.

Jörn

-- 
The story so far:
In the beginning the Universe was created.  This has made a lot
of people very angry and been widely regarded as a bad move.
-- Douglas Adams

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [Patch] Always include <linux/types.h>
  2008-11-05 19:16           ` Jörn Engel
  2008-11-05 19:48             ` Andreas Schwab
  2008-11-05 20:02             ` Jörn Engel
@ 2008-11-05 20:20             ` Alexey Dobriyan
  2 siblings, 0 replies; 183+ messages in thread
From: Alexey Dobriyan @ 2008-11-05 20:20 UTC (permalink / raw)
  To: Jörn Engel; +Cc: Sam Ravnborg, Andrew Morton, linux-kernel

On Wed, Nov 05, 2008 at 08:16:29PM +0100, Jörn Engel wrote:
> [ Threading should have been broken.  Doh! ]
> 
> On Wed, 5 November 2008 20:23:12 +0300, Alexey Dobriyan wrote:
> > On Wed, Nov 05, 2008 at 05:39:41PM +0100, Jörn Engel wrote:
> > > Hardly any file in the kernel can be compiled without including
> > > <linux/types.h>, directly or indirectly.  And I'd wager a beer that
> > > noone can find a non-trivial example.  I couldn't.
> > 
> > This is only going to slow down compilation and types.h is not causing much
> > compilation problems, in fact, I can't recall a compilation problem due to
> > types.h. Contary to config.h situation which was a pain.
> 
> My hope was actually to speed up compilation.  If the average c file
> includes 10 headers, on types.h will get included by most of them,
> possibly multiple times.  Each run after the first still has to parse
> the whole file, just to drop everything between  #ifndef _LINUX_TYPES_H
> and #endif.
> 
> By passing types.h on the command line we can drop it from all headers
> and only have to parse it once.  Just the intermediate step of parsing
> types.h 11 times instead of 10 will slow things down.  By about .4% on
> my not very beefy notebook.
> 
> Before:
> real    4m33.241s
> user    3m58.524s
> sys     0m18.539s
> 
> After:
> real    4m29.707s
> user    3m59.674s
> sys     0m18.182s

Could be anything.

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [Patch] Always include <linux/types.h>
  2008-11-05 20:02             ` Jörn Engel
@ 2008-11-05 20:32               ` Alexey Dobriyan
  2008-11-07  8:02                 ` Jörn Engel
  0 siblings, 1 reply; 183+ messages in thread
From: Alexey Dobriyan @ 2008-11-05 20:32 UTC (permalink / raw)
  To: Jörn Engel; +Cc: Sam Ravnborg, Andrew Morton, linux-kernel

On Wed, Nov 05, 2008 at 09:02:17PM +0100, Jörn Engel wrote:
> On Wed, 5 November 2008 20:16:28 +0100, Jörn Engel wrote:
> > 
> > My hope was actually to speed up compilation.  If the average c file
> > includes 10 headers, on types.h will get included by most of them,
> > possibly multiple times.  Each run after the first still has to parse
> > the whole file, just to drop everything between  #ifndef _LINUX_TYPES_H
> > and #endif.
> > 
> > By passing types.h on the command line we can drop it from all headers
> > and only have to parse it once.  Just the intermediate step of parsing
> > types.h 11 times instead of 10 will slow things down.  By about .4% on
> > my not very beefy notebook.
> > 
> > Before:
> > real    4m33.241s
> > user    3m58.524s
> > sys     0m18.539s
> > 
> > After:
> > real    4m29.707s
> > user    3m59.674s
> > sys     0m18.182s
> 
> And after removing all explicit #include <linux/types.h> from headers:
> real    4m31.946s
> user    3m59.521s
> sys     0m18.752s
> 
> All this may be lost in the noise.  The build machine wasn't completely
> idle and the variation in system time is rather random.  So it neither
> helps nor hurts much.  Nor does it solve any real problem.
> 
> We might just as well drop it, I guess.

If you are working on improving compile times, it's better concentrate
on removing unneeded includes. If just removing "extern"s from prototypes
can reliably save several seconds, reducing headers can do wonders.

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [Patch] Always include <linux/types.h>
  2008-11-05 20:32               ` Alexey Dobriyan
@ 2008-11-07  8:02                 ` Jörn Engel
  0 siblings, 0 replies; 183+ messages in thread
From: Jörn Engel @ 2008-11-07  8:02 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: Sam Ravnborg, Andrew Morton, linux-kernel

On Wed, 5 November 2008 23:32:12 +0300, Alexey Dobriyan wrote:
> 
> If you are working on improving compile times, it's better concentrate
> on removing unneeded includes. If just removing "extern"s from prototypes
> can reliably save several seconds, reducing headers can do wonders.

My goal was more to assume we want all headers to compile standalone and
see where that would lead.  Result for include/linux/ was some 500 added
lines, 170 of which were to add types.h or compiler.h.  Another 50-100
further includes were fairly well-spread across the spectrum.  The
remainder was declarations like
struct super_block;

Overall we have three evils to choose from.  Headers with unresolved
dependencies lead to random compile breakage after removing a header
from some .c file.  Even if the change was tested, it can still break
for some config/architecture combination month down the line.

Sprinkling more includes throughout the headers increase compile time.
And the common practice of declaring a structure instead of including
the header is a pita when working with ctags.  The last problem is
particularly annoying since I have no idea what problem this warning is
supposed to solve:
In file included from include/linux/coda_cache.c:1:
include/linux/coda_cache.h:18: warning: ‘struct super_block’ declared inside parameter list
include/linux/coda_cache.h:18: warning: its scope is only this definition or declaration, which is probably not what you want

Should we just teach gcc to shut up about that one?

Jörn

-- 
Anything that can go wrong, will.
-- Finagle's Law

^ permalink raw reply	[flat|nested] 183+ messages in thread

* [PATCH 04/18 ver2] libosd: OSDv1 preliminary implementation
  2008-11-04 16:44   ` [PATCH 04/18] libosd: OSDv1 preliminary implementation Boaz Harrosh
  2008-11-04 18:03     ` Sam Ravnborg
  2008-11-04 19:16     ` [PATCH 04/18] libosd: OSDv1 preliminary implementation Andrew Morton
@ 2008-11-09 14:50     ` Boaz Harrosh
  2 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-09 14:50 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Jörn Engel, Sam Ravnborg
  Cc: open-osd development, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, linux-scsi, Sami.Iren, linux-kernel


Implementation of the most basic OSD functionality and
infrastructure. Mainly Format, Create/Remove Partition,
Create/Remove Object, and read/write.

- Add Makefile and Kbuild to compile libosd.ko
- osd_initiator.c Implementation file for osd_initiator.h
  and osd_sec.h APIs
- osd_debug.h - Some kprintf macro definitions

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild          |   26 +++
 drivers/scsi/osd/Makefile        |   37 +++
 drivers/scsi/osd/osd_debug.h     |   27 +++
 drivers/scsi/osd/osd_initiator.c |  448 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 538 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kbuild
 create mode 100755 drivers/scsi/osd/Makefile
 create mode 100644 drivers/scsi/osd/osd_debug.h
 create mode 100644 drivers/scsi/osd/osd_initiator.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
new file mode 100644
index 0000000..b6328e6
--- /dev/null
+++ b/drivers/scsi/osd/Kbuild
@@ -0,0 +1,26 @@
+#
+# Kbuild for the OSD modules
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+
+ifneq ($(OSD_INC),)
+# we are built out-of-tree Kconfigure everything as on
+
+CONFIG_SCSI_OSD_INITIATOR=m
+ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
+
+ccflags-y += -I$(OSD_INC)
+# ccflags-y += -DCONFIG_SCSI_OSD_DEBUG
+endif
+
+# libosd.ko - osd-initiator library
+libosd-y := osd_initiator.o
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile
new file mode 100755
index 0000000..d905344
--- /dev/null
+++ b/drivers/scsi/osd/Makefile
@@ -0,0 +1,37 @@
+#
+# Makefile for the OSD modules (out of tree)
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+# This Makefile is used to call the kernel Makefile in case of an out-of-tree
+# build.
+# $KSRC should point to a Kernel source tree otherwise host's default is
+# used. (eg. /lib/modules/`uname -r`/build)
+
+# include path for out-of-tree Headers
+OSD_INC ?= `pwd`/../../../include
+
+# allow users to override these
+# e.g. to compile for a kernel that you aren't currently running
+KSRC ?= /lib/modules/$(shell uname -r)/build
+KBUILD_OUTPUT ?=
+ARCH ?=
+V ?= 0
+
+# this is the basic Kbuild out-of-tree invocation, with the M= option
+KBUILD_BASE = +$(MAKE) -C $(KSRC) M=`pwd` KBUILD_OUTPUT=$(KBUILD_OUTPUT) ARCH=$(ARCH) V=$(V)
+
+all: libosd
+
+libosd: ;
+	$(KBUILD_BASE) OSD_INC=$(OSD_INC) modules
+
+clean:
+	$(KBUILD_BASE) clean
diff --git a/drivers/scsi/osd/osd_debug.h b/drivers/scsi/osd/osd_debug.h
new file mode 100644
index 0000000..0bc65fa
--- /dev/null
+++ b/drivers/scsi/osd/osd_debug.h
@@ -0,0 +1,27 @@
+/*
+ * osd_debug.h - Some kprintf macros
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_DEBUG_H__
+#define __OSD_DEBUG_H__
+
+#define OSD_ERR(fmt, a...) printk(KERN_ERR "osd: " fmt, ##a)
+#define OSD_INFO(fmt, a...) printk(KERN_NOTICE "osd: " fmt, ##a)
+
+#ifdef CONFIG_SCSI_OSD_DEBUG
+#define OSD_DEBUG(fmt, a...) \
+	printk(KERN_NOTICE "osd @%s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define OSD_DEBUG(fmt, a...) do {} while (0)
+#endif
+
+#endif /* ndef __OSD_DEBUG_H__ */
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
new file mode 100644
index 0000000..63b8a91
--- /dev/null
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -0,0 +1,448 @@
+/*
+ * osd_initiator - Main body of the osd initiator library.
+ *
+ * Note: The file does not contain the advanced security functionality which
+ * is only needed by the security_manager's initiators.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+#include <scsi/scsi_device.h>
+
+#include "osd_debug.h"
+
+enum { OSD_REQ_RETRIES = 1 };
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd initiator library libosd.ko");
+MODULE_LICENSE("GPL");
+
+static inline void build_test(void)
+{
+	/* structures were not packed */
+	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
+}
+
+static unsigned _osd_req_cdb_len(struct osd_request *or)
+{
+	return OSDv1_TOTAL_CDB_LEN;
+}
+
+void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
+{
+	memset(osdd, 0, sizeof(*osdd));
+	osdd->scsi_device = scsi_device;
+	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+	/* TODO: Allocate pools for osd_request attributes ... */
+}
+EXPORT_SYMBOL(osd_dev_init);
+
+void osd_dev_fini(struct osd_dev *osdd)
+{
+	/* TODO: De-allocate pools */
+
+	osdd->scsi_device = NULL;
+}
+EXPORT_SYMBOL(osd_dev_fini);
+
+static struct osd_request *_osd_request_alloc(gfp_t gfp)
+{
+	struct osd_request *or;
+
+	/* TODO: Use mempool with one saved request */
+	or = kzalloc(sizeof(*or), gfp);
+	return or;
+}
+
+static void _osd_request_free(struct osd_request *or)
+{
+	kfree(or);
+}
+
+struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp)
+{
+	struct osd_request *or;
+
+	or = _osd_request_alloc(gfp);
+	if (!or)
+		return NULL;
+
+	or->osd_dev = dev;
+	or->alloc_flags = gfp;
+	or->timeout = dev->def_timeout;
+	or->retries = OSD_REQ_RETRIES;
+
+	return or;
+}
+EXPORT_SYMBOL(osd_start_request);
+
+/*
+ * If osd_finalize_request() was called but the request was not executed through
+ * the block layer, then we must release BIOs.
+ */
+static void _abort_unexecuted_bios(struct request *rq)
+{
+	struct bio *bio;
+
+	while ((bio = rq->bio) != NULL) {
+		rq->bio = bio->bi_next;
+		bio_endio(bio, 0);
+	}
+}
+
+void osd_end_request(struct osd_request *or)
+{
+	struct request *rq = or->request;
+
+	if (rq) {
+		if (rq->next_rq) {
+			_abort_unexecuted_bios(rq->next_rq);
+			blk_put_request(rq->next_rq);
+		}
+
+		_abort_unexecuted_bios(rq);
+		blk_put_request(rq);
+	}
+	_osd_request_free(or);
+}
+EXPORT_SYMBOL(osd_end_request);
+
+int osd_execute_request(struct osd_request *or)
+{
+	return blk_execute_rq(or->request->q, NULL, or->request, 0);
+}
+EXPORT_SYMBOL(osd_execute_request);
+
+static void osd_request_async_done(struct request *req, int error)
+{
+	struct osd_request *or = req->end_io_data;
+
+	or->async_error = error;
+
+	if (error)
+		OSD_DEBUG("osd_request_async_done error recieved %d\n", error);
+
+	if (or->async_done)
+		or->async_done(or, or->async_private);
+	else
+		osd_end_request(or);
+}
+
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private)
+{
+	or->request->end_io_data = or;
+	or->async_private = private;
+	or->async_done = done;
+
+	blk_execute_rq_nowait(or->request->q, NULL, or->request, 0,
+			      osd_request_async_done);
+	return 0;
+}
+EXPORT_SYMBOL(osd_execute_request_async);
+
+/*
+ * Common to all OSD commands
+ */
+
+static void _osdv1_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv1_cdb *ocdb = &or->cdb.v1;
+
+	/*
+	 * For speed, the commands
+	 *	OSD_ACT_PERFORM_SCSI_COMMAND	, V1 0x8F7E, V2 0x8F7C
+	 *	OSD_ACT_SCSI_TASK_MANAGEMENT	, V1 0x8F7F, V2 0x8F7D
+	 * are not supported here. Should pass zero and set after the call
+	 */
+	act &= __constant_cpu_to_be16(~0x0080); /* V1 action code */
+
+	OSD_DEBUG("OSDv1 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v1.length = cpu_to_be64(len);
+	ocdb->h.v1.start_address = cpu_to_be64(offset);
+}
+
+static void _osd_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	_osdv1_req_encode_common(or, act, obj, offset, len);
+}
+
+/*
+ * Device commands
+ */
+void osd_req_format(struct osd_request *or, u64 tot_capacity)
+{
+	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
+				tot_capacity);
+}
+EXPORT_SYMBOL(osd_req_format);
+
+/*
+ * Partition commands
+ */
+static void _osd_req_encode_partition(struct osd_request *or,
+	__be16 act, osd_id partition)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	_osd_req_encode_common(or, act, &par, 0, 0);
+}
+
+void osd_req_create_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_CREATE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_create_partition);
+
+void osd_req_remove_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_REMOVE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_remove_partition);
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_CREATE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_create_object);
+
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_REMOVE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_remove_object);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, bio->bi_size);
+	WARN_ON(or->out.bio || or->out.total_bytes);
+	bio->bi_rw |= (1 << BIO_RW);
+	or->out.bio = bio;
+	or->out.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_write);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_READ, obj, offset, bio->bi_size);
+	WARN_ON(or->in.bio || or->in.total_bytes);
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_read);
+
+/*
+ * osd_finalize_request and helpers
+ */
+
+static int _init_blk_request(struct osd_request *or,
+	bool has_in, bool has_out)
+{
+	gfp_t flags = or->alloc_flags;
+	struct scsi_device *scsi_device = or->osd_dev->scsi_device;
+	struct request_queue *q = scsi_device->request_queue;
+	struct request *req;
+	int ret = -ENOMEM;
+
+	req = blk_get_request(q, has_out, flags);
+	if (!req)
+		goto out;
+
+	or->request = req;
+	req->cmd_type = REQ_TYPE_BLOCK_PC;
+	req->timeout = or->timeout;
+	req->retries = or->retries;
+	req->sense = or->sense;
+	req->sense_len = 0;
+
+	if (has_out) {
+		or->out.req = req;
+		if (has_in) {
+			/* allocate bidi request */
+			req = blk_get_request(q, READ, flags);
+			if (!req) {
+				OSD_DEBUG("blk_get_request for bidi failed\n");
+				goto out;
+			}
+			req->cmd_type = REQ_TYPE_BLOCK_PC;
+			or->in.req = or->request->next_rq = req;
+		}
+	} else if (has_in)
+		or->in.req = req;
+
+	ret = 0;
+out:
+	OSD_DEBUG("or=%p has_in=%d has_out=%d => %d, %p\n",
+			or, has_in, has_out, ret, or->request);
+	return ret;
+}
+
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	bool has_in, has_out;
+	int ret;
+
+	if (options & OSD_REQ_FUA)
+		cdbh->options |= OSD_CDB_FUA;
+
+	if (options & OSD_REQ_DPO)
+		cdbh->options |= OSD_CDB_DPO;
+
+	if (options & OSD_REQ_BYPASS_TIMESTAMPS)
+		cdbh->timestamp_control = OSD_CDB_BYPASS_TIMESTAMPS;
+
+	osd_set_caps(&or->cdb, cap);
+
+	has_in = or->in.bio || or->get_attr.total_bytes;
+	has_out = or->out.bio || or->set_attr.total_bytes ||
+		or->enc_get_attr.total_bytes;
+
+	ret = _init_blk_request(or, has_in, has_out);
+	if (ret) {
+		OSD_DEBUG("_init_blk_request failed\n");
+		return ret;
+	}
+
+	if (or->out.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->out.req,
+					or->out.bio);
+		if (ret) {
+			OSD_DEBUG("blk_rq_append_bio out failed\n");
+			return ret;
+		}
+		OSD_DEBUG("out bytes=%llu (bytes_req=%u)\n",
+			or->out.total_bytes, or->out.req->data_len);
+	}
+	if (or->in.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->in.req, or->in.bio);
+		if (ret) {
+			OSD_DEBUG("blk_rq_append_bio in failed\n");
+			return ret;
+		}
+		OSD_DEBUG("in bytes=%llu (bytes_req=%u)\n",
+			or->in.total_bytes, or->in.req->data_len);
+	}
+
+	if (!or->attributes_mode)
+		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+	cdbh->command_specific_options |= or->attributes_mode;
+
+	or->request->cmd = or->cdb.buff;
+	or->request->cmd_len = _osd_req_cdb_len(or);
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_finalize_request);
+
+/*
+ * Implementation of osd_sec.h API
+ * TODO: Move to a separate osd_sec.c file at a later stage.
+ */
+
+enum { OSD_SEC_CAP_V1_ALL_CAPS =
+	OSD_SEC_CAP_APPEND | OSD_SEC_CAP_OBJ_MGMT | OSD_SEC_CAP_REMOVE   |
+	OSD_SEC_CAP_CREATE | OSD_SEC_CAP_SET_ATTR | OSD_SEC_CAP_GET_ATTR |
+	OSD_SEC_CAP_WRITE  | OSD_SEC_CAP_READ     | OSD_SEC_CAP_POL_SEC  |
+	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
+};
+
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
+{
+	struct osd_capability *cap = caps;
+	u8 type;
+	u8 descriptor_type;
+
+	if (likely(obj->id)) {
+		if (unlikely(is_collection)) {
+			type = OSD_SEC_OBJ_COLLECTION;
+			descriptor_type = is_v1 ? OSD_SEC_OBJ_DESC_OBJ :
+						  OSD_SEC_OBJ_DESC_COL;
+		} else {
+			type = OSD_SEC_OBJ_USER;
+			descriptor_type = OSD_SEC_OBJ_DESC_OBJ;
+		}
+		WARN_ON(!obj->partition);
+	} else {
+		type = obj->partition ? OSD_SEC_OBJ_PARTITION :
+					OSD_SEC_OBJ_ROOT;
+		descriptor_type = OSD_SEC_OBJ_DESC_PAR;
+	}
+
+	memset(cap, 0, sizeof(*cap));
+
+	cap->h.format = OSD_SEC_CAP_FORMAT_VER1;
+	cap->h.integrity_algorithm__key_version = 0; /* MAKE_BYTE(0, 0); */
+	cap->h.security_method = OSD_SEC_NOSEC;
+/*	cap->expiration_time;
+	cap->AUDIT[30-10];
+	cap->discriminator[42-30];
+	cap->object_created_time; */
+	cap->h.object_type = type;
+	osd_sec_set_caps(&cap->h, OSD_SEC_CAP_V1_ALL_CAPS);
+	cap->h.object_descriptor_type = descriptor_type;
+	cap->od.obj_desc.policy_access_tag = 0;
+	cap->od.obj_desc.allowed_partition_id = cpu_to_be64(obj->partition);
+	cap->od.obj_desc.allowed_object_id = cpu_to_be64(obj->id);
+}
+EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
+
+void osd_set_caps(struct osd_cdb *cdb, const void *caps)
+{
+	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+}
-- 
1.6.0.1



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 03/18 ver2] libosd: OSDv1 Headers
  2008-11-04 16:44     ` Boaz Harrosh
@ 2008-11-09 14:52       ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-09 14:52 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Jörn Engel
  Cc: open-osd development, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, linux-scsi, Sami.Iren, linux-kernel


Headers only patch.

osd_protocol.h
	Contains a C-fied definition of the T10 OSD standard
osd_types.h
	Contains CPU order common used types
osd_initiator.h
	API definition of the osd_initiator library
osd_sec.h
	Contains High level API for the security manager.

[Note that checkpatch spews errors on things that are valid in this context
and will not be fixed]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
 include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_sec.h       |   45 ++++
 include/scsi/osd_types.h     |   40 ++++
 4 files changed, 914 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_initiator.h
 create mode 100644 include/scsi/osd_protocol.h
 create mode 100644 include/scsi/osd_sec.h
 create mode 100644 include/scsi/osd_types.h

diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
new file mode 100644
index 0000000..9bab95d
--- /dev/null
+++ b/include/scsi/osd_initiator.h
@@ -0,0 +1,332 @@
+/*
+ * osd_initiator.h - OSD initiator API definition
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_INITIATOR_H__
+#define __OSD_INITIATOR_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+#include <linux/blkdev.h>
+
+/* Note: "NI" in comments below means "Not Implemented yet" */
+
+/*
+ * Object-based Storage Device.
+ * This object represents an OSD device.
+ * It is not a full linux device in any way. It is only
+ * a place to hang resources associated with a Linux
+ * request Q and some default properties.
+ */
+struct osd_dev {
+	struct scsi_device *scsi_device;
+	unsigned def_timeout;
+};
+
+void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
+void osd_dev_fini(struct osd_dev *);
+
+struct osd_request;
+typedef void (osd_req_done_fn)(struct osd_request *, void *);
+
+struct osd_request {
+	struct osd_cdb cdb;
+	struct osd_data_out_integrity_info out_data_integ;
+	struct osd_data_in_integrity_info in_data_integ;
+
+	struct osd_dev *osd_dev;
+	struct request *request;
+
+	struct _osd_req_data_segment {
+		void *buff;
+		unsigned alloc_size; /* 0 here means not allocated by us */
+		unsigned total_bytes;
+	} set_attr, enc_get_attr, get_attr;
+
+	struct _osd_io_info {
+		struct bio *bio;
+		u64 total_bytes;
+		struct request *req;
+		struct _osd_req_data_segment *last_seg;
+		u8 *pad_buff;
+	} out, in;
+
+	gfp_t alloc_flags;
+	unsigned timeout;
+	unsigned retries;
+	u8 sense[OSD_MAX_SENSE_LEN];
+	enum osd_attributes_mode attributes_mode;
+
+	osd_req_done_fn *async_done;
+	void *async_private;
+	int async_error;
+};
+
+/**
+ * How to use the osd library:
+ *
+ * osd_start_request
+ *	Allocates a request.
+ *
+ * osd_req_*
+ *	Call one of, to encode the desired operation.
+ *
+ * osd_add_{get,set}_attr
+ *	Optionally add attributes to the CDB, list or page mode.
+ *
+ * osd_finalize_request
+ *	Computes final data out/in offsets and signs the request,
+ *	making it ready for execution.
+ *
+ * osd_execute_request
+ *	May be called to execute it through the block layer. Other wise submit
+ *	the associated block request in some other way.
+ *
+ * After execution:
+ * osd_req_decode_sense
+ *	Decodes sense information to verify execution results.
+ *
+ * osd_req_decode_get_attr
+ *	Retrieve osd_add_get_attr_list() values if used.
+ *
+ * osd_end_request
+ *	Must be called to deallocate the request.
+ */
+
+/**
+ * osd_start_request - Allocate and initialize an osd_request
+ *
+ * @osd_dev:    OSD device that holds the scsi-device and default values
+ *              that the request is associated with.
+ * @gfp:        The allocation flags to use for request allocation, and all
+ *              subsequent allocations. This will be stored at
+ *              osd_request->alloc_flags, can be changed by user later
+ *
+ * Allocate osd_request and initialize all members to the
+ * default/initial state.
+ */
+struct osd_request *osd_start_request(struct osd_dev *, gfp_t gfp);
+
+enum osd_req_options {
+	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
+	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
+
+	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
+};
+
+/**
+ * osd_finalize_request - Sign request and prepare request for execution
+ *
+ * @or:		osd_request to prepare
+ * @options:	combination of osd_req_options bit flags or 0.
+ * @cap	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
+ *              The security manager as capabilities for this cdb.
+ * @cap_key	The cryptographic key used to sign the cdb/data. Can be null
+ *              if NOSEC is used.
+ *
+ * The actual request and bios are only allocated here, so are the get_attr
+ * buffers that will receive the returned attributes. Copy's @cap to cdb.
+ * Sign the cdb/data with @cap_key.
+ */
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key);
+
+/**
+ * osd_execute_request - Execute the request synchronously through
+ *                       the block-layer
+ * @or:		osd_request to Executed
+ *
+ * Calls blk_execute_rq to q the command and waits for completion.
+ */
+int osd_execute_request(struct osd_request *or);
+
+/**
+ * osd_execute_request_async - submits the request for execution through
+ *                             the block-layer without waitting.
+ * @or:                      - osd_request to Executed
+ * @done: (Optional)         - Called at end of execution
+ * @private:                 - Will be passes to @done function
+ *
+ * Calls blk_execute_rq_nowait to q the command. When execution is done
+ * Optionally calles @done with @private as parameter. or->async_error has the
+ * Return code
+ */
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private);
+
+/**
+ * osd_end_request - return osd_request to free store
+ *
+ * @or:		osd_request to free
+ *
+ * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
+ */
+void osd_end_request(struct osd_request *or);
+
+/*
+ * CDB Encoding
+ *
+ * Note: call only one of the following methods.
+ */
+
+/*
+ * Device commands
+ */
+void osd_req_set_master_seed_xchg(struct osd_request *, ...);/* NI */
+void osd_req_set_master_key(struct osd_request *, ...);/* NI */
+
+void osd_req_format(struct osd_request *, u64 tot_capacity);
+
+/* list all partitions
+ * @list header must be initialized to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_dev_partitions(struct osd_request *,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
+
+void osd_req_flush_obsd(struct osd_request *,
+	enum osd_options_flush_scope_values);
+
+void osd_req_perform_scsi_command(struct osd_request *,
+	const u8 *cdb, ...);/* NI */
+void osd_req_task_management(struct osd_request *, ...);/* NI */
+
+/*
+ * Partition commands
+ */
+void osd_req_create_partition(struct osd_request *, osd_id partition);
+void osd_req_remove_partition(struct osd_request *, osd_id partition);
+
+void osd_req_set_partition_key(struct osd_request *,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
+
+/* list all collections in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_collections(struct osd_request *,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+/* list all objects in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_objects(struct osd_request *,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+void osd_req_flush_partition(struct osd_request *,
+	osd_id partition, enum osd_options_flush_scope_values);
+
+/*
+ * Collection commands
+ */
+void osd_req_create_collection(struct osd_request *,
+	const struct osd_obj_id *);/* NI */
+void osd_req_remove_collection(struct osd_request *,
+	const struct osd_obj_id *);/* NI */
+
+/* list all objects in the collection */
+int osd_req_list_collection_objects(struct osd_request *,
+	const struct osd_obj_id *, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem);
+
+/* V2 only filtered list of objects in the collection */
+void osd_req_query(struct osd_request *, ...);/* NI */
+
+void osd_req_flush_collection(struct osd_request *,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values);
+
+void osd_req_get_member_attrs(struct osd_request *, ...);/* V2-only NI */
+void osd_req_set_member_attrs(struct osd_request *, ...);/* V2-only NI */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *, struct osd_obj_id *);
+void osd_req_remove_object(struct osd_request *, struct osd_obj_id *);
+
+void osd_req_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);
+void osd_req_append(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out);/* NI */
+void osd_req_create_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
+void osd_req_clear(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
+void osd_req_punch(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
+
+void osd_req_flush_object(struct osd_request *,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values,
+	/*V2*/ u64 offset, /*V2*/ u64 len);
+
+void osd_req_read(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_in, u64 offset);
+
+/*
+ * Root/Partition/Collection/Object Attributes commands
+ */
+
+/* get before set */
+void osd_req_get_attributes(struct osd_request *, const struct osd_obj_id *);
+
+/* set before get */
+void osd_req_set_attributes(struct osd_request *, const struct osd_obj_id *);
+
+/*
+ * Attributes appended to most commands
+ */
+
+/* Attributes List mode (or V2 CDB) */
+  /*
+   * TODO: In ver2 if at finalize time only one attr was set and no gets,
+   * then the Attributes CDB mode is used automatically to save IO.
+   */
+
+/* set a list of attributes. */
+int osd_req_add_set_attr_list(struct osd_request *,
+	const struct osd_attr *, unsigned nelem);
+
+/* get a list of attributes */
+int osd_req_add_get_attr_list(struct osd_request *,
+	const struct osd_attr *, unsigned nelem);
+
+/*
+ * Attributes list decoding
+ * Must be called after osd_request.request was executed
+ * It is called in a loop to decode the returned get_attr
+ * (see osd_add_get_attr)
+ */
+int osd_req_decode_get_attr_list(struct osd_request *,
+	struct osd_attr *, int *nelem, void **iterator);
+
+/* Attributes Page mode */
+
+/*
+ * Read an attribute page and optionally set one attribute
+ *
+ * Retrieves the attribute page directly to a user buffer.
+ * @attr_page_data shall stay valid until end of execution.
+ * See osd_attributes.h for common page structures
+ */
+int osd_req_add_get_attr_page(struct osd_request *,
+	u32 page_id, void *attr_page_data, unsigned max_page_len,
+	const struct osd_attr *set_one);
+
+#endif /* __OSD_LIB_H__ */
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
new file mode 100644
index 0000000..77a74a3
--- /dev/null
+++ b/include/scsi/osd_protocol.h
@@ -0,0 +1,497 @@
+/*
+ * osd_protocol.h - OSD T10 standard C definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_PROTOCOL_H__
+#define __OSD_PROTOCOL_H__
+
+#include <linux/types.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+enum {
+	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
+	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
+	OSDv1_CAP_LEN = 80,
+	/* Latest supported version */
+	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
+	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
+	OSD_CAP_LEN = OSDv1_CAP_LEN,
+
+	OSD_SYSTEMID_LEN = 20,
+	OSD_CRYPTO_KEYID_SIZE = 20,
+	OSD_CRYPTO_SEED_SIZE = 4,
+	OSD_CRYPTO_NONCE_SIZE = 12,
+	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
+
+	OSD_PARTITION_FIRST_ID = 0x10000,
+	OSD_OBJECT_FIRST_ID = 0x10000,
+};
+
+/* (osd-r10 5.2.4)
+ * osd2r03: 5.2.3 Caching control bits
+ */
+enum osd_options_byte {
+	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
+	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
+};
+
+/*
+ * osd2r03: 5.2.5 Isolation.
+ * First 3 bits, V2-only.
+ * Also for attr 110h "default isolation method" at Root Information page
+ */
+enum osd_options_byte_isolation {
+	OSD_ISOLATION_DEFAULT = 0,
+	OSD_ISOLATION_NONE = 1,
+	OSD_ISOLATION_STRICT = 2,
+	OSD_ISOLATION_RANGE = 4,
+	OSD_ISOLATION_FUNCTIONAL = 5,
+	OSD_ISOLATION_VENDOR = 7,
+};
+
+/* (osd-r10: 6.7)
+ * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
+ */
+enum osd_options_flush_scope_values {
+	OSD_CDB_FLUSH_ALL = 0,
+	OSD_CDB_FLUSH_ATTR_ONLY = 1,
+
+	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
+	/* V2-only */
+	OSD_CDB_FLUSH_ALL_RANGE = 2,
+};
+
+/* osd2r03: 5.2.10 Timestamps control */
+enum {
+	OSD_CDB_NORMAL_TIMESTAMPS = 0,
+	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
+};
+
+/* (osd-r10: 5.2.2.1)
+ * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
+ *	2 bits at second nibble of command_specific_options byte
+ */
+enum osd_attributes_mode {
+	/* V2-only */
+	OSD_CDB_SET_ONE_ATTR = 0x10,
+
+	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
+	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
+
+	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
+};
+
+/* (osd-r10: 4.12.5)
+ * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
+ *	byte offset = mantissa * (2^(exponent+8))
+ *	struct {
+ *		unsigned mantissa: 28;
+ *		int exponent: 04;
+ *	}
+ */
+typedef __be32 __bitwise osd_cdb_offset;
+
+enum {
+	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
+	OSD_OFFSET_MAX_BITS = 28,
+
+	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MAX_SHIFT = 16,
+};
+
+/* Return the smallest allowed encoded offset that contains @offset.
+ *
+ * The actual encoded offset returned is @offset + *padding.
+ * (up to max_shift, non-inclusive)
+ */
+osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
+	int min_shift, int max_shift);
+
+/* Minimum alignment is 256 bytes
+ * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
+ * which is 8 to 23 but IBM code restricts it to 16, so be it.
+ */
+static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
+/* osd2r03: 5.2.1 Overview */
+struct osd_cdb_head {
+	struct scsi_varlen_cdb_hdr varlen_cdb;
+/*10*/	u8		options;
+	u8		command_specific_options;
+	u8		timestamp_control;
+/*13*/	u8		reserved1[3];
+/*16*/	__be64		partition;
+/*24*/	__be64		object;
+/*32*/	union { /* V1 vs V2 alignment differences */
+		struct __osdv1_cdb_addr_len {
+/*32*/			__be32 		list_identifier;/* Rarely used */
+/*36*/			__be64		length;
+/*44*/			__be64		start_address;
+		} __packed v1;
+	};
+/*52*/	union { /* selected attributes mode Page/List/Single */
+		struct osd_attributes_page_mode {
+/*52*/			__be32		get_attr_page;
+/*56*/			__be32		get_attr_alloc_length;
+/*60*/			osd_cdb_offset	get_attr_offset;
+
+/*64*/			__be32		set_attr_page;
+/*68*/			__be32		set_attr_id;
+/*72*/			__be32		set_attr_length;
+/*76*/			osd_cdb_offset	set_attr_offset;
+		} __packed attrs_page;
+
+		struct osd_attributes_list_mode {
+/*52*/			__be32		get_attr_desc_bytes;
+/*56*/			osd_cdb_offset	get_attr_desc_offset;
+
+/*60*/			__be32		get_attr_alloc_length;
+/*64*/			osd_cdb_offset	get_attr_offset;
+
+/*68*/			__be32		set_attr_bytes;
+/*72*/			osd_cdb_offset	set_attr_offset;
+			__be32 not_used;
+		} __packed attrs_list;
+
+		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
+		struct osd_attributes_cdb_mode {
+/*52*/			__be32		set_attr_page;
+/*56*/			__be32		set_attr_id;
+/*60*/			__be16		set_attr_len;
+/*62*/			u8		set_attr_val[80-62];
+		} __packed attrs_cdb;
+/*52*/		u8 get_set_attributes_parameters[80-52];
+	};
+} __packed;
+/*80*/
+
+/*160 v1*/
+struct osd_security_parameters {
+/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*192*/osd_cdb_offset	data_in_integrity_check_offset;
+/*196*/osd_cdb_offset	data_out_integrity_check_offset;
+} __packed;
+/*200 v1*/
+
+struct osdv1_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSDv1_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
+struct osd_cdb {
+	union {
+		struct osdv1_cdb v1;
+		u8 buff[OSD_TOTAL_CDB_LEN];
+	};
+} __packed;
+
+static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
+{
+	return (struct osd_cdb_head *)ocdb->buff;
+}
+
+/* define both version actions
+ * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
+ */
+#define OSD_ACT___(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
+
+/* V2 only actions */
+#define OSD_ACT_V2(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
+
+#define OSD_ACT_V1_V2(Name, Num1, Num2) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
+
+enum osd_service_actions {
+	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
+	OSD_ACT___(FORMAT_OSD,			0x01)
+	OSD_ACT___(CREATE,			0x02)
+	OSD_ACT___(LIST,			0x03)
+	OSD_ACT_V2(PUNCH,			0x04)
+	OSD_ACT___(READ,			0x05)
+	OSD_ACT___(WRITE,			0x06)
+	OSD_ACT___(APPEND,			0x07)
+	OSD_ACT___(FLUSH,			0x08)
+	OSD_ACT_V2(CLEAR,			0x09)
+	OSD_ACT___(REMOVE,			0x0A)
+	OSD_ACT___(CREATE_PARTITION,		0x0B)
+	OSD_ACT___(REMOVE_PARTITION,		0x0C)
+	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
+	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
+	OSD_ACT___(CREATE_AND_WRITE,		0x12)
+	OSD_ACT___(CREATE_COLLECTION,		0x15)
+	OSD_ACT___(REMOVE_COLLECTION,		0x16)
+	OSD_ACT___(LIST_COLLECTION,		0x17)
+	OSD_ACT___(SET_KEY,			0x18)
+	OSD_ACT___(SET_MASTER_KEY,		0x19)
+	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
+	OSD_ACT___(FLUSH_PARTITION,		0x1B)
+	OSD_ACT___(FLUSH_OSD,			0x1C)
+
+	OSD_ACT_V2(QUERY,			0x20)
+	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
+	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
+	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
+	OSD_ACT_V2(READ_MAP,			0x31)
+
+	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
+	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
+	/* 0x8F80 to 0x8FFF are Vendor specific */
+};
+
+/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
+struct osd_attributes_list_attrid {
+	__be32 page;
+	__be32 attr_id;
+} __packed;
+
+/*
+ * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
+ *                  for setting attributes
+ */
+struct osd_attributes_list_element {
+	__be32 page;
+	__be32 attr_id;
+	__be16 attr_bytes;
+	u8 attr_val[0];
+} __packed;
+
+enum {
+	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+};
+
+enum {
+	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
+	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
+};
+
+static inline unsigned osdv1_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
+}
+
+/*
+ * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
+ */
+enum osd_attr_list_types {
+	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
+	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
+	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
+	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
+};
+
+/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
+struct osd_attributes_list_multi_header {
+	__be64 object_id;
+	u8 object_type; /* object_type enum below */
+	u8 reserved[5];
+	__be16 list_bytes;
+	/* followed by struct osd_attributes_list_element's */
+};
+
+struct osdv1_attributes_list_header {
+	u8 type;	/* low 4-bit only */
+	u8 pad;
+	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
+{
+	return be16_to_cpu(h->list_bytes);
+}
+
+/* (osd-r10 6.13)
+ * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
+ *	for root_lstchg below
+ */
+enum {
+	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
+	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
+};
+
+/*
+ * osd2r03: 6.15.2 LIST command parameter data
+ * (Also for LIST COLLECTION)
+ */
+struct osd_obj_id_list {
+	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
+	__be64 continuation_id;
+	__be32 list_identifier;
+	u8 pad[3];
+	u8 root_lstchg;
+	__be64 object_ids[0];
+} __packed;
+
+static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
+	bool *is_changed)
+{
+	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
+	return 0 != list->continuation_id;
+}
+
+/*
+ * osd2r03: 4.12.4.5 The ALLDATA security method
+ */
+struct osd_data_out_integrity_info {
+	__be64 data_bytes;
+	__be64 set_attributes_bytes;
+	__be64 get_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_data_in_integrity_info {
+	__be64 data_bytes;
+	__be64 retrieved_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_timestamp {
+	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
+} __packed;
+/* FIXME: define helper functions to convert to/from osd time format */
+
+/*
+ * Capability & Security definitions
+ * osd2r03: 4.11.2.2 Capability format
+ * osd2r03: 5.2.8 Security parameters
+ */
+
+struct osd_key_identifier {
+	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+} __packed;
+
+/* for osd_capability.format */
+enum {
+	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
+	OSD_SEC_CAP_FORMAT_VER1 = 1,
+	OSD_SEC_CAP_FORMAT_VER2 = 2,
+};
+
+/* security_method */
+enum {
+	OSD_SEC_NOSEC = 0,
+	OSD_SEC_CAPKEY = 1,
+	OSD_SEC_CMDRSP = 2,
+	OSD_SEC_ALLDATA = 3,
+};
+
+enum object_type {
+	OSD_SEC_OBJ_ROOT = 0x1,
+	OSD_SEC_OBJ_PARTITION = 0x2,
+	OSD_SEC_OBJ_COLLECTION = 0x40,
+	OSD_SEC_OBJ_USER = 0x80,
+};
+
+enum osd_capability_bit_masks {
+	OSD_SEC_CAP_APPEND	= (1 << 0),
+	OSD_SEC_CAP_OBJ_MGMT	= (1 << 1),
+	OSD_SEC_CAP_REMOVE	= (1 << 2),
+	OSD_SEC_CAP_CREATE	= (1 << 3),
+	OSD_SEC_CAP_SET_ATTR	= (1 << 4),
+	OSD_SEC_CAP_GET_ATTR	= (1 << 5),
+	OSD_SEC_CAP_WRITE	= (1 << 6),
+	OSD_SEC_CAP_READ	= (1 << 7),
+
+	OSD_SEC_CAP_NONE1	= (1 << 8),
+	OSD_SEC_CAP_NONE2	= (1 << 9),
+	OSD_SEC_CAP_NONE3	= (1 << 10),
+	OSD_SEC_CAP_QUERY	= (1 << 11), /*v2 only*/
+	OSD_SEC_CAP_M_OBJECT	= (1 << 12), /*v2 only*/
+	OSD_SEC_CAP_POL_SEC	= (1 << 13),
+	OSD_SEC_CAP_GLOBAL	= (1 << 14),
+	OSD_SEC_CAP_DEV_MGMT	= (1 << 15),
+};
+
+/* for object_descriptor_type (hi nibble used) */
+enum {
+	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
+	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
+	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
+	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
+};
+
+/* (osd-r10:4.9.2.2)
+ * osd2r03:4.11.2.2 Capability format
+ */
+struct osd_capability_head {
+	u8 format; /* low nibble */
+	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
+	u8 security_method;
+	u8 reserved1;
+/*04*/	struct osd_timestamp expiration_time;
+/*10*/	u8 audit[30-10];
+/*30*/	u8 discriminator[42-30];
+/*42*/	struct osd_timestamp object_created_time;
+/*48*/	u8 object_type;
+	u8 permissions_bit_mask[54-49];
+/*54*/	u8 reserved2;
+/*55*/	u8 object_descriptor_type; /* high nibble */
+} __packed;
+
+/*56 v1*/
+struct osdv1_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 policy_access_tag;
+/*60*/			__be64 allowed_partition_id;
+/*68*/			__be64 allowed_object_id;
+/*76*/			__be32 reserved;
+		} __packed obj_desc;
+
+		u8 object_descriptor[80-56];/*24*/
+	};
+} __packed;
+/*80 v1*/
+
+struct osd_capability {
+	struct osd_capability_head h;
+	struct osdv1_cap_object_descriptor od;
+} __packed;
+
+/**
+ * osd_sec_set_caps - set cap-bits into the capabilities header
+ *
+ * @cap:	The osd_capability_head to set cap bits to.
+ * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
+ *
+ * permissions_bit_mask is unaligned use below to set into caps
+ * in a version independent way
+ */
+static inline void osd_sec_set_caps(struct osd_capability_head *cap,
+	u16 bit_mask)
+{
+	/*
+	 *Note: The bits above are defined LE order this is because this way
+	 *      they can grow in the future to more then 16, and still retain
+	 *      there constant values.
+	 */
+	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
+}
+
+#endif /* ndef __OSD_PROTOCOL_H__ */
diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h
new file mode 100644
index 0000000..4c09fee
--- /dev/null
+++ b/include/scsi/osd_sec.h
@@ -0,0 +1,45 @@
+/*
+ * osd_sec.h - OSD security manager API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_SEC_H__
+#define __OSD_SEC_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/*
+ * Contains types and constants of osd capabilities and security
+ * encoding/decoding.
+ * API is trying to keep security abstract so initiator of an object
+ * based pNFS client knows as little as possible about security and
+ * capabilities. It is the Server's osd-initiator place to know more.
+ * Also can be used by osd-target.
+ */
+void osd_sec_encode_caps(void *caps, ...);/* NI */
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1);
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_params);
+
+/* Conditionally sign the CDB according to security setting in ocdb
+ * with cap_key */
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key);
+
+/* Unconditionally sign the BIO data with cap_key.
+ * Check for osd_is_sec_alldata() was done prior to calling this. */
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key);
+
+/* Version independent copy of caps into the cdb */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps);
+
+#endif /* ndef __OSD_SEC_H__ */
diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h
new file mode 100644
index 0000000..ea5372d
--- /dev/null
+++ b/include/scsi/osd_types.h
@@ -0,0 +1,40 @@
+/*
+ * osd_types.h - Types and constants which are not part of the protocol.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Contains types and constants that are implementation specific and are
+ * used by more than one part of the osd library.
+ *     (Eg initiator/target/security_manager/...)
+ */
+#ifndef __OSD_TYPES_H__
+#define __OSD_TYPES_H__
+
+struct osd_systemid {
+	u8 data[OSD_SYSTEMID_LEN];
+};
+
+typedef u64 __bitwise osd_id;
+
+struct osd_obj_id {
+	osd_id partition;
+	osd_id id;
+};
+
+static const struct __weak osd_obj_id osd_root_object = {0, 0};
+
+struct osd_attr {
+	u32 page;
+	u32 attr_id;
+	u16 len;		/* byte count of operand */
+	void *val_ptr;		/* in network order */
+};
+
+#endif /* ndef __OSD_TYPES_H__ */
-- 
1.6.0.1



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 03/18 ver2] libosd: OSDv1 Headers
@ 2008-11-09 14:52       ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-09 14:52 UTC (permalink / raw)
  To: James Bottomley, Andrew Morton, Jörn Engel
  Cc: open-osd development, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, linux-scsi, Sami.Iren, linux-kernel


Headers only patch.

osd_protocol.h
	Contains a C-fied definition of the T10 OSD standard
osd_types.h
	Contains CPU order common used types
osd_initiator.h
	API definition of the osd_initiator library
osd_sec.h
	Contains High level API for the security manager.

[Note that checkpatch spews errors on things that are valid in this context
and will not be fixed]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
 include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_sec.h       |   45 ++++
 include/scsi/osd_types.h     |   40 ++++
 4 files changed, 914 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_initiator.h
 create mode 100644 include/scsi/osd_protocol.h
 create mode 100644 include/scsi/osd_sec.h
 create mode 100644 include/scsi/osd_types.h

diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
new file mode 100644
index 0000000..9bab95d
--- /dev/null
+++ b/include/scsi/osd_initiator.h
@@ -0,0 +1,332 @@
+/*
+ * osd_initiator.h - OSD initiator API definition
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_INITIATOR_H__
+#define __OSD_INITIATOR_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+#include <linux/blkdev.h>
+
+/* Note: "NI" in comments below means "Not Implemented yet" */
+
+/*
+ * Object-based Storage Device.
+ * This object represents an OSD device.
+ * It is not a full linux device in any way. It is only
+ * a place to hang resources associated with a Linux
+ * request Q and some default properties.
+ */
+struct osd_dev {
+	struct scsi_device *scsi_device;
+	unsigned def_timeout;
+};
+
+void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
+void osd_dev_fini(struct osd_dev *);
+
+struct osd_request;
+typedef void (osd_req_done_fn)(struct osd_request *, void *);
+
+struct osd_request {
+	struct osd_cdb cdb;
+	struct osd_data_out_integrity_info out_data_integ;
+	struct osd_data_in_integrity_info in_data_integ;
+
+	struct osd_dev *osd_dev;
+	struct request *request;
+
+	struct _osd_req_data_segment {
+		void *buff;
+		unsigned alloc_size; /* 0 here means not allocated by us */
+		unsigned total_bytes;
+	} set_attr, enc_get_attr, get_attr;
+
+	struct _osd_io_info {
+		struct bio *bio;
+		u64 total_bytes;
+		struct request *req;
+		struct _osd_req_data_segment *last_seg;
+		u8 *pad_buff;
+	} out, in;
+
+	gfp_t alloc_flags;
+	unsigned timeout;
+	unsigned retries;
+	u8 sense[OSD_MAX_SENSE_LEN];
+	enum osd_attributes_mode attributes_mode;
+
+	osd_req_done_fn *async_done;
+	void *async_private;
+	int async_error;
+};
+
+/**
+ * How to use the osd library:
+ *
+ * osd_start_request
+ *	Allocates a request.
+ *
+ * osd_req_*
+ *	Call one of, to encode the desired operation.
+ *
+ * osd_add_{get,set}_attr
+ *	Optionally add attributes to the CDB, list or page mode.
+ *
+ * osd_finalize_request
+ *	Computes final data out/in offsets and signs the request,
+ *	making it ready for execution.
+ *
+ * osd_execute_request
+ *	May be called to execute it through the block layer. Other wise submit
+ *	the associated block request in some other way.
+ *
+ * After execution:
+ * osd_req_decode_sense
+ *	Decodes sense information to verify execution results.
+ *
+ * osd_req_decode_get_attr
+ *	Retrieve osd_add_get_attr_list() values if used.
+ *
+ * osd_end_request
+ *	Must be called to deallocate the request.
+ */
+
+/**
+ * osd_start_request - Allocate and initialize an osd_request
+ *
+ * @osd_dev:    OSD device that holds the scsi-device and default values
+ *              that the request is associated with.
+ * @gfp:        The allocation flags to use for request allocation, and all
+ *              subsequent allocations. This will be stored at
+ *              osd_request->alloc_flags, can be changed by user later
+ *
+ * Allocate osd_request and initialize all members to the
+ * default/initial state.
+ */
+struct osd_request *osd_start_request(struct osd_dev *, gfp_t gfp);
+
+enum osd_req_options {
+	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
+	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
+
+	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
+};
+
+/**
+ * osd_finalize_request - Sign request and prepare request for execution
+ *
+ * @or:		osd_request to prepare
+ * @options:	combination of osd_req_options bit flags or 0.
+ * @cap	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
+ *              The security manager as capabilities for this cdb.
+ * @cap_key	The cryptographic key used to sign the cdb/data. Can be null
+ *              if NOSEC is used.
+ *
+ * The actual request and bios are only allocated here, so are the get_attr
+ * buffers that will receive the returned attributes. Copy's @cap to cdb.
+ * Sign the cdb/data with @cap_key.
+ */
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key);
+
+/**
+ * osd_execute_request - Execute the request synchronously through
+ *                       the block-layer
+ * @or:		osd_request to Executed
+ *
+ * Calls blk_execute_rq to q the command and waits for completion.
+ */
+int osd_execute_request(struct osd_request *or);
+
+/**
+ * osd_execute_request_async - submits the request for execution through
+ *                             the block-layer without waitting.
+ * @or:                      - osd_request to Executed
+ * @done: (Optional)         - Called at end of execution
+ * @private:                 - Will be passes to @done function
+ *
+ * Calls blk_execute_rq_nowait to q the command. When execution is done
+ * Optionally calles @done with @private as parameter. or->async_error has the
+ * Return code
+ */
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private);
+
+/**
+ * osd_end_request - return osd_request to free store
+ *
+ * @or:		osd_request to free
+ *
+ * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
+ */
+void osd_end_request(struct osd_request *or);
+
+/*
+ * CDB Encoding
+ *
+ * Note: call only one of the following methods.
+ */
+
+/*
+ * Device commands
+ */
+void osd_req_set_master_seed_xchg(struct osd_request *, ...);/* NI */
+void osd_req_set_master_key(struct osd_request *, ...);/* NI */
+
+void osd_req_format(struct osd_request *, u64 tot_capacity);
+
+/* list all partitions
+ * @list header must be initialized to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_dev_partitions(struct osd_request *,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
+
+void osd_req_flush_obsd(struct osd_request *,
+	enum osd_options_flush_scope_values);
+
+void osd_req_perform_scsi_command(struct osd_request *,
+	const u8 *cdb, ...);/* NI */
+void osd_req_task_management(struct osd_request *, ...);/* NI */
+
+/*
+ * Partition commands
+ */
+void osd_req_create_partition(struct osd_request *, osd_id partition);
+void osd_req_remove_partition(struct osd_request *, osd_id partition);
+
+void osd_req_set_partition_key(struct osd_request *,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
+
+/* list all collections in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_collections(struct osd_request *,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+/* list all objects in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_objects(struct osd_request *,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+void osd_req_flush_partition(struct osd_request *,
+	osd_id partition, enum osd_options_flush_scope_values);
+
+/*
+ * Collection commands
+ */
+void osd_req_create_collection(struct osd_request *,
+	const struct osd_obj_id *);/* NI */
+void osd_req_remove_collection(struct osd_request *,
+	const struct osd_obj_id *);/* NI */
+
+/* list all objects in the collection */
+int osd_req_list_collection_objects(struct osd_request *,
+	const struct osd_obj_id *, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem);
+
+/* V2 only filtered list of objects in the collection */
+void osd_req_query(struct osd_request *, ...);/* NI */
+
+void osd_req_flush_collection(struct osd_request *,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values);
+
+void osd_req_get_member_attrs(struct osd_request *, ...);/* V2-only NI */
+void osd_req_set_member_attrs(struct osd_request *, ...);/* V2-only NI */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *, struct osd_obj_id *);
+void osd_req_remove_object(struct osd_request *, struct osd_obj_id *);
+
+void osd_req_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);
+void osd_req_append(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out);/* NI */
+void osd_req_create_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
+void osd_req_clear(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
+void osd_req_punch(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
+
+void osd_req_flush_object(struct osd_request *,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values,
+	/*V2*/ u64 offset, /*V2*/ u64 len);
+
+void osd_req_read(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_in, u64 offset);
+
+/*
+ * Root/Partition/Collection/Object Attributes commands
+ */
+
+/* get before set */
+void osd_req_get_attributes(struct osd_request *, const struct osd_obj_id *);
+
+/* set before get */
+void osd_req_set_attributes(struct osd_request *, const struct osd_obj_id *);
+
+/*
+ * Attributes appended to most commands
+ */
+
+/* Attributes List mode (or V2 CDB) */
+  /*
+   * TODO: In ver2 if at finalize time only one attr was set and no gets,
+   * then the Attributes CDB mode is used automatically to save IO.
+   */
+
+/* set a list of attributes. */
+int osd_req_add_set_attr_list(struct osd_request *,
+	const struct osd_attr *, unsigned nelem);
+
+/* get a list of attributes */
+int osd_req_add_get_attr_list(struct osd_request *,
+	const struct osd_attr *, unsigned nelem);
+
+/*
+ * Attributes list decoding
+ * Must be called after osd_request.request was executed
+ * It is called in a loop to decode the returned get_attr
+ * (see osd_add_get_attr)
+ */
+int osd_req_decode_get_attr_list(struct osd_request *,
+	struct osd_attr *, int *nelem, void **iterator);
+
+/* Attributes Page mode */
+
+/*
+ * Read an attribute page and optionally set one attribute
+ *
+ * Retrieves the attribute page directly to a user buffer.
+ * @attr_page_data shall stay valid until end of execution.
+ * See osd_attributes.h for common page structures
+ */
+int osd_req_add_get_attr_page(struct osd_request *,
+	u32 page_id, void *attr_page_data, unsigned max_page_len,
+	const struct osd_attr *set_one);
+
+#endif /* __OSD_LIB_H__ */
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
new file mode 100644
index 0000000..77a74a3
--- /dev/null
+++ b/include/scsi/osd_protocol.h
@@ -0,0 +1,497 @@
+/*
+ * osd_protocol.h - OSD T10 standard C definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_PROTOCOL_H__
+#define __OSD_PROTOCOL_H__
+
+#include <linux/types.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+enum {
+	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
+	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
+	OSDv1_CAP_LEN = 80,
+	/* Latest supported version */
+	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
+	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
+	OSD_CAP_LEN = OSDv1_CAP_LEN,
+
+	OSD_SYSTEMID_LEN = 20,
+	OSD_CRYPTO_KEYID_SIZE = 20,
+	OSD_CRYPTO_SEED_SIZE = 4,
+	OSD_CRYPTO_NONCE_SIZE = 12,
+	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
+
+	OSD_PARTITION_FIRST_ID = 0x10000,
+	OSD_OBJECT_FIRST_ID = 0x10000,
+};
+
+/* (osd-r10 5.2.4)
+ * osd2r03: 5.2.3 Caching control bits
+ */
+enum osd_options_byte {
+	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
+	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
+};
+
+/*
+ * osd2r03: 5.2.5 Isolation.
+ * First 3 bits, V2-only.
+ * Also for attr 110h "default isolation method" at Root Information page
+ */
+enum osd_options_byte_isolation {
+	OSD_ISOLATION_DEFAULT = 0,
+	OSD_ISOLATION_NONE = 1,
+	OSD_ISOLATION_STRICT = 2,
+	OSD_ISOLATION_RANGE = 4,
+	OSD_ISOLATION_FUNCTIONAL = 5,
+	OSD_ISOLATION_VENDOR = 7,
+};
+
+/* (osd-r10: 6.7)
+ * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
+ */
+enum osd_options_flush_scope_values {
+	OSD_CDB_FLUSH_ALL = 0,
+	OSD_CDB_FLUSH_ATTR_ONLY = 1,
+
+	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
+	/* V2-only */
+	OSD_CDB_FLUSH_ALL_RANGE = 2,
+};
+
+/* osd2r03: 5.2.10 Timestamps control */
+enum {
+	OSD_CDB_NORMAL_TIMESTAMPS = 0,
+	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
+};
+
+/* (osd-r10: 5.2.2.1)
+ * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
+ *	2 bits at second nibble of command_specific_options byte
+ */
+enum osd_attributes_mode {
+	/* V2-only */
+	OSD_CDB_SET_ONE_ATTR = 0x10,
+
+	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
+	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
+
+	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
+};
+
+/* (osd-r10: 4.12.5)
+ * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
+ *	byte offset = mantissa * (2^(exponent+8))
+ *	struct {
+ *		unsigned mantissa: 28;
+ *		int exponent: 04;
+ *	}
+ */
+typedef __be32 __bitwise osd_cdb_offset;
+
+enum {
+	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
+	OSD_OFFSET_MAX_BITS = 28,
+
+	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MAX_SHIFT = 16,
+};
+
+/* Return the smallest allowed encoded offset that contains @offset.
+ *
+ * The actual encoded offset returned is @offset + *padding.
+ * (up to max_shift, non-inclusive)
+ */
+osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
+	int min_shift, int max_shift);
+
+/* Minimum alignment is 256 bytes
+ * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
+ * which is 8 to 23 but IBM code restricts it to 16, so be it.
+ */
+static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
+/* osd2r03: 5.2.1 Overview */
+struct osd_cdb_head {
+	struct scsi_varlen_cdb_hdr varlen_cdb;
+/*10*/	u8		options;
+	u8		command_specific_options;
+	u8		timestamp_control;
+/*13*/	u8		reserved1[3];
+/*16*/	__be64		partition;
+/*24*/	__be64		object;
+/*32*/	union { /* V1 vs V2 alignment differences */
+		struct __osdv1_cdb_addr_len {
+/*32*/			__be32 		list_identifier;/* Rarely used */
+/*36*/			__be64		length;
+/*44*/			__be64		start_address;
+		} __packed v1;
+	};
+/*52*/	union { /* selected attributes mode Page/List/Single */
+		struct osd_attributes_page_mode {
+/*52*/			__be32		get_attr_page;
+/*56*/			__be32		get_attr_alloc_length;
+/*60*/			osd_cdb_offset	get_attr_offset;
+
+/*64*/			__be32		set_attr_page;
+/*68*/			__be32		set_attr_id;
+/*72*/			__be32		set_attr_length;
+/*76*/			osd_cdb_offset	set_attr_offset;
+		} __packed attrs_page;
+
+		struct osd_attributes_list_mode {
+/*52*/			__be32		get_attr_desc_bytes;
+/*56*/			osd_cdb_offset	get_attr_desc_offset;
+
+/*60*/			__be32		get_attr_alloc_length;
+/*64*/			osd_cdb_offset	get_attr_offset;
+
+/*68*/			__be32		set_attr_bytes;
+/*72*/			osd_cdb_offset	set_attr_offset;
+			__be32 not_used;
+		} __packed attrs_list;
+
+		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
+		struct osd_attributes_cdb_mode {
+/*52*/			__be32		set_attr_page;
+/*56*/			__be32		set_attr_id;
+/*60*/			__be16		set_attr_len;
+/*62*/			u8		set_attr_val[80-62];
+		} __packed attrs_cdb;
+/*52*/		u8 get_set_attributes_parameters[80-52];
+	};
+} __packed;
+/*80*/
+
+/*160 v1*/
+struct osd_security_parameters {
+/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*192*/osd_cdb_offset	data_in_integrity_check_offset;
+/*196*/osd_cdb_offset	data_out_integrity_check_offset;
+} __packed;
+/*200 v1*/
+
+struct osdv1_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSDv1_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
+struct osd_cdb {
+	union {
+		struct osdv1_cdb v1;
+		u8 buff[OSD_TOTAL_CDB_LEN];
+	};
+} __packed;
+
+static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
+{
+	return (struct osd_cdb_head *)ocdb->buff;
+}
+
+/* define both version actions
+ * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
+ */
+#define OSD_ACT___(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
+
+/* V2 only actions */
+#define OSD_ACT_V2(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
+
+#define OSD_ACT_V1_V2(Name, Num1, Num2) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
+
+enum osd_service_actions {
+	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
+	OSD_ACT___(FORMAT_OSD,			0x01)
+	OSD_ACT___(CREATE,			0x02)
+	OSD_ACT___(LIST,			0x03)
+	OSD_ACT_V2(PUNCH,			0x04)
+	OSD_ACT___(READ,			0x05)
+	OSD_ACT___(WRITE,			0x06)
+	OSD_ACT___(APPEND,			0x07)
+	OSD_ACT___(FLUSH,			0x08)
+	OSD_ACT_V2(CLEAR,			0x09)
+	OSD_ACT___(REMOVE,			0x0A)
+	OSD_ACT___(CREATE_PARTITION,		0x0B)
+	OSD_ACT___(REMOVE_PARTITION,		0x0C)
+	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
+	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
+	OSD_ACT___(CREATE_AND_WRITE,		0x12)
+	OSD_ACT___(CREATE_COLLECTION,		0x15)
+	OSD_ACT___(REMOVE_COLLECTION,		0x16)
+	OSD_ACT___(LIST_COLLECTION,		0x17)
+	OSD_ACT___(SET_KEY,			0x18)
+	OSD_ACT___(SET_MASTER_KEY,		0x19)
+	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
+	OSD_ACT___(FLUSH_PARTITION,		0x1B)
+	OSD_ACT___(FLUSH_OSD,			0x1C)
+
+	OSD_ACT_V2(QUERY,			0x20)
+	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
+	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
+	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
+	OSD_ACT_V2(READ_MAP,			0x31)
+
+	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
+	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
+	/* 0x8F80 to 0x8FFF are Vendor specific */
+};
+
+/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
+struct osd_attributes_list_attrid {
+	__be32 page;
+	__be32 attr_id;
+} __packed;
+
+/*
+ * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
+ *                  for setting attributes
+ */
+struct osd_attributes_list_element {
+	__be32 page;
+	__be32 attr_id;
+	__be16 attr_bytes;
+	u8 attr_val[0];
+} __packed;
+
+enum {
+	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+};
+
+enum {
+	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
+	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
+};
+
+static inline unsigned osdv1_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
+}
+
+/*
+ * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
+ */
+enum osd_attr_list_types {
+	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
+	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
+	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
+	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
+};
+
+/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
+struct osd_attributes_list_multi_header {
+	__be64 object_id;
+	u8 object_type; /* object_type enum below */
+	u8 reserved[5];
+	__be16 list_bytes;
+	/* followed by struct osd_attributes_list_element's */
+};
+
+struct osdv1_attributes_list_header {
+	u8 type;	/* low 4-bit only */
+	u8 pad;
+	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
+{
+	return be16_to_cpu(h->list_bytes);
+}
+
+/* (osd-r10 6.13)
+ * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
+ *	for root_lstchg below
+ */
+enum {
+	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
+	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
+};
+
+/*
+ * osd2r03: 6.15.2 LIST command parameter data
+ * (Also for LIST COLLECTION)
+ */
+struct osd_obj_id_list {
+	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
+	__be64 continuation_id;
+	__be32 list_identifier;
+	u8 pad[3];
+	u8 root_lstchg;
+	__be64 object_ids[0];
+} __packed;
+
+static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
+	bool *is_changed)
+{
+	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
+	return 0 != list->continuation_id;
+}
+
+/*
+ * osd2r03: 4.12.4.5 The ALLDATA security method
+ */
+struct osd_data_out_integrity_info {
+	__be64 data_bytes;
+	__be64 set_attributes_bytes;
+	__be64 get_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_data_in_integrity_info {
+	__be64 data_bytes;
+	__be64 retrieved_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_timestamp {
+	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
+} __packed;
+/* FIXME: define helper functions to convert to/from osd time format */
+
+/*
+ * Capability & Security definitions
+ * osd2r03: 4.11.2.2 Capability format
+ * osd2r03: 5.2.8 Security parameters
+ */
+
+struct osd_key_identifier {
+	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+} __packed;
+
+/* for osd_capability.format */
+enum {
+	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
+	OSD_SEC_CAP_FORMAT_VER1 = 1,
+	OSD_SEC_CAP_FORMAT_VER2 = 2,
+};
+
+/* security_method */
+enum {
+	OSD_SEC_NOSEC = 0,
+	OSD_SEC_CAPKEY = 1,
+	OSD_SEC_CMDRSP = 2,
+	OSD_SEC_ALLDATA = 3,
+};
+
+enum object_type {
+	OSD_SEC_OBJ_ROOT = 0x1,
+	OSD_SEC_OBJ_PARTITION = 0x2,
+	OSD_SEC_OBJ_COLLECTION = 0x40,
+	OSD_SEC_OBJ_USER = 0x80,
+};
+
+enum osd_capability_bit_masks {
+	OSD_SEC_CAP_APPEND	= (1 << 0),
+	OSD_SEC_CAP_OBJ_MGMT	= (1 << 1),
+	OSD_SEC_CAP_REMOVE	= (1 << 2),
+	OSD_SEC_CAP_CREATE	= (1 << 3),
+	OSD_SEC_CAP_SET_ATTR	= (1 << 4),
+	OSD_SEC_CAP_GET_ATTR	= (1 << 5),
+	OSD_SEC_CAP_WRITE	= (1 << 6),
+	OSD_SEC_CAP_READ	= (1 << 7),
+
+	OSD_SEC_CAP_NONE1	= (1 << 8),
+	OSD_SEC_CAP_NONE2	= (1 << 9),
+	OSD_SEC_CAP_NONE3	= (1 << 10),
+	OSD_SEC_CAP_QUERY	= (1 << 11), /*v2 only*/
+	OSD_SEC_CAP_M_OBJECT	= (1 << 12), /*v2 only*/
+	OSD_SEC_CAP_POL_SEC	= (1 << 13),
+	OSD_SEC_CAP_GLOBAL	= (1 << 14),
+	OSD_SEC_CAP_DEV_MGMT	= (1 << 15),
+};
+
+/* for object_descriptor_type (hi nibble used) */
+enum {
+	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
+	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
+	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
+	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
+};
+
+/* (osd-r10:4.9.2.2)
+ * osd2r03:4.11.2.2 Capability format
+ */
+struct osd_capability_head {
+	u8 format; /* low nibble */
+	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
+	u8 security_method;
+	u8 reserved1;
+/*04*/	struct osd_timestamp expiration_time;
+/*10*/	u8 audit[30-10];
+/*30*/	u8 discriminator[42-30];
+/*42*/	struct osd_timestamp object_created_time;
+/*48*/	u8 object_type;
+	u8 permissions_bit_mask[54-49];
+/*54*/	u8 reserved2;
+/*55*/	u8 object_descriptor_type; /* high nibble */
+} __packed;
+
+/*56 v1*/
+struct osdv1_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 policy_access_tag;
+/*60*/			__be64 allowed_partition_id;
+/*68*/			__be64 allowed_object_id;
+/*76*/			__be32 reserved;
+		} __packed obj_desc;
+
+		u8 object_descriptor[80-56];/*24*/
+	};
+} __packed;
+/*80 v1*/
+
+struct osd_capability {
+	struct osd_capability_head h;
+	struct osdv1_cap_object_descriptor od;
+} __packed;
+
+/**
+ * osd_sec_set_caps - set cap-bits into the capabilities header
+ *
+ * @cap:	The osd_capability_head to set cap bits to.
+ * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
+ *
+ * permissions_bit_mask is unaligned use below to set into caps
+ * in a version independent way
+ */
+static inline void osd_sec_set_caps(struct osd_capability_head *cap,
+	u16 bit_mask)
+{
+	/*
+	 *Note: The bits above are defined LE order this is because this way
+	 *      they can grow in the future to more then 16, and still retain
+	 *      there constant values.
+	 */
+	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
+}
+
+#endif /* ndef __OSD_PROTOCOL_H__ */
diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h
new file mode 100644
index 0000000..4c09fee
--- /dev/null
+++ b/include/scsi/osd_sec.h
@@ -0,0 +1,45 @@
+/*
+ * osd_sec.h - OSD security manager API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_SEC_H__
+#define __OSD_SEC_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/*
+ * Contains types and constants of osd capabilities and security
+ * encoding/decoding.
+ * API is trying to keep security abstract so initiator of an object
+ * based pNFS client knows as little as possible about security and
+ * capabilities. It is the Server's osd-initiator place to know more.
+ * Also can be used by osd-target.
+ */
+void osd_sec_encode_caps(void *caps, ...);/* NI */
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1);
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_params);
+
+/* Conditionally sign the CDB according to security setting in ocdb
+ * with cap_key */
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key);
+
+/* Unconditionally sign the BIO data with cap_key.
+ * Check for osd_is_sec_alldata() was done prior to calling this. */
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key);
+
+/* Version independent copy of caps into the cdb */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps);
+
+#endif /* ndef __OSD_SEC_H__ */
diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h
new file mode 100644
index 0000000..ea5372d
--- /dev/null
+++ b/include/scsi/osd_types.h
@@ -0,0 +1,40 @@
+/*
+ * osd_types.h - Types and constants which are not part of the protocol.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Contains types and constants that are implementation specific and are
+ * used by more than one part of the osd library.
+ *     (Eg initiator/target/security_manager/...)
+ */
+#ifndef __OSD_TYPES_H__
+#define __OSD_TYPES_H__
+
+struct osd_systemid {
+	u8 data[OSD_SYSTEMID_LEN];
+};
+
+typedef u64 __bitwise osd_id;
+
+struct osd_obj_id {
+	osd_id partition;
+	osd_id id;
+};
+
+static const struct __weak osd_obj_id osd_root_object = {0, 0};
+
+struct osd_attr {
+	u32 page;
+	u32 attr_id;
+	u16 len;		/* byte count of operand */
+	void *val_ptr;		/* in network order */
+};
+
+#endif /* ndef __OSD_TYPES_H__ */
-- 
1.6.0.1


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* Re: [osd-dev] [PATCH 04/18] libosd: OSDv1 preliminary implementation
  2008-11-05 13:12       ` Boaz Harrosh
@ 2008-11-09 14:55         ` Boaz Harrosh
  2008-11-10  5:37           ` Randy Dunlap
  0 siblings, 1 reply; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-09 14:55 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: open-osd development, Mike Christie, linux-scsi, Jeff Garzik,
	Sami.Iren, linux-kernel, James Bottomley, Andrew Morton,
	Randy Dunlap

Boaz Harrosh wrote:
> Sam Ravnborg wrote:
>>> +EXPORT_SYMBOL(osd_dev_init);
>> kernel-doc comments for all exported funtions / variables.
>>
> 
> I have some kernel-doc comments of exported functions in the Header
> file. I have not yet finished all of them. (Laziness on my part).
> 
> Are kernel-doc comments in headers a big NO-NO. I like it this way,
> so when I have to learn a new Library all the information
> I need to know is in the header. Also the header is a much better place
> when you do programing by shopping, that is you don't know what you need
> and you look for what's available.
> 
> Thanks
> Boaz

Sam please comment if kernel-doc comments are OK in headers

Thanks
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCHSET 00/18] open-osd: OSD Initiator library for Linux
  2008-11-04 19:19   ` [PATCHSET 00/18] open-osd: OSD Initiator library for Linux Andrew Morton
  2008-11-05 13:56     ` Boaz Harrosh
@ 2008-11-09 14:58     ` Boaz Harrosh
  2008-11-09 23:26       ` Stephen Rothwell
  1 sibling, 1 reply; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-09 14:58 UTC (permalink / raw)
  To: Andrew Morton, James.Bottomley, linux-next, Stephen Rothwell,
	Sam Ravnborg
  Cc: michaelc, fujita.tomonori, jeff, osd-dev, linux-scsi, Sami.Iren,
	Pete Wyckoff, linux-kernel

Andrew Morton wrote:
> On Tue, 04 Nov 2008 18:09:31 +0200
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> Please consider for inclusion, an in-kernel OSD initiator
>> library. Its main users are planned to be various OSD based file
>> systems and the pNFS-Objects Layout Driver. (To be submitted soon)
>>  
>> To try out and run the library please visit
>> http://open-osd.org and follow the instructions there.
>>
>> The submitted patchset is also available via git at:
>>    git://git.open-osd.org/linux-open-osd.git osd
>>    http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=osd
>>
>> Or a compact out-of-tree repository that includes sources 
>> and some extras:
>>    git://git.open-osd.org/open-osd.git master
>>    http://git.open-osd.org/gitweb.cgi?p=open-osd.git;a=summary
>>
>> ...
>>
>> We would like this to sit in -mm tree for a while to make sure it is compilable
>> on all platform.
> 
> The best way to do that is to include your git tree in linux-next.  If
> this code has a probably-will-be-merged-in-2.6.29 status then please
> prepare a branch for Stephen to include in the linux-next lineup.
> 

Hi Stephen and James

I have prepared a branch for linux-next based on today's Linus tree
It is here:
    git://git.open-osd.org/linux-open-osd.git linux-next
This is if it's OK with James, as these bits are his responsibility.
They need only sit in linux-next for a couple of weeks to get some wider
compilation exposure. Other then that they are totally new code and
are safe. Eventually they should be included into Linux-next through
scsi-misc-2.6.

I have only posted "ver 2" updates to a couple of patches that had
comments by people but more patches changed. Mainly:
- rename of scsi_dev => scsi_device
- missing static keyword
- Kbuild fixes and comments by Sam Ravnborg
- small typos found on the way

The new patchset can be reviewed at:
    git://git.open-osd.org/linux-open-osd.git linux-next
    http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=linux-next

or Based on current scsi-misc-2.6:
    git://git.open-osd.org/linux-open-osd.git osd
    http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=osd

I did not want to spam the mailing-list with somewhat same patches.
I will post them, if any one needs me to.

Thanks everyone for your help
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver2] libosd: OSDv1 Headers
  2008-11-09 14:52       ` Boaz Harrosh
@ 2008-11-09 17:45         ` Jörn Engel
  -1 siblings, 0 replies; 183+ messages in thread
From: Jörn Engel @ 2008-11-09 17:45 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James Bottomley, Andrew Morton, open-osd development,
	Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-scsi,
	Sami.Iren, linux-kernel

On Sun, 9 November 2008 16:52:36 +0200, Boaz Harrosh wrote:
> 
> +struct osdv1_cdb {
> +	struct osd_cdb_head h;
> +	u8 caps[OSDv1_CAP_LEN];
> +	struct osd_security_parameters sec_params;
> +} __packed;

__packed can result in slow code being generated.  But removing the
attribute can lead to bugs on other architectures.  F.e. the size of
the structure below is different for i386 and x86_64.

struct foo {
	u64 bar;
	u32 baz;
};

My personal solution is to use this little macro and then just follow
every structure defition with a size check.

#define SIZE_CHECK(type, size)					\
static inline void check_##type(void)				\
{								\
	BUILD_BUG_ON(sizeof(struct type) != (size));		\
}
...
struct foo {
	u64 bar;
	u32 baz;
};

SIZE_CHECK(foo, 12);

The above would not compile on x86_64 and clearly indicate a missing
__packed.  In other cases the attribute can be removed.

Jörn

-- 
Invincibility is in oneself, vulnerability is in the opponent.
-- Sun Tzu

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver2] libosd: OSDv1 Headers
@ 2008-11-09 17:45         ` Jörn Engel
  0 siblings, 0 replies; 183+ messages in thread
From: Jörn Engel @ 2008-11-09 17:45 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James Bottomley, Andrew Morton, open-osd development,
	Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-scsi,
	Sami.Iren, linux-kernel

On Sun, 9 November 2008 16:52:36 +0200, Boaz Harrosh wrote:
> 
> +struct osdv1_cdb {
> +	struct osd_cdb_head h;
> +	u8 caps[OSDv1_CAP_LEN];
> +	struct osd_security_parameters sec_params;
> +} __packed;

__packed can result in slow code being generated.  But removing the
attribute can lead to bugs on other architectures.  F.e. the size of
the structure below is different for i386 and x86_64.

struct foo {
	u64 bar;
	u32 baz;
};

My personal solution is to use this little macro and then just follow
every structure defition with a size check.

#define SIZE_CHECK(type, size)					\
static inline void check_##type(void)				\
{								\
	BUILD_BUG_ON(sizeof(struct type) != (size));		\
}
...
struct foo {
	u64 bar;
	u32 baz;
};

SIZE_CHECK(foo, 12);

The above would not compile on x86_64 and clearly indicate a missing
__packed.  In other cases the attribute can be removed.

Jörn

-- 
Invincibility is in oneself, vulnerability is in the opponent.
-- Sun Tzu
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCHSET 00/18] open-osd: OSD Initiator library for Linux
  2008-11-09 14:58     ` Boaz Harrosh
@ 2008-11-09 23:26       ` Stephen Rothwell
  2008-11-10 12:52         ` Boaz Harrosh
  0 siblings, 1 reply; 183+ messages in thread
From: Stephen Rothwell @ 2008-11-09 23:26 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: Andrew Morton, James.Bottomley, linux-next, Sam Ravnborg,
	michaelc, fujita.tomonori, jeff, osd-dev, linux-scsi, Sami.Iren,
	Pete Wyckoff, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1069 bytes --]

Hi Boaz,

On Sun, 09 Nov 2008 16:58:59 +0200 Boaz Harrosh <bharrosh@panasas.com> wrote:
>
> I have prepared a branch for linux-next based on today's Linus tree
> It is here:
>     git://git.open-osd.org/linux-open-osd.git linux-next
> This is if it's OK with James, as these bits are his responsibility.
> They need only sit in linux-next for a couple of weeks to get some wider
> compilation exposure. Other then that they are totally new code and
> are safe. Eventually they should be included into Linux-next through
> scsi-misc-2.6.

I have added that tree to linux-next for today.

What I say to everyone:  commits in that branch must have been posted
somewhere appropriate, reviewed, unit tested and destined for the next
merge window.  Also, note that my (new) practise is to temporarily drop a
tree if it causes non-trivial conflicts (especially with Linus' tree), so
don't be too upset if you get a message from me to that effect.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [osd-dev] [PATCH 04/18] libosd: OSDv1 preliminary implementation
  2008-11-09 14:55         ` [osd-dev] " Boaz Harrosh
@ 2008-11-10  5:37           ` Randy Dunlap
  2008-11-10  9:00             ` Boaz Harrosh
  0 siblings, 1 reply; 183+ messages in thread
From: Randy Dunlap @ 2008-11-10  5:37 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: Sam Ravnborg, open-osd development, Mike Christie, linux-scsi,
	Jeff Garzik, Sami.Iren, linux-kernel, James Bottomley,
	Andrew Morton, Randy Dunlap

Boaz Harrosh wrote:
> Boaz Harrosh wrote:
>> Sam Ravnborg wrote:
>>>> +EXPORT_SYMBOL(osd_dev_init);
>>> kernel-doc comments for all exported funtions / variables.
>>>
>> I have some kernel-doc comments of exported functions in the Header
>> file. I have not yet finished all of them. (Laziness on my part).
>>
>> Are kernel-doc comments in headers a big NO-NO. I like it this way,
>> so when I have to learn a new Library all the information
>> I need to know is in the header. Also the header is a much better place
>> when you do programing by shopping, that is you don't know what you need
>> and you look for what's available.
>>
>> Thanks
>> Boaz
> 
> Sam please comment if kernel-doc comments are OK in headers

Hi,

The de facto standard for kernel-doc comments is at the implementation site,
which means normally in .c files, except for macros or inline functions.

Sure you can find some exceptions to that.  And there is no hard requirement
in Documentation/kernel-doc-nano-HOWTO.txt.

IMO the biggest concern is making sure that the (kernel-doc) comments are
updated when the function implementation changes (if updates are needed).
Where would be the best place for this to be more likely to happen?
Usually at the function implementation, I would say.

~Randy


-- 
~Randy

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver2] libosd: OSDv1 Headers
  2008-11-09 17:45         ` Jörn Engel
@ 2008-11-10  8:47           ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-10  8:47 UTC (permalink / raw)
  To: Jörn Engel
  Cc: James Bottomley, Andrew Morton, open-osd development,
	Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-scsi,
	Sami.Iren, linux-kernel

Jörn Engel wrote:
> On Sun, 9 November 2008 16:52:36 +0200, Boaz Harrosh wrote:
>> +struct osdv1_cdb {
>> +	struct osd_cdb_head h;
>> +	u8 caps[OSDv1_CAP_LEN];
>> +	struct osd_security_parameters sec_params;
>> +} __packed;
> 
> __packed can result in slow code being generated.  But removing the
> attribute can lead to bugs on other architectures.  F.e. the size of
> the structure below is different for i386 and x86_64.
> 
> struct foo {
> 	u64 bar;
> 	u32 baz;
> };
> 
> My personal solution is to use this little macro and then just follow
> every structure defition with a size check.
> 
> #define SIZE_CHECK(type, size)					\
> static inline void check_##type(void)				\
> {								\
> 	BUILD_BUG_ON(sizeof(struct type) != (size));		\
> }
> ...
> struct foo {
> 	u64 bar;
> 	u32 baz;
> };
> 
> SIZE_CHECK(foo, 12);
> 
> The above would not compile on x86_64 and clearly indicate a missing
> __packed.  In other cases the attribute can be removed.
> 
> Jörn
> 

Hi Jörn
Thank you for your comments

I do have a size check that governs the complete structure it is the first
code in osd_initiator.c at build_test(). It will catch any discrepancies
from the protocol.

I have done some experimentation with __packed both on 32 and 64 bit x86.
When it does nothing like the above foo in 32bit, then there is no code
difference with it or with out it, but on 64bit I must have it otherwise
the structure grows.

These are all, on-the-wire structures. I must have __packed, otherwise
I'm at the compiler mercy and that's bad.

If the assembly - size and offsets - of foo is exactly the same with or
without the __packed, but the generated code is different then clearly this
is a compiler bug. I've herd of this myth before, and at least with my
gcc 4.1.2 there is no such bug. Either the structure gets packed, or there is
no difference. All the places I have __packed in the code are absolutely must
be so, stated by the protocol.

Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver2] libosd: OSDv1 Headers
@ 2008-11-10  8:47           ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-10  8:47 UTC (permalink / raw)
  To: Jörn Engel
  Cc: James Bottomley, Andrew Morton, open-osd development,
	Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-scsi,
	Sami.Iren, linux-kernel

Jörn Engel wrote:
> On Sun, 9 November 2008 16:52:36 +0200, Boaz Harrosh wrote:
>> +struct osdv1_cdb {
>> +	struct osd_cdb_head h;
>> +	u8 caps[OSDv1_CAP_LEN];
>> +	struct osd_security_parameters sec_params;
>> +} __packed;
> 
> __packed can result in slow code being generated.  But removing the
> attribute can lead to bugs on other architectures.  F.e. the size of
> the structure below is different for i386 and x86_64.
> 
> struct foo {
> 	u64 bar;
> 	u32 baz;
> };
> 
> My personal solution is to use this little macro and then just follow
> every structure defition with a size check.
> 
> #define SIZE_CHECK(type, size)					\
> static inline void check_##type(void)				\
> {								\
> 	BUILD_BUG_ON(sizeof(struct type) != (size));		\
> }
> ...
> struct foo {
> 	u64 bar;
> 	u32 baz;
> };
> 
> SIZE_CHECK(foo, 12);
> 
> The above would not compile on x86_64 and clearly indicate a missing
> __packed.  In other cases the attribute can be removed.
> 
> Jörn
> 

Hi Jörn
Thank you for your comments

I do have a size check that governs the complete structure it is the first
code in osd_initiator.c at build_test(). It will catch any discrepancies
from the protocol.

I have done some experimentation with __packed both on 32 and 64 bit x86.
When it does nothing like the above foo in 32bit, then there is no code
difference with it or with out it, but on 64bit I must have it otherwise
the structure grows.

These are all, on-the-wire structures. I must have __packed, otherwise
I'm at the compiler mercy and that's bad.

If the assembly - size and offsets - of foo is exactly the same with or
without the __packed, but the generated code is different then clearly this
is a compiler bug. I've herd of this myth before, and at least with my
gcc 4.1.2 there is no such bug. Either the structure gets packed, or there is
no difference. All the places I have __packed in the code are absolutely must
be so, stated by the protocol.

Boaz
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [osd-dev] [PATCH 04/18] libosd: OSDv1 preliminary implementation
  2008-11-10  5:37           ` Randy Dunlap
@ 2008-11-10  9:00             ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-10  9:00 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Sam Ravnborg, open-osd development, Mike Christie, linux-scsi,
	Jeff Garzik, Sami.Iren, linux-kernel, James Bottomley,
	Andrew Morton

Randy Dunlap wrote:
> Boaz Harrosh wrote:
>> Boaz Harrosh wrote:
>>> Sam Ravnborg wrote:
>>>>> +EXPORT_SYMBOL(osd_dev_init);
>>>> kernel-doc comments for all exported funtions / variables.
>>>>
>>> I have some kernel-doc comments of exported functions in the Header
>>> file. I have not yet finished all of them. (Laziness on my part).
>>>
>>> Are kernel-doc comments in headers a big NO-NO. I like it this way,
>>> so when I have to learn a new Library all the information
>>> I need to know is in the header. Also the header is a much better place
>>> when you do programing by shopping, that is you don't know what you need
>>> and you look for what's available.
>>>
>>> Thanks
>>> Boaz
>> Sam please comment if kernel-doc comments are OK in headers
> 
> Hi,
> 
> The de facto standard for kernel-doc comments is at the implementation site,
> which means normally in .c files, except for macros or inline functions.
> 
> Sure you can find some exceptions to that.  And there is no hard requirement
> in Documentation/kernel-doc-nano-HOWTO.txt.
> 
> IMO the biggest concern is making sure that the (kernel-doc) comments are
> updated when the function implementation changes (if updates are needed).
> Where would be the best place for this to be more likely to happen?
> Usually at the function implementation, I would say.
> 
> ~Randy
> 
> 
Thanks Randy

I would like to keep them in the Headers then. This is because I make
sure that the implementation includes the declaring header, so any miss-matches
are caught by the compiler. 
And because these are all library routines exported to other modules. The important
thing is the API you linked with. If the API/parametrization change it must first
change in the header. The internal implementation is not documented only the external
black-box functionality is documented in these places.

I will think about it some more, but for now, if it's OK I would like to keep them
like submitted. In this particular library they make more sense to me in the header.

Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCHSET 00/18] open-osd: OSD Initiator library for Linux
  2008-11-09 23:26       ` Stephen Rothwell
@ 2008-11-10 12:52         ` Boaz Harrosh
  2008-11-10 13:04           ` Stephen Rothwell
  0 siblings, 1 reply; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-10 12:52 UTC (permalink / raw)
  To: Stephen Rothwell
  Cc: Andrew Morton, James.Bottomley, linux-next, Sam Ravnborg,
	michaelc, fujita.tomonori, jeff, osd-dev, linux-scsi, Sami.Iren,
	Pete Wyckoff, linux-kernel

Stephen Rothwell wrote:
> Hi Boaz,
> 
> On Sun, 09 Nov 2008 16:58:59 +0200 Boaz Harrosh <bharrosh@panasas.com> wrote:
>> I have prepared a branch for linux-next based on today's Linus tree
>> It is here:
>>     git://git.open-osd.org/linux-open-osd.git linux-next
>> This is if it's OK with James, as these bits are his responsibility.
>> They need only sit in linux-next for a couple of weeks to get some wider
>> compilation exposure. Other then that they are totally new code and
>> are safe. Eventually they should be included into Linux-next through
>> scsi-misc-2.6.
> 
> I have added that tree to linux-next for today.
> 
> What I say to everyone:  commits in that branch must have been posted
> somewhere appropriate, reviewed, unit tested and destined for the next
> merge window.  Also, note that my (new) practise is to temporarily drop a
> tree if it causes non-trivial conflicts (especially with Linus' tree), so
> don't be too upset if you get a message from me to that effect.
> 

Thank you Stephen, very much

This has proven itself already. I found some warnings on some ARCHs
concerning printk of u64 types. I have made a sweep and fixed all these
places and others.
(same place: git://git.open-osd.org/linux-open-osd.git linux-next)

If you could keep it for the next round it could be grate. So I can make
sure I got rid of all the warnings.

Thanks again
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCHSET 00/18] open-osd: OSD Initiator library for Linux
  2008-11-10 12:52         ` Boaz Harrosh
@ 2008-11-10 13:04           ` Stephen Rothwell
  0 siblings, 0 replies; 183+ messages in thread
From: Stephen Rothwell @ 2008-11-10 13:04 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: Andrew Morton, James.Bottomley, linux-next, Sam Ravnborg,
	michaelc, fujita.tomonori, jeff, osd-dev, linux-scsi, Sami.Iren,
	Pete Wyckoff, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 757 bytes --]

Hi Boaz,

On Mon, 10 Nov 2008 14:52:21 +0200 Boaz Harrosh <bharrosh@panasas.com> wrote:
>
> This has proven itself already. I found some warnings on some ARCHs
> concerning printk of u64 types. I have made a sweep and fixed all these
> places and others.

Good.  That's partly what -next is for (to find the arch dependent
problems).

> If you could keep it for the next round it could be grate. So I can make
> sure I got rid of all the warnings.

Normally trees stay in linux-next until they are no longer needed
(usually at least until they have been integrated into Linus' tree) and I
automatically refetch the trees each day.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver2] libosd: OSDv1 Headers
  2008-11-10  8:47           ` Boaz Harrosh
@ 2008-11-10 15:17             ` Jörn Engel
  -1 siblings, 0 replies; 183+ messages in thread
From: Jörn Engel @ 2008-11-10 15:17 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James Bottomley, Andrew Morton, open-osd development,
	Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-scsi,
	Sami.Iren, linux-kernel

On Mon, 10 November 2008 10:47:07 +0200, Boaz Harrosh wrote:
> 
> If the assembly - size and offsets - of foo is exactly the same with or
> without the __packed, but the generated code is different then clearly this
> is a compiler bug. I've herd of this myth before, and at least with my
> gcc 4.1.2 there is no such bug. Either the structure gets packed, or there is
> no difference. All the places I have __packed in the code are absolutely must
> be so, stated by the protocol.

Ok, if current compilers are fine, I won't complain.

Jörn

-- 
There's nothing better for promoting creativity in a medium than
making an audience feel "Hmm ­ I could do better than that!"
-- Douglas Adams in a slashdot interview

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver2] libosd: OSDv1 Headers
@ 2008-11-10 15:17             ` Jörn Engel
  0 siblings, 0 replies; 183+ messages in thread
From: Jörn Engel @ 2008-11-10 15:17 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James Bottomley, Andrew Morton, open-osd development,
	Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-scsi,
	Sami.Iren, linux-kernel

On Mon, 10 November 2008 10:47:07 +0200, Boaz Harrosh wrote:
> 
> If the assembly - size and offsets - of foo is exactly the same with or
> without the __packed, but the generated code is different then clearly this
> is a compiler bug. I've herd of this myth before, and at least with my
> gcc 4.1.2 there is no such bug. Either the structure gets packed, or there is
> no difference. All the places I have __packed in the code are absolutely must
> be so, stated by the protocol.

Ok, if current compilers are fine, I won't complain.

Jörn

-- 
There's nothing better for promoting creativity in a medium than
making an audience feel "Hmm ­ I could do better than that!"
-- Douglas Adams in a slashdot interview
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver2] libosd: OSDv1 Headers
  2008-11-09 14:52       ` Boaz Harrosh
  (?)
  (?)
@ 2008-11-10 17:29       ` Randy Dunlap
  2008-11-12 13:10           ` Boaz Harrosh
  2008-11-12 13:13           ` Boaz Harrosh
  -1 siblings, 2 replies; 183+ messages in thread
From: Randy Dunlap @ 2008-11-10 17:29 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James Bottomley, Andrew Morton, Jörn Engel,
	open-osd development, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, linux-scsi, Sami.Iren, linux-kernel

On Sun, 09 Nov 2008 16:52:36 +0200 Boaz Harrosh wrote:

> Headers only patch.
> 
> osd_protocol.h
> 	Contains a C-fied definition of the T10 OSD standard
> osd_types.h
> 	Contains CPU order common used types
> osd_initiator.h
> 	API definition of the osd_initiator library
> osd_sec.h
> 	Contains High level API for the security manager.
> 
> [Note that checkpatch spews errors on things that are valid in this context
> and will not be fixed]
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> Reviewed-by: Benny Halevy <bhalevy@panasas.com>
> ---
>  include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
>  include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
>  include/scsi/osd_sec.h       |   45 ++++
>  include/scsi/osd_types.h     |   40 ++++
>  4 files changed, 914 insertions(+), 0 deletions(-)
>  create mode 100644 include/scsi/osd_initiator.h
>  create mode 100644 include/scsi/osd_protocol.h
>  create mode 100644 include/scsi/osd_sec.h
>  create mode 100644 include/scsi/osd_types.h
> 
> diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
> new file mode 100644
> index 0000000..9bab95d
> --- /dev/null
> +++ b/include/scsi/osd_initiator.h
> @@ -0,0 +1,332 @@
> +/*
> + * osd_initiator.h - OSD initiator API definition
> + *
> + * Copyright (C) 2008 Panasas Inc.  All rights reserved.
> + *
> + * Authors:
> + *   Boaz Harrosh <bharrosh@panasas.com>
> + *   Benny Halevy <bhalevy@panasas.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + *
> + */
> +#ifndef __OSD_INITIATOR_H__
> +#define __OSD_INITIATOR_H__
> +
> +#include "osd_protocol.h"
> +#include "osd_types.h"
> +
> +#include <linux/blkdev.h>
> +
> +/* Note: "NI" in comments below means "Not Implemented yet" */
> +
> +/*
> + * Object-based Storage Device.
> + * This object represents an OSD device.
> + * It is not a full linux device in any way. It is only
> + * a place to hang resources associated with a Linux
> + * request Q and some default properties.
> + */
> +struct osd_dev {
> +	struct scsi_device *scsi_device;
> +	unsigned def_timeout;
> +};
> +
> +void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);

Don't mix having parameter names and not having them.
Preferred is having them.

> +void osd_dev_fini(struct osd_dev *);
> +
> +struct osd_request;
> +typedef void (osd_req_done_fn)(struct osd_request *, void *);
> +
> +struct osd_request {
> +	struct osd_cdb cdb;
> +	struct osd_data_out_integrity_info out_data_integ;
> +	struct osd_data_in_integrity_info in_data_integ;
> +
> +	struct osd_dev *osd_dev;
> +	struct request *request;
> +
> +	struct _osd_req_data_segment {
> +		void *buff;
> +		unsigned alloc_size; /* 0 here means not allocated by us */

Could/would some other code allocate it, or is the "by us" just redundant?

> +		unsigned total_bytes;
> +	} set_attr, enc_get_attr, get_attr;
> +
> +	struct _osd_io_info {
> +		struct bio *bio;
> +		u64 total_bytes;
> +		struct request *req;
> +		struct _osd_req_data_segment *last_seg;
> +		u8 *pad_buff;
> +	} out, in;
> +
> +	gfp_t alloc_flags;
> +	unsigned timeout;
> +	unsigned retries;
> +	u8 sense[OSD_MAX_SENSE_LEN];
> +	enum osd_attributes_mode attributes_mode;
> +
> +	osd_req_done_fn *async_done;
> +	void *async_private;
> +	int async_error;
> +};
> +
> +/**

Don't start comment blocks with /** when they are not kernel-doc,
like this one is not.

> + * How to use the osd library:
> + *
> + * osd_start_request
> + *	Allocates a request.
> + *
> + * osd_req_*
> + *	Call one of, to encode the desired operation.
> + *
> + * osd_add_{get,set}_attr
> + *	Optionally add attributes to the CDB, list or page mode.
> + *
> + * osd_finalize_request
> + *	Computes final data out/in offsets and signs the request,
> + *	making it ready for execution.
> + *
> + * osd_execute_request
> + *	May be called to execute it through the block layer. Other wise submit
> + *	the associated block request in some other way.
> + *
> + * After execution:
> + * osd_req_decode_sense
> + *	Decodes sense information to verify execution results.
> + *
> + * osd_req_decode_get_attr
> + *	Retrieve osd_add_get_attr_list() values if used.
> + *
> + * osd_end_request
> + *	Must be called to deallocate the request.
> + */
> +
> +/**
> + * osd_start_request - Allocate and initialize an osd_request
> + *
> + * @osd_dev:    OSD device that holds the scsi-device and default values
> + *              that the request is associated with.
> + * @gfp:        The allocation flags to use for request allocation, and all
> + *              subsequent allocations. This will be stored at
> + *              osd_request->alloc_flags, can be changed by user later
> + *
> + * Allocate osd_request and initialize all members to the
> + * default/initial state.
> + */
> +struct osd_request *osd_start_request(struct osd_dev *, gfp_t gfp);
> +
> +enum osd_req_options {
> +	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
> +	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
> +
> +	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
> +};
> +
> +/**
> + * osd_finalize_request - Sign request and prepare request for execution
> + *
> + * @or:		osd_request to prepare
> + * @options:	combination of osd_req_options bit flags or 0.
> + * @cap	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
> + *              The security manager as capabilities for this cdb.
> + * @cap_key	The cryptographic key used to sign the cdb/data. Can be null
> + *              if NOSEC is used.

Last 2 parameters need a ':' after the @param_name, like the first 2 have.

> + *
> + * The actual request and bios are only allocated here, so are the get_attr
> + * buffers that will receive the returned attributes. Copy's @cap to cdb.
> + * Sign the cdb/data with @cap_key.
> + */
> +int osd_finalize_request(struct osd_request *or,
> +	u8 options, const void *cap, const u8 *cap_key);
> +
> +/**
> + * osd_execute_request - Execute the request synchronously through
> + *                       the block-layer

Function name and short description need to be on one line.

> + * @or:		osd_request to Executed
> + *
> + * Calls blk_execute_rq to q the command and waits for completion.
> + */
> +int osd_execute_request(struct osd_request *or);
> +
> +/**
> + * osd_execute_request_async - submits the request for execution through
> + *                             the block-layer without waitting.

Ditto.

> + * @or:                      - osd_request to Executed
> + * @done: (Optional)         - Called at end of execution
> + * @private:                 - Will be passes to @done function

s/passes/passed/

> + *
> + * Calls blk_execute_rq_nowait to q the command. When execution is done
> + * Optionally calles @done with @private as parameter. or->async_error has the

s/calles/calls/

> + * Return code

and don't start each line with a Capital letter since they are not the
beginning of sentences.  What's with that period ('.') before "or->async_error"
(which needs a space after "or").


> + */
> +int osd_execute_request_async(struct osd_request *or,
> +	osd_req_done_fn *done, void *private);
> +
> +/**
> + * osd_end_request - return osd_request to free store
> + *
> + * @or:		osd_request to free
> + *
> + * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
> + */
> +void osd_end_request(struct osd_request *or);
> +
> +/*
> + * CDB Encoding
> + *
> + * Note: call only one of the following methods.
> + */
> +
> +/*
> + * Device commands
> + */
> +void osd_req_set_master_seed_xchg(struct osd_request *, ...);/* NI */
> +void osd_req_set_master_key(struct osd_request *, ...);/* NI */
> +
> +void osd_req_format(struct osd_request *, u64 tot_capacity);
> +
> +/* list all partitions
> + * @list header must be initialized to zero on first run.
> + *
> + * Call osd_is_obj_list_done() to find if we got the complete list.
> + */
> +int osd_req_list_dev_partitions(struct osd_request *,
> +	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
> +
> +void osd_req_flush_obsd(struct osd_request *,
> +	enum osd_options_flush_scope_values);
> +
> +void osd_req_perform_scsi_command(struct osd_request *,
> +	const u8 *cdb, ...);/* NI */
> +void osd_req_task_management(struct osd_request *, ...);/* NI */
> +
> +/*
> + * Partition commands
> + */
> +void osd_req_create_partition(struct osd_request *, osd_id partition);
> +void osd_req_remove_partition(struct osd_request *, osd_id partition);
> +
> +void osd_req_set_partition_key(struct osd_request *,
> +	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
> +	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
> +
> +/* list all collections in the partition
> + * @list header must be init to zero on first run.
> + *
> + * Call osd_is_obj_list_done() to find if we got the complete list.
> + */
> +int osd_req_list_partition_collections(struct osd_request *,
> +	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
> +	unsigned nelem);
> +
> +/* list all objects in the partition
> + * @list header must be init to zero on first run.
> + *
> + * Call osd_is_obj_list_done() to find if we got the complete list.
> + */
> +int osd_req_list_partition_objects(struct osd_request *,
> +	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
> +	unsigned nelem);
> +
> +void osd_req_flush_partition(struct osd_request *,
> +	osd_id partition, enum osd_options_flush_scope_values);
> +
> +/*
> + * Collection commands
> + */
> +void osd_req_create_collection(struct osd_request *,
> +	const struct osd_obj_id *);/* NI */
> +void osd_req_remove_collection(struct osd_request *,
> +	const struct osd_obj_id *);/* NI */
> +
> +/* list all objects in the collection */
> +int osd_req_list_collection_objects(struct osd_request *,
> +	const struct osd_obj_id *, osd_id initial_id,
> +	struct osd_obj_id_list *list, unsigned nelem);
> +
> +/* V2 only filtered list of objects in the collection */
> +void osd_req_query(struct osd_request *, ...);/* NI */
> +
> +void osd_req_flush_collection(struct osd_request *,
> +	const struct osd_obj_id *, enum osd_options_flush_scope_values);
> +
> +void osd_req_get_member_attrs(struct osd_request *, ...);/* V2-only NI */
> +void osd_req_set_member_attrs(struct osd_request *, ...);/* V2-only NI */
> +
> +/*
> + * Object commands
> + */
> +void osd_req_create_object(struct osd_request *, struct osd_obj_id *);
> +void osd_req_remove_object(struct osd_request *, struct osd_obj_id *);
> +
> +void osd_req_write(struct osd_request *,
> +	const struct osd_obj_id *, struct bio *data_out, u64 offset);
> +void osd_req_append(struct osd_request *,
> +	const struct osd_obj_id *, struct bio *data_out);/* NI */
> +void osd_req_create_write(struct osd_request *,
> +	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
> +void osd_req_clear(struct osd_request *,
> +	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
> +void osd_req_punch(struct osd_request *,
> +	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
> +
> +void osd_req_flush_object(struct osd_request *,
> +	const struct osd_obj_id *, enum osd_options_flush_scope_values,
> +	/*V2*/ u64 offset, /*V2*/ u64 len);
> +
> +void osd_req_read(struct osd_request *,
> +	const struct osd_obj_id *, struct bio *data_in, u64 offset);
> +
> +/*
> + * Root/Partition/Collection/Object Attributes commands
> + */
> +
> +/* get before set */
> +void osd_req_get_attributes(struct osd_request *, const struct osd_obj_id *);
> +
> +/* set before get */
> +void osd_req_set_attributes(struct osd_request *, const struct osd_obj_id *);
> +
> +/*
> + * Attributes appended to most commands
> + */
> +
> +/* Attributes List mode (or V2 CDB) */
> +  /*
> +   * TODO: In ver2 if at finalize time only one attr was set and no gets,
> +   * then the Attributes CDB mode is used automatically to save IO.
> +   */
> +
> +/* set a list of attributes. */
> +int osd_req_add_set_attr_list(struct osd_request *,
> +	const struct osd_attr *, unsigned nelem);
> +
> +/* get a list of attributes */
> +int osd_req_add_get_attr_list(struct osd_request *,
> +	const struct osd_attr *, unsigned nelem);
> +
> +/*
> + * Attributes list decoding
> + * Must be called after osd_request.request was executed
> + * It is called in a loop to decode the returned get_attr
> + * (see osd_add_get_attr)
> + */
> +int osd_req_decode_get_attr_list(struct osd_request *,
> +	struct osd_attr *, int *nelem, void **iterator);
> +
> +/* Attributes Page mode */
> +
> +/*
> + * Read an attribute page and optionally set one attribute
> + *
> + * Retrieves the attribute page directly to a user buffer.
> + * @attr_page_data shall stay valid until end of execution.
> + * See osd_attributes.h for common page structures
> + */
> +int osd_req_add_get_attr_page(struct osd_request *,
> +	u32 page_id, void *attr_page_data, unsigned max_page_len,
> +	const struct osd_attr *set_one);
> +
> +#endif /* __OSD_LIB_H__ */
> diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
> new file mode 100644
> index 0000000..77a74a3
> --- /dev/null
> +++ b/include/scsi/osd_protocol.h
> @@ -0,0 +1,497 @@
> +/*
> + * osd_protocol.h - OSD T10 standard C definitions.
> + *
> + * Copyright (C) 2008 Panasas Inc.  All rights reserved.
> + *
> + * Authors:
> + *   Boaz Harrosh <bharrosh@panasas.com>
> + *   Benny Halevy <bhalevy@panasas.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + *
> + * This file contains types and constants that are defined by the protocol
> + * Note: All names and symbols are taken from the OSD standard's text.
> + */
> +#ifndef __OSD_PROTOCOL_H__
> +#define __OSD_PROTOCOL_H__
> +
> +#include <linux/types.h>
> +#include <asm/unaligned.h>
> +#include <scsi/scsi.h>
> +
> +enum {
> +	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
> +	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
> +	OSDv1_CAP_LEN = 80,
> +	/* Latest supported version */
> +	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
> +	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
> +	OSD_CAP_LEN = OSDv1_CAP_LEN,
> +
> +	OSD_SYSTEMID_LEN = 20,
> +	OSD_CRYPTO_KEYID_SIZE = 20,
> +	OSD_CRYPTO_SEED_SIZE = 4,
> +	OSD_CRYPTO_NONCE_SIZE = 12,
> +	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
> +
> +	OSD_PARTITION_FIRST_ID = 0x10000,
> +	OSD_OBJECT_FIRST_ID = 0x10000,
> +};
> +
> +/* (osd-r10 5.2.4)
> + * osd2r03: 5.2.3 Caching control bits
> + */
> +enum osd_options_byte {
> +	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
> +	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
> +};
> +
> +/*
> + * osd2r03: 5.2.5 Isolation.
> + * First 3 bits, V2-only.
> + * Also for attr 110h "default isolation method" at Root Information page
> + */
> +enum osd_options_byte_isolation {
> +	OSD_ISOLATION_DEFAULT = 0,
> +	OSD_ISOLATION_NONE = 1,
> +	OSD_ISOLATION_STRICT = 2,
> +	OSD_ISOLATION_RANGE = 4,
> +	OSD_ISOLATION_FUNCTIONAL = 5,
> +	OSD_ISOLATION_VENDOR = 7,
> +};
> +
> +/* (osd-r10: 6.7)
> + * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
> + */
> +enum osd_options_flush_scope_values {
> +	OSD_CDB_FLUSH_ALL = 0,
> +	OSD_CDB_FLUSH_ATTR_ONLY = 1,
> +
> +	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
> +	/* V2-only */
> +	OSD_CDB_FLUSH_ALL_RANGE = 2,
> +};
> +
> +/* osd2r03: 5.2.10 Timestamps control */
> +enum {
> +	OSD_CDB_NORMAL_TIMESTAMPS = 0,
> +	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
> +};
> +
> +/* (osd-r10: 5.2.2.1)
> + * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
> + *	2 bits at second nibble of command_specific_options byte
> + */
> +enum osd_attributes_mode {
> +	/* V2-only */
> +	OSD_CDB_SET_ONE_ATTR = 0x10,
> +
> +	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
> +	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
> +
> +	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
> +};
> +
> +/* (osd-r10: 4.12.5)
> + * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
> + *	byte offset = mantissa * (2^(exponent+8))
> + *	struct {
> + *		unsigned mantissa: 28;
> + *		int exponent: 04;
> + *	}
> + */
> +typedef __be32 __bitwise osd_cdb_offset;
> +
> +enum {
> +	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
> +	OSD_OFFSET_MAX_BITS = 28,
> +
> +	OSDv1_OFFSET_MIN_SHIFT = 8,
> +	OSD_OFFSET_MAX_SHIFT = 16,
> +};
> +
> +/* Return the smallest allowed encoded offset that contains @offset.
> + *
> + * The actual encoded offset returned is @offset + *padding.
> + * (up to max_shift, non-inclusive)
> + */
> +osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
> +	int min_shift, int max_shift);
> +
> +/* Minimum alignment is 256 bytes
> + * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
> + * which is 8 to 23 but IBM code restricts it to 16, so be it.
> + */
> +static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
> +{
> +	return __osd_encode_offset(offset, padding,
> +				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
> +}
> +
> +/* osd2r03: 5.2.1 Overview */
> +struct osd_cdb_head {
> +	struct scsi_varlen_cdb_hdr varlen_cdb;
> +/*10*/	u8		options;
> +	u8		command_specific_options;
> +	u8		timestamp_control;
> +/*13*/	u8		reserved1[3];
> +/*16*/	__be64		partition;
> +/*24*/	__be64		object;
> +/*32*/	union { /* V1 vs V2 alignment differences */
> +		struct __osdv1_cdb_addr_len {
> +/*32*/			__be32 		list_identifier;/* Rarely used */
> +/*36*/			__be64		length;
> +/*44*/			__be64		start_address;
> +		} __packed v1;
> +	};
> +/*52*/	union { /* selected attributes mode Page/List/Single */
> +		struct osd_attributes_page_mode {
> +/*52*/			__be32		get_attr_page;
> +/*56*/			__be32		get_attr_alloc_length;
> +/*60*/			osd_cdb_offset	get_attr_offset;
> +
> +/*64*/			__be32		set_attr_page;
> +/*68*/			__be32		set_attr_id;
> +/*72*/			__be32		set_attr_length;
> +/*76*/			osd_cdb_offset	set_attr_offset;
> +		} __packed attrs_page;
> +
> +		struct osd_attributes_list_mode {
> +/*52*/			__be32		get_attr_desc_bytes;
> +/*56*/			osd_cdb_offset	get_attr_desc_offset;
> +
> +/*60*/			__be32		get_attr_alloc_length;
> +/*64*/			osd_cdb_offset	get_attr_offset;
> +
> +/*68*/			__be32		set_attr_bytes;
> +/*72*/			osd_cdb_offset	set_attr_offset;
> +			__be32 not_used;
> +		} __packed attrs_list;
> +
> +		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
> +		struct osd_attributes_cdb_mode {
> +/*52*/			__be32		set_attr_page;
> +/*56*/			__be32		set_attr_id;
> +/*60*/			__be16		set_attr_len;
> +/*62*/			u8		set_attr_val[80-62];
> +		} __packed attrs_cdb;
> +/*52*/		u8 get_set_attributes_parameters[80-52];
> +	};
> +} __packed;
> +/*80*/
> +
> +/*160 v1*/
> +struct osd_security_parameters {
> +/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
> +/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
> +/*192*/osd_cdb_offset	data_in_integrity_check_offset;
> +/*196*/osd_cdb_offset	data_out_integrity_check_offset;
> +} __packed;
> +/*200 v1*/
> +
> +struct osdv1_cdb {
> +	struct osd_cdb_head h;
> +	u8 caps[OSDv1_CAP_LEN];
> +	struct osd_security_parameters sec_params;
> +} __packed;
> +
> +struct osd_cdb {
> +	union {
> +		struct osdv1_cdb v1;
> +		u8 buff[OSD_TOTAL_CDB_LEN];
> +	};
> +} __packed;
> +
> +static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
> +{
> +	return (struct osd_cdb_head *)ocdb->buff;
> +}
> +
> +/* define both version actions
> + * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
> + */
> +#define OSD_ACT___(Name, Num) \
> +	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
> +	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
> +
> +/* V2 only actions */
> +#define OSD_ACT_V2(Name, Num) \
> +	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
> +
> +#define OSD_ACT_V1_V2(Name, Num1, Num2) \
> +	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
> +	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
> +
> +enum osd_service_actions {
> +	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
> +	OSD_ACT___(FORMAT_OSD,			0x01)
> +	OSD_ACT___(CREATE,			0x02)
> +	OSD_ACT___(LIST,			0x03)
> +	OSD_ACT_V2(PUNCH,			0x04)
> +	OSD_ACT___(READ,			0x05)
> +	OSD_ACT___(WRITE,			0x06)
> +	OSD_ACT___(APPEND,			0x07)
> +	OSD_ACT___(FLUSH,			0x08)
> +	OSD_ACT_V2(CLEAR,			0x09)
> +	OSD_ACT___(REMOVE,			0x0A)
> +	OSD_ACT___(CREATE_PARTITION,		0x0B)
> +	OSD_ACT___(REMOVE_PARTITION,		0x0C)
> +	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
> +	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
> +	OSD_ACT___(CREATE_AND_WRITE,		0x12)
> +	OSD_ACT___(CREATE_COLLECTION,		0x15)
> +	OSD_ACT___(REMOVE_COLLECTION,		0x16)
> +	OSD_ACT___(LIST_COLLECTION,		0x17)
> +	OSD_ACT___(SET_KEY,			0x18)
> +	OSD_ACT___(SET_MASTER_KEY,		0x19)
> +	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
> +	OSD_ACT___(FLUSH_PARTITION,		0x1B)
> +	OSD_ACT___(FLUSH_OSD,			0x1C)
> +
> +	OSD_ACT_V2(QUERY,			0x20)
> +	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
> +	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
> +	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
> +	OSD_ACT_V2(READ_MAP,			0x31)
> +
> +	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
> +	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
> +	/* 0x8F80 to 0x8FFF are Vendor specific */
> +};
> +
> +/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
> +struct osd_attributes_list_attrid {
> +	__be32 page;
> +	__be32 attr_id;
> +} __packed;
> +
> +/*
> + * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
> + *                  for setting attributes
> + */
> +struct osd_attributes_list_element {
> +	__be32 page;
> +	__be32 attr_id;
> +	__be16 attr_bytes;
> +	u8 attr_val[0];
> +} __packed;
> +
> +enum {
> +	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
> +};
> +
> +enum {
> +	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
> +	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
> +};
> +
> +static inline unsigned osdv1_attr_list_elem_size(unsigned len)
> +{
> +	return ALIGN(len + sizeof(struct osd_attributes_list_element),
> +		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
> +}
> +
> +/*
> + * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
> + */
> +enum osd_attr_list_types {
> +	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
> +	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
> +	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
> +	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
> +};
> +
> +/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
> +struct osd_attributes_list_multi_header {
> +	__be64 object_id;
> +	u8 object_type; /* object_type enum below */
> +	u8 reserved[5];
> +	__be16 list_bytes;
> +	/* followed by struct osd_attributes_list_element's */
> +};
> +
> +struct osdv1_attributes_list_header {
> +	u8 type;	/* low 4-bit only */
> +	u8 pad;
> +	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
> +	/*
> +	 * type=9 followed by struct osd_attributes_list_element's
> +	 * type=E followed by struct osd_attributes_list_multi_header's
> +	 */
> +} __packed;
> +
> +static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
> +{
> +	return be16_to_cpu(h->list_bytes);
> +}
> +
> +/* (osd-r10 6.13)
> + * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
> + *	for root_lstchg below
> + */
> +enum {
> +	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
> +	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
> +};
> +
> +/*
> + * osd2r03: 6.15.2 LIST command parameter data
> + * (Also for LIST COLLECTION)
> + */
> +struct osd_obj_id_list {
> +	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
> +	__be64 continuation_id;
> +	__be32 list_identifier;
> +	u8 pad[3];
> +	u8 root_lstchg;
> +	__be64 object_ids[0];
> +} __packed;
> +
> +static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
> +	bool *is_changed)
> +{
> +	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
> +	return 0 != list->continuation_id;
> +}
> +
> +/*
> + * osd2r03: 4.12.4.5 The ALLDATA security method
> + */
> +struct osd_data_out_integrity_info {
> +	__be64 data_bytes;
> +	__be64 set_attributes_bytes;
> +	__be64 get_attributes_bytes;
> +	__be64 integrity_check_value;
> +} __packed;
> +
> +struct osd_data_in_integrity_info {
> +	__be64 data_bytes;
> +	__be64 retrieved_attributes_bytes;
> +	__be64 integrity_check_value;
> +} __packed;
> +
> +struct osd_timestamp {
> +	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
> +} __packed;
> +/* FIXME: define helper functions to convert to/from osd time format */
> +
> +/*
> + * Capability & Security definitions
> + * osd2r03: 4.11.2.2 Capability format
> + * osd2r03: 5.2.8 Security parameters
> + */
> +
> +struct osd_key_identifier {
> +	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
> +} __packed;
> +
> +/* for osd_capability.format */
> +enum {
> +	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
> +	OSD_SEC_CAP_FORMAT_VER1 = 1,
> +	OSD_SEC_CAP_FORMAT_VER2 = 2,
> +};
> +
> +/* security_method */
> +enum {
> +	OSD_SEC_NOSEC = 0,
> +	OSD_SEC_CAPKEY = 1,
> +	OSD_SEC_CMDRSP = 2,
> +	OSD_SEC_ALLDATA = 3,
> +};
> +
> +enum object_type {
> +	OSD_SEC_OBJ_ROOT = 0x1,
> +	OSD_SEC_OBJ_PARTITION = 0x2,
> +	OSD_SEC_OBJ_COLLECTION = 0x40,
> +	OSD_SEC_OBJ_USER = 0x80,
> +};
> +
> +enum osd_capability_bit_masks {
> +	OSD_SEC_CAP_APPEND	= (1 << 0),
> +	OSD_SEC_CAP_OBJ_MGMT	= (1 << 1),
> +	OSD_SEC_CAP_REMOVE	= (1 << 2),
> +	OSD_SEC_CAP_CREATE	= (1 << 3),
> +	OSD_SEC_CAP_SET_ATTR	= (1 << 4),
> +	OSD_SEC_CAP_GET_ATTR	= (1 << 5),
> +	OSD_SEC_CAP_WRITE	= (1 << 6),
> +	OSD_SEC_CAP_READ	= (1 << 7),
> +
> +	OSD_SEC_CAP_NONE1	= (1 << 8),
> +	OSD_SEC_CAP_NONE2	= (1 << 9),
> +	OSD_SEC_CAP_NONE3	= (1 << 10),
> +	OSD_SEC_CAP_QUERY	= (1 << 11), /*v2 only*/
> +	OSD_SEC_CAP_M_OBJECT	= (1 << 12), /*v2 only*/
> +	OSD_SEC_CAP_POL_SEC	= (1 << 13),
> +	OSD_SEC_CAP_GLOBAL	= (1 << 14),
> +	OSD_SEC_CAP_DEV_MGMT	= (1 << 15),

These could use BIT(nr) from bitops.h.

> +};
> +
> +/* for object_descriptor_type (hi nibble used) */
> +enum {
> +	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
> +	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
> +	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
> +	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
> +};
> +
> +/* (osd-r10:4.9.2.2)
> + * osd2r03:4.11.2.2 Capability format
> + */
> +struct osd_capability_head {
> +	u8 format; /* low nibble */
> +	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
> +	u8 security_method;
> +	u8 reserved1;
> +/*04*/	struct osd_timestamp expiration_time;
> +/*10*/	u8 audit[30-10];
> +/*30*/	u8 discriminator[42-30];
> +/*42*/	struct osd_timestamp object_created_time;
> +/*48*/	u8 object_type;
> +	u8 permissions_bit_mask[54-49];

The offset comments are OK with me, but please lose the [b-a] length specifiers.


> +/*54*/	u8 reserved2;
> +/*55*/	u8 object_descriptor_type; /* high nibble */
> +} __packed;
> +
> +/*56 v1*/
> +struct osdv1_cap_object_descriptor {
> +	union {
> +		struct {
> +/*56*/			__be32 policy_access_tag;
> +/*60*/			__be64 allowed_partition_id;
> +/*68*/			__be64 allowed_object_id;
> +/*76*/			__be32 reserved;
> +		} __packed obj_desc;
> +
> +		u8 object_descriptor[80-56];/*24*/
> +	};
> +} __packed;
> +/*80 v1*/
> +
> +struct osd_capability {
> +	struct osd_capability_head h;
> +	struct osdv1_cap_object_descriptor od;
> +} __packed;
> +
> +/**
> + * osd_sec_set_caps - set cap-bits into the capabilities header
> + *
> + * @cap:	The osd_capability_head to set cap bits to.
> + * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
> + *
> + * permissions_bit_mask is unaligned use below to set into caps
> + * in a version independent way
> + */
> +static inline void osd_sec_set_caps(struct osd_capability_head *cap,
> +	u16 bit_mask)
> +{
> +	/*
> +	 *Note: The bits above are defined LE order this is because this way
> +	 *      they can grow in the future to more then 16, and still retain
> +	 *      there constant values.
> +	 */
> +	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
> +}
> +
> +#endif /* ndef __OSD_PROTOCOL_H__ */

---
~Randy

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver2] libosd: OSDv1 Headers
  2008-11-10 17:29       ` Randy Dunlap
@ 2008-11-12 13:10           ` Boaz Harrosh
  2008-11-12 13:13           ` Boaz Harrosh
  1 sibling, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-12 13:10 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: James Bottomley, Andrew Morton, Jörn Engel,
	open-osd development, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, linux-scsi, Sami.Iren, linux-kernel

Randy Dunlap wrote:
> On Sun, 09 Nov 2008 16:52:36 +0200 Boaz Harrosh wrote:
> 
>> Headers only patch.
>>
>> osd_protocol.h
>> 	Contains a C-fied definition of the T10 OSD standard
>> osd_types.h
>> 	Contains CPU order common used types
>> osd_initiator.h
>> 	API definition of the osd_initiator library
>> osd_sec.h
>> 	Contains High level API for the security manager.
>>
>> [Note that checkpatch spews errors on things that are valid in this context
>> and will not be fixed]
>>
>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>> Reviewed-by: Benny Halevy <bhalevy@panasas.com>

Thank you Randy for your review, I will post a fixed
patch shortly. I have changed according to your comments
except in one place, see arguments below.

>> ---
>>  include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
>>  include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
>>  include/scsi/osd_sec.h       |   45 ++++
>>  include/scsi/osd_types.h     |   40 ++++
>>  4 files changed, 914 insertions(+), 0 deletions(-)
>>  create mode 100644 include/scsi/osd_initiator.h
>>  create mode 100644 include/scsi/osd_protocol.h
>>  create mode 100644 include/scsi/osd_sec.h
>>  create mode 100644 include/scsi/osd_types.h
>>
>> diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
>> new file mode 100644
>> index 0000000..9bab95d
>> --- /dev/null
>> +++ b/include/scsi/osd_initiator.h
>> @@ -0,0 +1,332 @@
>> +/*
>> + * osd_initiator.h - OSD initiator API definition
>> + *
>> + * Copyright (C) 2008 Panasas Inc.  All rights reserved.
>> + *
>> + * Authors:
>> + *   Boaz Harrosh <bharrosh@panasas.com>
>> + *   Benny Halevy <bhalevy@panasas.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2
>> + *
>> + */
>> +#ifndef __OSD_INITIATOR_H__
>> +#define __OSD_INITIATOR_H__
>> +
>> +#include "osd_protocol.h"
>> +#include "osd_types.h"
>> +
>> +#include <linux/blkdev.h>
>> +
>> +/* Note: "NI" in comments below means "Not Implemented yet" */
>> +
>> +/*
>> + * Object-based Storage Device.
>> + * This object represents an OSD device.
>> + * It is not a full linux device in any way. It is only
>> + * a place to hang resources associated with a Linux
>> + * request Q and some default properties.
>> + */
>> +struct osd_dev {
>> +	struct scsi_device *scsi_device;
>> +	unsigned def_timeout;
>> +};
>> +
>> +void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
> 
> Don't mix having parameter names and not having them.
> Preferred is having them.
> 

I don't know what got into me. I thought it would be more readable this
way. But you are right consistency is very important.

>> +void osd_dev_fini(struct osd_dev *);
>> +
>> +struct osd_request;
>> +typedef void (osd_req_done_fn)(struct osd_request *, void *);
>> +
>> +struct osd_request {
>> +	struct osd_cdb cdb;
>> +	struct osd_data_out_integrity_info out_data_integ;
>> +	struct osd_data_in_integrity_info in_data_integ;
>> +
>> +	struct osd_dev *osd_dev;
>> +	struct request *request;
>> +
>> +	struct _osd_req_data_segment {
>> +		void *buff;
>> +		unsigned alloc_size; /* 0 here means not allocated by us */
> 
> Could/would some other code allocate it, or is the "by us" just redundant?
> 

I've changed the comment as it was not clear it is now:
+		unsigned alloc_size; /* 0 here means: don't call kfree */

>> +		unsigned total_bytes;
>> +	} set_attr, enc_get_attr, get_attr;
>> +
>> +	struct _osd_io_info {
>> +		struct bio *bio;
>> +		u64 total_bytes;
>> +		struct request *req;
>> +		struct _osd_req_data_segment *last_seg;
>> +		u8 *pad_buff;
>> +	} out, in;
>> +
>> +	gfp_t alloc_flags;
>> +	unsigned timeout;
>> +	unsigned retries;
>> +	u8 sense[OSD_MAX_SENSE_LEN];
>> +	enum osd_attributes_mode attributes_mode;
>> +
>> +	osd_req_done_fn *async_done;
>> +	void *async_private;
>> +	int async_error;
>> +};
>> +
>> +/**
> 
> Don't start comment blocks with /** when they are not kernel-doc,
> like this one is not.
> 

OK, I must confess my kernel-doc total ignorance. I was imagining that
each source file's kernel-doc comments are collected into an html file.
I thought that this comment will be like an introduction to the following
function-by-function reference. Anyway it's fixed

>> + * How to use the osd library:
>> + *
>> + * osd_start_request
>> + *	Allocates a request.
>> + *
>> + * osd_req_*
>> + *	Call one of, to encode the desired operation.
>> + *
>> + * osd_add_{get,set}_attr
>> + *	Optionally add attributes to the CDB, list or page mode.
>> + *
>> + * osd_finalize_request
>> + *	Computes final data out/in offsets and signs the request,
>> + *	making it ready for execution.
>> + *
>> + * osd_execute_request
>> + *	May be called to execute it through the block layer. Other wise submit
>> + *	the associated block request in some other way.
>> + *
>> + * After execution:
>> + * osd_req_decode_sense
>> + *	Decodes sense information to verify execution results.
>> + *
>> + * osd_req_decode_get_attr
>> + *	Retrieve osd_add_get_attr_list() values if used.
>> + *
>> + * osd_end_request
>> + *	Must be called to deallocate the request.
>> + */
>> +
>> +/**
>> + * osd_start_request - Allocate and initialize an osd_request
>> + *
>> + * @osd_dev:    OSD device that holds the scsi-device and default values
>> + *              that the request is associated with.
>> + * @gfp:        The allocation flags to use for request allocation, and all
>> + *              subsequent allocations. This will be stored at
>> + *              osd_request->alloc_flags, can be changed by user later
>> + *
>> + * Allocate osd_request and initialize all members to the
>> + * default/initial state.
>> + */
>> +struct osd_request *osd_start_request(struct osd_dev *, gfp_t gfp);
>> +
>> +enum osd_req_options {
>> +	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
>> +	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
>> +
>> +	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
>> +};
>> +
>> +/**
>> + * osd_finalize_request - Sign request and prepare request for execution
>> + *
>> + * @or:		osd_request to prepare
>> + * @options:	combination of osd_req_options bit flags or 0.
>> + * @cap	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
>> + *              The security manager as capabilities for this cdb.
>> + * @cap_key	The cryptographic key used to sign the cdb/data. Can be null
>> + *              if NOSEC is used.
> 
> Last 2 parameters need a ':' after the @param_name, like the first 2 have.
> 
oops

>> + *
>> + * The actual request and bios are only allocated here, so are the get_attr
>> + * buffers that will receive the returned attributes. Copy's @cap to cdb.
>> + * Sign the cdb/data with @cap_key.
>> + */
>> +int osd_finalize_request(struct osd_request *or,
>> +	u8 options, const void *cap, const u8 *cap_key);
>> +
>> +/**
>> + * osd_execute_request - Execute the request synchronously through
>> + *                       the block-layer
> 
> Function name and short description need to be on one line.
> 

OK I re-worded so it will fit in one line. What happens if it does not
fit, both name and description, in 80 characters? is there a continuation
symbol or something?

>> + * @or:		osd_request to Executed
>> + *
>> + * Calls blk_execute_rq to q the command and waits for completion.
>> + */
>> +int osd_execute_request(struct osd_request *or);
>> +
>> +/**
>> + * osd_execute_request_async - submits the request for execution through
>> + *                             the block-layer without waitting.
> 
> Ditto.
> 
>> + * @or:                      - osd_request to Executed
>> + * @done: (Optional)         - Called at end of execution
>> + * @private:                 - Will be passes to @done function
> 
> s/passes/passed/
> 
Thanks

>> + *
>> + * Calls blk_execute_rq_nowait to q the command. When execution is done
>> + * Optionally calles @done with @private as parameter. or->async_error has the
> 
> s/calles/calls/
> 
>> + * Return code
> 
> and don't start each line with a Capital letter since they are not the
> beginning of sentences.  What's with that period ('.') before "or->async_error"
> (which needs a space after "or").
> 

I reworded these so they are more clear, I hope.

> 
>> + */
>> +int osd_execute_request_async(struct osd_request *or,
>> +	osd_req_done_fn *done, void *private);
>> +
>> +/**
>> + * osd_end_request - return osd_request to free store
>> + *
>> + * @or:		osd_request to free
>> + *
>> + * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
>> + */
>> +void osd_end_request(struct osd_request *or);
>> +
>> +/*
>> + * CDB Encoding
>> + *
>> + * Note: call only one of the following methods.
>> + */
>> +
>> +/*
>> + * Device commands
>> + */
>> +void osd_req_set_master_seed_xchg(struct osd_request *, ...);/* NI */
>> +void osd_req_set_master_key(struct osd_request *, ...);/* NI */
>> +
>> +void osd_req_format(struct osd_request *, u64 tot_capacity);
>> +
>> +/* list all partitions
>> + * @list header must be initialized to zero on first run.
>> + *
>> + * Call osd_is_obj_list_done() to find if we got the complete list.
>> + */
>> +int osd_req_list_dev_partitions(struct osd_request *,
>> +	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
>> +
>> +void osd_req_flush_obsd(struct osd_request *,
>> +	enum osd_options_flush_scope_values);
>> +
>> +void osd_req_perform_scsi_command(struct osd_request *,
>> +	const u8 *cdb, ...);/* NI */
>> +void osd_req_task_management(struct osd_request *, ...);/* NI */
>> +
>> +/*
>> + * Partition commands
>> + */
>> +void osd_req_create_partition(struct osd_request *, osd_id partition);
>> +void osd_req_remove_partition(struct osd_request *, osd_id partition);
>> +
>> +void osd_req_set_partition_key(struct osd_request *,
>> +	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
>> +	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
>> +
>> +/* list all collections in the partition
>> + * @list header must be init to zero on first run.
>> + *
>> + * Call osd_is_obj_list_done() to find if we got the complete list.
>> + */
>> +int osd_req_list_partition_collections(struct osd_request *,
>> +	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
>> +	unsigned nelem);
>> +
>> +/* list all objects in the partition
>> + * @list header must be init to zero on first run.
>> + *
>> + * Call osd_is_obj_list_done() to find if we got the complete list.
>> + */
>> +int osd_req_list_partition_objects(struct osd_request *,
>> +	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
>> +	unsigned nelem);
>> +
>> +void osd_req_flush_partition(struct osd_request *,
>> +	osd_id partition, enum osd_options_flush_scope_values);
>> +
>> +/*
>> + * Collection commands
>> + */
>> +void osd_req_create_collection(struct osd_request *,
>> +	const struct osd_obj_id *);/* NI */
>> +void osd_req_remove_collection(struct osd_request *,
>> +	const struct osd_obj_id *);/* NI */
>> +
>> +/* list all objects in the collection */
>> +int osd_req_list_collection_objects(struct osd_request *,
>> +	const struct osd_obj_id *, osd_id initial_id,
>> +	struct osd_obj_id_list *list, unsigned nelem);
>> +
>> +/* V2 only filtered list of objects in the collection */
>> +void osd_req_query(struct osd_request *, ...);/* NI */
>> +
>> +void osd_req_flush_collection(struct osd_request *,
>> +	const struct osd_obj_id *, enum osd_options_flush_scope_values);
>> +
>> +void osd_req_get_member_attrs(struct osd_request *, ...);/* V2-only NI */
>> +void osd_req_set_member_attrs(struct osd_request *, ...);/* V2-only NI */
>> +
>> +/*
>> + * Object commands
>> + */
>> +void osd_req_create_object(struct osd_request *, struct osd_obj_id *);
>> +void osd_req_remove_object(struct osd_request *, struct osd_obj_id *);
>> +
>> +void osd_req_write(struct osd_request *,
>> +	const struct osd_obj_id *, struct bio *data_out, u64 offset);
>> +void osd_req_append(struct osd_request *,
>> +	const struct osd_obj_id *, struct bio *data_out);/* NI */
>> +void osd_req_create_write(struct osd_request *,
>> +	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
>> +void osd_req_clear(struct osd_request *,
>> +	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
>> +void osd_req_punch(struct osd_request *,
>> +	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
>> +
>> +void osd_req_flush_object(struct osd_request *,
>> +	const struct osd_obj_id *, enum osd_options_flush_scope_values,
>> +	/*V2*/ u64 offset, /*V2*/ u64 len);
>> +
>> +void osd_req_read(struct osd_request *,
>> +	const struct osd_obj_id *, struct bio *data_in, u64 offset);
>> +
>> +/*
>> + * Root/Partition/Collection/Object Attributes commands
>> + */
>> +
>> +/* get before set */
>> +void osd_req_get_attributes(struct osd_request *, const struct osd_obj_id *);
>> +
>> +/* set before get */
>> +void osd_req_set_attributes(struct osd_request *, const struct osd_obj_id *);
>> +
>> +/*
>> + * Attributes appended to most commands
>> + */
>> +
>> +/* Attributes List mode (or V2 CDB) */
>> +  /*
>> +   * TODO: In ver2 if at finalize time only one attr was set and no gets,
>> +   * then the Attributes CDB mode is used automatically to save IO.
>> +   */
>> +
>> +/* set a list of attributes. */
>> +int osd_req_add_set_attr_list(struct osd_request *,
>> +	const struct osd_attr *, unsigned nelem);
>> +
>> +/* get a list of attributes */
>> +int osd_req_add_get_attr_list(struct osd_request *,
>> +	const struct osd_attr *, unsigned nelem);
>> +
>> +/*
>> + * Attributes list decoding
>> + * Must be called after osd_request.request was executed
>> + * It is called in a loop to decode the returned get_attr
>> + * (see osd_add_get_attr)
>> + */
>> +int osd_req_decode_get_attr_list(struct osd_request *,
>> +	struct osd_attr *, int *nelem, void **iterator);
>> +
>> +/* Attributes Page mode */
>> +
>> +/*
>> + * Read an attribute page and optionally set one attribute
>> + *
>> + * Retrieves the attribute page directly to a user buffer.
>> + * @attr_page_data shall stay valid until end of execution.
>> + * See osd_attributes.h for common page structures
>> + */
>> +int osd_req_add_get_attr_page(struct osd_request *,
>> +	u32 page_id, void *attr_page_data, unsigned max_page_len,
>> +	const struct osd_attr *set_one);
>> +
>> +#endif /* __OSD_LIB_H__ */
>> diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
>> new file mode 100644
>> index 0000000..77a74a3
>> --- /dev/null
>> +++ b/include/scsi/osd_protocol.h
>> @@ -0,0 +1,497 @@
>> +/*
>> + * osd_protocol.h - OSD T10 standard C definitions.
>> + *
>> + * Copyright (C) 2008 Panasas Inc.  All rights reserved.
>> + *
>> + * Authors:
>> + *   Boaz Harrosh <bharrosh@panasas.com>
>> + *   Benny Halevy <bhalevy@panasas.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2
>> + *
>> + * This file contains types and constants that are defined by the protocol
>> + * Note: All names and symbols are taken from the OSD standard's text.
>> + */
>> +#ifndef __OSD_PROTOCOL_H__
>> +#define __OSD_PROTOCOL_H__
>> +
>> +#include <linux/types.h>
>> +#include <asm/unaligned.h>
>> +#include <scsi/scsi.h>
>> +
>> +enum {
>> +	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
>> +	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
>> +	OSDv1_CAP_LEN = 80,
>> +	/* Latest supported version */
>> +	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
>> +	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
>> +	OSD_CAP_LEN = OSDv1_CAP_LEN,
>> +
>> +	OSD_SYSTEMID_LEN = 20,
>> +	OSD_CRYPTO_KEYID_SIZE = 20,
>> +	OSD_CRYPTO_SEED_SIZE = 4,
>> +	OSD_CRYPTO_NONCE_SIZE = 12,
>> +	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
>> +
>> +	OSD_PARTITION_FIRST_ID = 0x10000,
>> +	OSD_OBJECT_FIRST_ID = 0x10000,
>> +};
>> +
>> +/* (osd-r10 5.2.4)
>> + * osd2r03: 5.2.3 Caching control bits
>> + */
>> +enum osd_options_byte {
>> +	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
>> +	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
>> +};
>> +
>> +/*
>> + * osd2r03: 5.2.5 Isolation.
>> + * First 3 bits, V2-only.
>> + * Also for attr 110h "default isolation method" at Root Information page
>> + */
>> +enum osd_options_byte_isolation {
>> +	OSD_ISOLATION_DEFAULT = 0,
>> +	OSD_ISOLATION_NONE = 1,
>> +	OSD_ISOLATION_STRICT = 2,
>> +	OSD_ISOLATION_RANGE = 4,
>> +	OSD_ISOLATION_FUNCTIONAL = 5,
>> +	OSD_ISOLATION_VENDOR = 7,
>> +};
>> +
>> +/* (osd-r10: 6.7)
>> + * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
>> + */
>> +enum osd_options_flush_scope_values {
>> +	OSD_CDB_FLUSH_ALL = 0,
>> +	OSD_CDB_FLUSH_ATTR_ONLY = 1,
>> +
>> +	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
>> +	/* V2-only */
>> +	OSD_CDB_FLUSH_ALL_RANGE = 2,
>> +};
>> +
>> +/* osd2r03: 5.2.10 Timestamps control */
>> +enum {
>> +	OSD_CDB_NORMAL_TIMESTAMPS = 0,
>> +	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
>> +};
>> +
>> +/* (osd-r10: 5.2.2.1)
>> + * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
>> + *	2 bits at second nibble of command_specific_options byte
>> + */
>> +enum osd_attributes_mode {
>> +	/* V2-only */
>> +	OSD_CDB_SET_ONE_ATTR = 0x10,
>> +
>> +	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
>> +	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
>> +
>> +	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
>> +};
>> +
>> +/* (osd-r10: 4.12.5)
>> + * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
>> + *	byte offset = mantissa * (2^(exponent+8))
>> + *	struct {
>> + *		unsigned mantissa: 28;
>> + *		int exponent: 04;
>> + *	}
>> + */
>> +typedef __be32 __bitwise osd_cdb_offset;
>> +
>> +enum {
>> +	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
>> +	OSD_OFFSET_MAX_BITS = 28,
>> +
>> +	OSDv1_OFFSET_MIN_SHIFT = 8,
>> +	OSD_OFFSET_MAX_SHIFT = 16,
>> +};
>> +
>> +/* Return the smallest allowed encoded offset that contains @offset.
>> + *
>> + * The actual encoded offset returned is @offset + *padding.
>> + * (up to max_shift, non-inclusive)
>> + */
>> +osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
>> +	int min_shift, int max_shift);
>> +
>> +/* Minimum alignment is 256 bytes
>> + * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
>> + * which is 8 to 23 but IBM code restricts it to 16, so be it.
>> + */
>> +static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
>> +{
>> +	return __osd_encode_offset(offset, padding,
>> +				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
>> +}
>> +
>> +/* osd2r03: 5.2.1 Overview */
>> +struct osd_cdb_head {
>> +	struct scsi_varlen_cdb_hdr varlen_cdb;
>> +/*10*/	u8		options;
>> +	u8		command_specific_options;
>> +	u8		timestamp_control;
>> +/*13*/	u8		reserved1[3];
>> +/*16*/	__be64		partition;
>> +/*24*/	__be64		object;
>> +/*32*/	union { /* V1 vs V2 alignment differences */
>> +		struct __osdv1_cdb_addr_len {
>> +/*32*/			__be32 		list_identifier;/* Rarely used */
>> +/*36*/			__be64		length;
>> +/*44*/			__be64		start_address;
>> +		} __packed v1;
>> +	};
>> +/*52*/	union { /* selected attributes mode Page/List/Single */
>> +		struct osd_attributes_page_mode {
>> +/*52*/			__be32		get_attr_page;
>> +/*56*/			__be32		get_attr_alloc_length;
>> +/*60*/			osd_cdb_offset	get_attr_offset;
>> +
>> +/*64*/			__be32		set_attr_page;
>> +/*68*/			__be32		set_attr_id;
>> +/*72*/			__be32		set_attr_length;
>> +/*76*/			osd_cdb_offset	set_attr_offset;
>> +		} __packed attrs_page;
>> +
>> +		struct osd_attributes_list_mode {
>> +/*52*/			__be32		get_attr_desc_bytes;
>> +/*56*/			osd_cdb_offset	get_attr_desc_offset;
>> +
>> +/*60*/			__be32		get_attr_alloc_length;
>> +/*64*/			osd_cdb_offset	get_attr_offset;
>> +
>> +/*68*/			__be32		set_attr_bytes;
>> +/*72*/			osd_cdb_offset	set_attr_offset;
>> +			__be32 not_used;
>> +		} __packed attrs_list;
>> +
>> +		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
>> +		struct osd_attributes_cdb_mode {
>> +/*52*/			__be32		set_attr_page;
>> +/*56*/			__be32		set_attr_id;
>> +/*60*/			__be16		set_attr_len;
>> +/*62*/			u8		set_attr_val[80-62];
>> +		} __packed attrs_cdb;
>> +/*52*/		u8 get_set_attributes_parameters[80-52];
>> +	};
>> +} __packed;
>> +/*80*/
>> +
>> +/*160 v1*/
>> +struct osd_security_parameters {
>> +/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
>> +/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
>> +/*192*/osd_cdb_offset	data_in_integrity_check_offset;
>> +/*196*/osd_cdb_offset	data_out_integrity_check_offset;
>> +} __packed;
>> +/*200 v1*/
>> +
>> +struct osdv1_cdb {
>> +	struct osd_cdb_head h;
>> +	u8 caps[OSDv1_CAP_LEN];
>> +	struct osd_security_parameters sec_params;
>> +} __packed;
>> +
>> +struct osd_cdb {
>> +	union {
>> +		struct osdv1_cdb v1;
>> +		u8 buff[OSD_TOTAL_CDB_LEN];
>> +	};
>> +} __packed;
>> +
>> +static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
>> +{
>> +	return (struct osd_cdb_head *)ocdb->buff;
>> +}
>> +
>> +/* define both version actions
>> + * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
>> + */
>> +#define OSD_ACT___(Name, Num) \
>> +	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
>> +	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
>> +
>> +/* V2 only actions */
>> +#define OSD_ACT_V2(Name, Num) \
>> +	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
>> +
>> +#define OSD_ACT_V1_V2(Name, Num1, Num2) \
>> +	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
>> +	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
>> +
>> +enum osd_service_actions {
>> +	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
>> +	OSD_ACT___(FORMAT_OSD,			0x01)
>> +	OSD_ACT___(CREATE,			0x02)
>> +	OSD_ACT___(LIST,			0x03)
>> +	OSD_ACT_V2(PUNCH,			0x04)
>> +	OSD_ACT___(READ,			0x05)
>> +	OSD_ACT___(WRITE,			0x06)
>> +	OSD_ACT___(APPEND,			0x07)
>> +	OSD_ACT___(FLUSH,			0x08)
>> +	OSD_ACT_V2(CLEAR,			0x09)
>> +	OSD_ACT___(REMOVE,			0x0A)
>> +	OSD_ACT___(CREATE_PARTITION,		0x0B)
>> +	OSD_ACT___(REMOVE_PARTITION,		0x0C)
>> +	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
>> +	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
>> +	OSD_ACT___(CREATE_AND_WRITE,		0x12)
>> +	OSD_ACT___(CREATE_COLLECTION,		0x15)
>> +	OSD_ACT___(REMOVE_COLLECTION,		0x16)
>> +	OSD_ACT___(LIST_COLLECTION,		0x17)
>> +	OSD_ACT___(SET_KEY,			0x18)
>> +	OSD_ACT___(SET_MASTER_KEY,		0x19)
>> +	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
>> +	OSD_ACT___(FLUSH_PARTITION,		0x1B)
>> +	OSD_ACT___(FLUSH_OSD,			0x1C)
>> +
>> +	OSD_ACT_V2(QUERY,			0x20)
>> +	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
>> +	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
>> +	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
>> +	OSD_ACT_V2(READ_MAP,			0x31)
>> +
>> +	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
>> +	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
>> +	/* 0x8F80 to 0x8FFF are Vendor specific */
>> +};
>> +
>> +/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
>> +struct osd_attributes_list_attrid {
>> +	__be32 page;
>> +	__be32 attr_id;
>> +} __packed;
>> +
>> +/*
>> + * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
>> + *                  for setting attributes
>> + */
>> +struct osd_attributes_list_element {
>> +	__be32 page;
>> +	__be32 attr_id;
>> +	__be16 attr_bytes;
>> +	u8 attr_val[0];
>> +} __packed;
>> +
>> +enum {
>> +	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
>> +};
>> +
>> +enum {
>> +	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
>> +	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
>> +};
>> +
>> +static inline unsigned osdv1_attr_list_elem_size(unsigned len)
>> +{
>> +	return ALIGN(len + sizeof(struct osd_attributes_list_element),
>> +		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
>> +}
>> +
>> +/*
>> + * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
>> + */
>> +enum osd_attr_list_types {
>> +	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
>> +	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
>> +	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
>> +	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
>> +};
>> +
>> +/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
>> +struct osd_attributes_list_multi_header {
>> +	__be64 object_id;
>> +	u8 object_type; /* object_type enum below */
>> +	u8 reserved[5];
>> +	__be16 list_bytes;
>> +	/* followed by struct osd_attributes_list_element's */
>> +};
>> +
>> +struct osdv1_attributes_list_header {
>> +	u8 type;	/* low 4-bit only */
>> +	u8 pad;
>> +	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
>> +	/*
>> +	 * type=9 followed by struct osd_attributes_list_element's
>> +	 * type=E followed by struct osd_attributes_list_multi_header's
>> +	 */
>> +} __packed;
>> +
>> +static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
>> +{
>> +	return be16_to_cpu(h->list_bytes);
>> +}
>> +
>> +/* (osd-r10 6.13)
>> + * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
>> + *	for root_lstchg below
>> + */
>> +enum {
>> +	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
>> +	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
>> +};
>> +
>> +/*
>> + * osd2r03: 6.15.2 LIST command parameter data
>> + * (Also for LIST COLLECTION)
>> + */
>> +struct osd_obj_id_list {
>> +	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
>> +	__be64 continuation_id;
>> +	__be32 list_identifier;
>> +	u8 pad[3];
>> +	u8 root_lstchg;
>> +	__be64 object_ids[0];
>> +} __packed;
>> +
>> +static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
>> +	bool *is_changed)
>> +{
>> +	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
>> +	return 0 != list->continuation_id;
>> +}
>> +
>> +/*
>> + * osd2r03: 4.12.4.5 The ALLDATA security method
>> + */
>> +struct osd_data_out_integrity_info {
>> +	__be64 data_bytes;
>> +	__be64 set_attributes_bytes;
>> +	__be64 get_attributes_bytes;
>> +	__be64 integrity_check_value;
>> +} __packed;
>> +
>> +struct osd_data_in_integrity_info {
>> +	__be64 data_bytes;
>> +	__be64 retrieved_attributes_bytes;
>> +	__be64 integrity_check_value;
>> +} __packed;
>> +
>> +struct osd_timestamp {
>> +	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
>> +} __packed;
>> +/* FIXME: define helper functions to convert to/from osd time format */
>> +
>> +/*
>> + * Capability & Security definitions
>> + * osd2r03: 4.11.2.2 Capability format
>> + * osd2r03: 5.2.8 Security parameters
>> + */
>> +
>> +struct osd_key_identifier {
>> +	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
>> +} __packed;
>> +
>> +/* for osd_capability.format */
>> +enum {
>> +	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
>> +	OSD_SEC_CAP_FORMAT_VER1 = 1,
>> +	OSD_SEC_CAP_FORMAT_VER2 = 2,
>> +};
>> +
>> +/* security_method */
>> +enum {
>> +	OSD_SEC_NOSEC = 0,
>> +	OSD_SEC_CAPKEY = 1,
>> +	OSD_SEC_CMDRSP = 2,
>> +	OSD_SEC_ALLDATA = 3,
>> +};
>> +
>> +enum object_type {
>> +	OSD_SEC_OBJ_ROOT = 0x1,
>> +	OSD_SEC_OBJ_PARTITION = 0x2,
>> +	OSD_SEC_OBJ_COLLECTION = 0x40,
>> +	OSD_SEC_OBJ_USER = 0x80,
>> +};
>> +
>> +enum osd_capability_bit_masks {
>> +	OSD_SEC_CAP_APPEND	= (1 << 0),
>> +	OSD_SEC_CAP_OBJ_MGMT	= (1 << 1),
>> +	OSD_SEC_CAP_REMOVE	= (1 << 2),
>> +	OSD_SEC_CAP_CREATE	= (1 << 3),
>> +	OSD_SEC_CAP_SET_ATTR	= (1 << 4),
>> +	OSD_SEC_CAP_GET_ATTR	= (1 << 5),
>> +	OSD_SEC_CAP_WRITE	= (1 << 6),
>> +	OSD_SEC_CAP_READ	= (1 << 7),
>> +
>> +	OSD_SEC_CAP_NONE1	= (1 << 8),
>> +	OSD_SEC_CAP_NONE2	= (1 << 9),
>> +	OSD_SEC_CAP_NONE3	= (1 << 10),
>> +	OSD_SEC_CAP_QUERY	= (1 << 11), /*v2 only*/
>> +	OSD_SEC_CAP_M_OBJECT	= (1 << 12), /*v2 only*/
>> +	OSD_SEC_CAP_POL_SEC	= (1 << 13),
>> +	OSD_SEC_CAP_GLOBAL	= (1 << 14),
>> +	OSD_SEC_CAP_DEV_MGMT	= (1 << 15),
> 
> These could use BIT(nr) from bitops.h.
> 
Thanks. It looks much better with this macro.

>> +};
>> +
>> +/* for object_descriptor_type (hi nibble used) */
>> +enum {
>> +	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
>> +	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
>> +	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
>> +	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
>> +};
>> +
>> +/* (osd-r10:4.9.2.2)
>> + * osd2r03:4.11.2.2 Capability format
>> + */
>> +struct osd_capability_head {
>> +	u8 format; /* low nibble */
>> +	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
>> +	u8 security_method;
>> +	u8 reserved1;
>> +/*04*/	struct osd_timestamp expiration_time;
>> +/*10*/	u8 audit[30-10];
>> +/*30*/	u8 discriminator[42-30];
>> +/*42*/	struct osd_timestamp object_created_time;
>> +/*48*/	u8 object_type;
>> +	u8 permissions_bit_mask[54-49];
> 
> The offset comments are OK with me, but please lose the [b-a] length specifiers.
> 

I would, please, like to keep them. For the user it does not matter.
Because he is not suppose to care if he is doing:
-	memset(och->permissions_bit_mask, 0, 5); // BAD
+	memset(och->permissions_bit_mask, 0, sizeof(och->permissions_bit_mask)); // GOOD

But for the protocol reader / debuggerer this is much easier since this is the
way he will see them on the wire and the way it is laid out in the standard text.

It was much easier to read the standard text and develop the header this way, complicated
by the fact that OSD v2 was a moving target and the changes from OSD v1. And it helped in
finding bugs. Now to go over all of them and calculate the difference and remove it. I'm
loosing information, and I feel sad to loose it.

But if you are totally not convinced I will remove them?

> 
>> +/*54*/	u8 reserved2;
>> +/*55*/	u8 object_descriptor_type; /* high nibble */
>> +} __packed;
>> +
>> +/*56 v1*/
>> +struct osdv1_cap_object_descriptor {
>> +	union {
>> +		struct {
>> +/*56*/			__be32 policy_access_tag;
>> +/*60*/			__be64 allowed_partition_id;
>> +/*68*/			__be64 allowed_object_id;
>> +/*76*/			__be32 reserved;
>> +		} __packed obj_desc;
>> +
>> +		u8 object_descriptor[80-56];/*24*/
>> +	};
>> +} __packed;
>> +/*80 v1*/
>> +
>> +struct osd_capability {
>> +	struct osd_capability_head h;
>> +	struct osdv1_cap_object_descriptor od;
>> +} __packed;
>> +
>> +/**
>> + * osd_sec_set_caps - set cap-bits into the capabilities header
>> + *
>> + * @cap:	The osd_capability_head to set cap bits to.
>> + * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
>> + *
>> + * permissions_bit_mask is unaligned use below to set into caps
>> + * in a version independent way
>> + */
>> +static inline void osd_sec_set_caps(struct osd_capability_head *cap,
>> +	u16 bit_mask)
>> +{
>> +	/*
>> +	 *Note: The bits above are defined LE order this is because this way
>> +	 *      they can grow in the future to more then 16, and still retain
>> +	 *      there constant values.
>> +	 */
>> +	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
>> +}
>> +
>> +#endif /* ndef __OSD_PROTOCOL_H__ */
> 
> ---
> ~Randy

Thanks
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver2] libosd: OSDv1 Headers
@ 2008-11-12 13:10           ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-12 13:10 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: James Bottomley, Andrew Morton, Jörn Engel,
	open-osd development, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, linux-scsi, Sami.Iren, linux-kernel

Randy Dunlap wrote:
> On Sun, 09 Nov 2008 16:52:36 +0200 Boaz Harrosh wrote:
> 
>> Headers only patch.
>>
>> osd_protocol.h
>> 	Contains a C-fied definition of the T10 OSD standard
>> osd_types.h
>> 	Contains CPU order common used types
>> osd_initiator.h
>> 	API definition of the osd_initiator library
>> osd_sec.h
>> 	Contains High level API for the security manager.
>>
>> [Note that checkpatch spews errors on things that are valid in this context
>> and will not be fixed]
>>
>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>> Reviewed-by: Benny Halevy <bhalevy@panasas.com>

Thank you Randy for your review, I will post a fixed
patch shortly. I have changed according to your comments
except in one place, see arguments below.

>> ---
>>  include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
>>  include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
>>  include/scsi/osd_sec.h       |   45 ++++
>>  include/scsi/osd_types.h     |   40 ++++
>>  4 files changed, 914 insertions(+), 0 deletions(-)
>>  create mode 100644 include/scsi/osd_initiator.h
>>  create mode 100644 include/scsi/osd_protocol.h
>>  create mode 100644 include/scsi/osd_sec.h
>>  create mode 100644 include/scsi/osd_types.h
>>
>> diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
>> new file mode 100644
>> index 0000000..9bab95d
>> --- /dev/null
>> +++ b/include/scsi/osd_initiator.h
>> @@ -0,0 +1,332 @@
>> +/*
>> + * osd_initiator.h - OSD initiator API definition
>> + *
>> + * Copyright (C) 2008 Panasas Inc.  All rights reserved.
>> + *
>> + * Authors:
>> + *   Boaz Harrosh <bharrosh@panasas.com>
>> + *   Benny Halevy <bhalevy@panasas.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2
>> + *
>> + */
>> +#ifndef __OSD_INITIATOR_H__
>> +#define __OSD_INITIATOR_H__
>> +
>> +#include "osd_protocol.h"
>> +#include "osd_types.h"
>> +
>> +#include <linux/blkdev.h>
>> +
>> +/* Note: "NI" in comments below means "Not Implemented yet" */
>> +
>> +/*
>> + * Object-based Storage Device.
>> + * This object represents an OSD device.
>> + * It is not a full linux device in any way. It is only
>> + * a place to hang resources associated with a Linux
>> + * request Q and some default properties.
>> + */
>> +struct osd_dev {
>> +	struct scsi_device *scsi_device;
>> +	unsigned def_timeout;
>> +};
>> +
>> +void osd_dev_init(struct osd_dev *, struct scsi_device *scsi_dev);
> 
> Don't mix having parameter names and not having them.
> Preferred is having them.
> 

I don't know what got into me. I thought it would be more readable this
way. But you are right consistency is very important.

>> +void osd_dev_fini(struct osd_dev *);
>> +
>> +struct osd_request;
>> +typedef void (osd_req_done_fn)(struct osd_request *, void *);
>> +
>> +struct osd_request {
>> +	struct osd_cdb cdb;
>> +	struct osd_data_out_integrity_info out_data_integ;
>> +	struct osd_data_in_integrity_info in_data_integ;
>> +
>> +	struct osd_dev *osd_dev;
>> +	struct request *request;
>> +
>> +	struct _osd_req_data_segment {
>> +		void *buff;
>> +		unsigned alloc_size; /* 0 here means not allocated by us */
> 
> Could/would some other code allocate it, or is the "by us" just redundant?
> 

I've changed the comment as it was not clear it is now:
+		unsigned alloc_size; /* 0 here means: don't call kfree */

>> +		unsigned total_bytes;
>> +	} set_attr, enc_get_attr, get_attr;
>> +
>> +	struct _osd_io_info {
>> +		struct bio *bio;
>> +		u64 total_bytes;
>> +		struct request *req;
>> +		struct _osd_req_data_segment *last_seg;
>> +		u8 *pad_buff;
>> +	} out, in;
>> +
>> +	gfp_t alloc_flags;
>> +	unsigned timeout;
>> +	unsigned retries;
>> +	u8 sense[OSD_MAX_SENSE_LEN];
>> +	enum osd_attributes_mode attributes_mode;
>> +
>> +	osd_req_done_fn *async_done;
>> +	void *async_private;
>> +	int async_error;
>> +};
>> +
>> +/**
> 
> Don't start comment blocks with /** when they are not kernel-doc,
> like this one is not.
> 

OK, I must confess my kernel-doc total ignorance. I was imagining that
each source file's kernel-doc comments are collected into an html file.
I thought that this comment will be like an introduction to the following
function-by-function reference. Anyway it's fixed

>> + * How to use the osd library:
>> + *
>> + * osd_start_request
>> + *	Allocates a request.
>> + *
>> + * osd_req_*
>> + *	Call one of, to encode the desired operation.
>> + *
>> + * osd_add_{get,set}_attr
>> + *	Optionally add attributes to the CDB, list or page mode.
>> + *
>> + * osd_finalize_request
>> + *	Computes final data out/in offsets and signs the request,
>> + *	making it ready for execution.
>> + *
>> + * osd_execute_request
>> + *	May be called to execute it through the block layer. Other wise submit
>> + *	the associated block request in some other way.
>> + *
>> + * After execution:
>> + * osd_req_decode_sense
>> + *	Decodes sense information to verify execution results.
>> + *
>> + * osd_req_decode_get_attr
>> + *	Retrieve osd_add_get_attr_list() values if used.
>> + *
>> + * osd_end_request
>> + *	Must be called to deallocate the request.
>> + */
>> +
>> +/**
>> + * osd_start_request - Allocate and initialize an osd_request
>> + *
>> + * @osd_dev:    OSD device that holds the scsi-device and default values
>> + *              that the request is associated with.
>> + * @gfp:        The allocation flags to use for request allocation, and all
>> + *              subsequent allocations. This will be stored at
>> + *              osd_request->alloc_flags, can be changed by user later
>> + *
>> + * Allocate osd_request and initialize all members to the
>> + * default/initial state.
>> + */
>> +struct osd_request *osd_start_request(struct osd_dev *, gfp_t gfp);
>> +
>> +enum osd_req_options {
>> +	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
>> +	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
>> +
>> +	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
>> +};
>> +
>> +/**
>> + * osd_finalize_request - Sign request and prepare request for execution
>> + *
>> + * @or:		osd_request to prepare
>> + * @options:	combination of osd_req_options bit flags or 0.
>> + * @cap	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
>> + *              The security manager as capabilities for this cdb.
>> + * @cap_key	The cryptographic key used to sign the cdb/data. Can be null
>> + *              if NOSEC is used.
> 
> Last 2 parameters need a ':' after the @param_name, like the first 2 have.
> 
oops

>> + *
>> + * The actual request and bios are only allocated here, so are the get_attr
>> + * buffers that will receive the returned attributes. Copy's @cap to cdb.
>> + * Sign the cdb/data with @cap_key.
>> + */
>> +int osd_finalize_request(struct osd_request *or,
>> +	u8 options, const void *cap, const u8 *cap_key);
>> +
>> +/**
>> + * osd_execute_request - Execute the request synchronously through
>> + *                       the block-layer
> 
> Function name and short description need to be on one line.
> 

OK I re-worded so it will fit in one line. What happens if it does not
fit, both name and description, in 80 characters? is there a continuation
symbol or something?

>> + * @or:		osd_request to Executed
>> + *
>> + * Calls blk_execute_rq to q the command and waits for completion.
>> + */
>> +int osd_execute_request(struct osd_request *or);
>> +
>> +/**
>> + * osd_execute_request_async - submits the request for execution through
>> + *                             the block-layer without waitting.
> 
> Ditto.
> 
>> + * @or:                      - osd_request to Executed
>> + * @done: (Optional)         - Called at end of execution
>> + * @private:                 - Will be passes to @done function
> 
> s/passes/passed/
> 
Thanks

>> + *
>> + * Calls blk_execute_rq_nowait to q the command. When execution is done
>> + * Optionally calles @done with @private as parameter. or->async_error has the
> 
> s/calles/calls/
> 
>> + * Return code
> 
> and don't start each line with a Capital letter since they are not the
> beginning of sentences.  What's with that period ('.') before "or->async_error"
> (which needs a space after "or").
> 

I reworded these so they are more clear, I hope.

> 
>> + */
>> +int osd_execute_request_async(struct osd_request *or,
>> +	osd_req_done_fn *done, void *private);
>> +
>> +/**
>> + * osd_end_request - return osd_request to free store
>> + *
>> + * @or:		osd_request to free
>> + *
>> + * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
>> + */
>> +void osd_end_request(struct osd_request *or);
>> +
>> +/*
>> + * CDB Encoding
>> + *
>> + * Note: call only one of the following methods.
>> + */
>> +
>> +/*
>> + * Device commands
>> + */
>> +void osd_req_set_master_seed_xchg(struct osd_request *, ...);/* NI */
>> +void osd_req_set_master_key(struct osd_request *, ...);/* NI */
>> +
>> +void osd_req_format(struct osd_request *, u64 tot_capacity);
>> +
>> +/* list all partitions
>> + * @list header must be initialized to zero on first run.
>> + *
>> + * Call osd_is_obj_list_done() to find if we got the complete list.
>> + */
>> +int osd_req_list_dev_partitions(struct osd_request *,
>> +	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
>> +
>> +void osd_req_flush_obsd(struct osd_request *,
>> +	enum osd_options_flush_scope_values);
>> +
>> +void osd_req_perform_scsi_command(struct osd_request *,
>> +	const u8 *cdb, ...);/* NI */
>> +void osd_req_task_management(struct osd_request *, ...);/* NI */
>> +
>> +/*
>> + * Partition commands
>> + */
>> +void osd_req_create_partition(struct osd_request *, osd_id partition);
>> +void osd_req_remove_partition(struct osd_request *, osd_id partition);
>> +
>> +void osd_req_set_partition_key(struct osd_request *,
>> +	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
>> +	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
>> +
>> +/* list all collections in the partition
>> + * @list header must be init to zero on first run.
>> + *
>> + * Call osd_is_obj_list_done() to find if we got the complete list.
>> + */
>> +int osd_req_list_partition_collections(struct osd_request *,
>> +	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
>> +	unsigned nelem);
>> +
>> +/* list all objects in the partition
>> + * @list header must be init to zero on first run.
>> + *
>> + * Call osd_is_obj_list_done() to find if we got the complete list.
>> + */
>> +int osd_req_list_partition_objects(struct osd_request *,
>> +	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
>> +	unsigned nelem);
>> +
>> +void osd_req_flush_partition(struct osd_request *,
>> +	osd_id partition, enum osd_options_flush_scope_values);
>> +
>> +/*
>> + * Collection commands
>> + */
>> +void osd_req_create_collection(struct osd_request *,
>> +	const struct osd_obj_id *);/* NI */
>> +void osd_req_remove_collection(struct osd_request *,
>> +	const struct osd_obj_id *);/* NI */
>> +
>> +/* list all objects in the collection */
>> +int osd_req_list_collection_objects(struct osd_request *,
>> +	const struct osd_obj_id *, osd_id initial_id,
>> +	struct osd_obj_id_list *list, unsigned nelem);
>> +
>> +/* V2 only filtered list of objects in the collection */
>> +void osd_req_query(struct osd_request *, ...);/* NI */
>> +
>> +void osd_req_flush_collection(struct osd_request *,
>> +	const struct osd_obj_id *, enum osd_options_flush_scope_values);
>> +
>> +void osd_req_get_member_attrs(struct osd_request *, ...);/* V2-only NI */
>> +void osd_req_set_member_attrs(struct osd_request *, ...);/* V2-only NI */
>> +
>> +/*
>> + * Object commands
>> + */
>> +void osd_req_create_object(struct osd_request *, struct osd_obj_id *);
>> +void osd_req_remove_object(struct osd_request *, struct osd_obj_id *);
>> +
>> +void osd_req_write(struct osd_request *,
>> +	const struct osd_obj_id *, struct bio *data_out, u64 offset);
>> +void osd_req_append(struct osd_request *,
>> +	const struct osd_obj_id *, struct bio *data_out);/* NI */
>> +void osd_req_create_write(struct osd_request *,
>> +	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
>> +void osd_req_clear(struct osd_request *,
>> +	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
>> +void osd_req_punch(struct osd_request *,
>> +	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
>> +
>> +void osd_req_flush_object(struct osd_request *,
>> +	const struct osd_obj_id *, enum osd_options_flush_scope_values,
>> +	/*V2*/ u64 offset, /*V2*/ u64 len);
>> +
>> +void osd_req_read(struct osd_request *,
>> +	const struct osd_obj_id *, struct bio *data_in, u64 offset);
>> +
>> +/*
>> + * Root/Partition/Collection/Object Attributes commands
>> + */
>> +
>> +/* get before set */
>> +void osd_req_get_attributes(struct osd_request *, const struct osd_obj_id *);
>> +
>> +/* set before get */
>> +void osd_req_set_attributes(struct osd_request *, const struct osd_obj_id *);
>> +
>> +/*
>> + * Attributes appended to most commands
>> + */
>> +
>> +/* Attributes List mode (or V2 CDB) */
>> +  /*
>> +   * TODO: In ver2 if at finalize time only one attr was set and no gets,
>> +   * then the Attributes CDB mode is used automatically to save IO.
>> +   */
>> +
>> +/* set a list of attributes. */
>> +int osd_req_add_set_attr_list(struct osd_request *,
>> +	const struct osd_attr *, unsigned nelem);
>> +
>> +/* get a list of attributes */
>> +int osd_req_add_get_attr_list(struct osd_request *,
>> +	const struct osd_attr *, unsigned nelem);
>> +
>> +/*
>> + * Attributes list decoding
>> + * Must be called after osd_request.request was executed
>> + * It is called in a loop to decode the returned get_attr
>> + * (see osd_add_get_attr)
>> + */
>> +int osd_req_decode_get_attr_list(struct osd_request *,
>> +	struct osd_attr *, int *nelem, void **iterator);
>> +
>> +/* Attributes Page mode */
>> +
>> +/*
>> + * Read an attribute page and optionally set one attribute
>> + *
>> + * Retrieves the attribute page directly to a user buffer.
>> + * @attr_page_data shall stay valid until end of execution.
>> + * See osd_attributes.h for common page structures
>> + */
>> +int osd_req_add_get_attr_page(struct osd_request *,
>> +	u32 page_id, void *attr_page_data, unsigned max_page_len,
>> +	const struct osd_attr *set_one);
>> +
>> +#endif /* __OSD_LIB_H__ */
>> diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
>> new file mode 100644
>> index 0000000..77a74a3
>> --- /dev/null
>> +++ b/include/scsi/osd_protocol.h
>> @@ -0,0 +1,497 @@
>> +/*
>> + * osd_protocol.h - OSD T10 standard C definitions.
>> + *
>> + * Copyright (C) 2008 Panasas Inc.  All rights reserved.
>> + *
>> + * Authors:
>> + *   Boaz Harrosh <bharrosh@panasas.com>
>> + *   Benny Halevy <bhalevy@panasas.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2
>> + *
>> + * This file contains types and constants that are defined by the protocol
>> + * Note: All names and symbols are taken from the OSD standard's text.
>> + */
>> +#ifndef __OSD_PROTOCOL_H__
>> +#define __OSD_PROTOCOL_H__
>> +
>> +#include <linux/types.h>
>> +#include <asm/unaligned.h>
>> +#include <scsi/scsi.h>
>> +
>> +enum {
>> +	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
>> +	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
>> +	OSDv1_CAP_LEN = 80,
>> +	/* Latest supported version */
>> +	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
>> +	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
>> +	OSD_CAP_LEN = OSDv1_CAP_LEN,
>> +
>> +	OSD_SYSTEMID_LEN = 20,
>> +	OSD_CRYPTO_KEYID_SIZE = 20,
>> +	OSD_CRYPTO_SEED_SIZE = 4,
>> +	OSD_CRYPTO_NONCE_SIZE = 12,
>> +	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
>> +
>> +	OSD_PARTITION_FIRST_ID = 0x10000,
>> +	OSD_OBJECT_FIRST_ID = 0x10000,
>> +};
>> +
>> +/* (osd-r10 5.2.4)
>> + * osd2r03: 5.2.3 Caching control bits
>> + */
>> +enum osd_options_byte {
>> +	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
>> +	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
>> +};
>> +
>> +/*
>> + * osd2r03: 5.2.5 Isolation.
>> + * First 3 bits, V2-only.
>> + * Also for attr 110h "default isolation method" at Root Information page
>> + */
>> +enum osd_options_byte_isolation {
>> +	OSD_ISOLATION_DEFAULT = 0,
>> +	OSD_ISOLATION_NONE = 1,
>> +	OSD_ISOLATION_STRICT = 2,
>> +	OSD_ISOLATION_RANGE = 4,
>> +	OSD_ISOLATION_FUNCTIONAL = 5,
>> +	OSD_ISOLATION_VENDOR = 7,
>> +};
>> +
>> +/* (osd-r10: 6.7)
>> + * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
>> + */
>> +enum osd_options_flush_scope_values {
>> +	OSD_CDB_FLUSH_ALL = 0,
>> +	OSD_CDB_FLUSH_ATTR_ONLY = 1,
>> +
>> +	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
>> +	/* V2-only */
>> +	OSD_CDB_FLUSH_ALL_RANGE = 2,
>> +};
>> +
>> +/* osd2r03: 5.2.10 Timestamps control */
>> +enum {
>> +	OSD_CDB_NORMAL_TIMESTAMPS = 0,
>> +	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
>> +};
>> +
>> +/* (osd-r10: 5.2.2.1)
>> + * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
>> + *	2 bits at second nibble of command_specific_options byte
>> + */
>> +enum osd_attributes_mode {
>> +	/* V2-only */
>> +	OSD_CDB_SET_ONE_ATTR = 0x10,
>> +
>> +	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
>> +	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
>> +
>> +	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
>> +};
>> +
>> +/* (osd-r10: 4.12.5)
>> + * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
>> + *	byte offset = mantissa * (2^(exponent+8))
>> + *	struct {
>> + *		unsigned mantissa: 28;
>> + *		int exponent: 04;
>> + *	}
>> + */
>> +typedef __be32 __bitwise osd_cdb_offset;
>> +
>> +enum {
>> +	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
>> +	OSD_OFFSET_MAX_BITS = 28,
>> +
>> +	OSDv1_OFFSET_MIN_SHIFT = 8,
>> +	OSD_OFFSET_MAX_SHIFT = 16,
>> +};
>> +
>> +/* Return the smallest allowed encoded offset that contains @offset.
>> + *
>> + * The actual encoded offset returned is @offset + *padding.
>> + * (up to max_shift, non-inclusive)
>> + */
>> +osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
>> +	int min_shift, int max_shift);
>> +
>> +/* Minimum alignment is 256 bytes
>> + * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
>> + * which is 8 to 23 but IBM code restricts it to 16, so be it.
>> + */
>> +static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
>> +{
>> +	return __osd_encode_offset(offset, padding,
>> +				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
>> +}
>> +
>> +/* osd2r03: 5.2.1 Overview */
>> +struct osd_cdb_head {
>> +	struct scsi_varlen_cdb_hdr varlen_cdb;
>> +/*10*/	u8		options;
>> +	u8		command_specific_options;
>> +	u8		timestamp_control;
>> +/*13*/	u8		reserved1[3];
>> +/*16*/	__be64		partition;
>> +/*24*/	__be64		object;
>> +/*32*/	union { /* V1 vs V2 alignment differences */
>> +		struct __osdv1_cdb_addr_len {
>> +/*32*/			__be32 		list_identifier;/* Rarely used */
>> +/*36*/			__be64		length;
>> +/*44*/			__be64		start_address;
>> +		} __packed v1;
>> +	};
>> +/*52*/	union { /* selected attributes mode Page/List/Single */
>> +		struct osd_attributes_page_mode {
>> +/*52*/			__be32		get_attr_page;
>> +/*56*/			__be32		get_attr_alloc_length;
>> +/*60*/			osd_cdb_offset	get_attr_offset;
>> +
>> +/*64*/			__be32		set_attr_page;
>> +/*68*/			__be32		set_attr_id;
>> +/*72*/			__be32		set_attr_length;
>> +/*76*/			osd_cdb_offset	set_attr_offset;
>> +		} __packed attrs_page;
>> +
>> +		struct osd_attributes_list_mode {
>> +/*52*/			__be32		get_attr_desc_bytes;
>> +/*56*/			osd_cdb_offset	get_attr_desc_offset;
>> +
>> +/*60*/			__be32		get_attr_alloc_length;
>> +/*64*/			osd_cdb_offset	get_attr_offset;
>> +
>> +/*68*/			__be32		set_attr_bytes;
>> +/*72*/			osd_cdb_offset	set_attr_offset;
>> +			__be32 not_used;
>> +		} __packed attrs_list;
>> +
>> +		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
>> +		struct osd_attributes_cdb_mode {
>> +/*52*/			__be32		set_attr_page;
>> +/*56*/			__be32		set_attr_id;
>> +/*60*/			__be16		set_attr_len;
>> +/*62*/			u8		set_attr_val[80-62];
>> +		} __packed attrs_cdb;
>> +/*52*/		u8 get_set_attributes_parameters[80-52];
>> +	};
>> +} __packed;
>> +/*80*/
>> +
>> +/*160 v1*/
>> +struct osd_security_parameters {
>> +/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
>> +/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
>> +/*192*/osd_cdb_offset	data_in_integrity_check_offset;
>> +/*196*/osd_cdb_offset	data_out_integrity_check_offset;
>> +} __packed;
>> +/*200 v1*/
>> +
>> +struct osdv1_cdb {
>> +	struct osd_cdb_head h;
>> +	u8 caps[OSDv1_CAP_LEN];
>> +	struct osd_security_parameters sec_params;
>> +} __packed;
>> +
>> +struct osd_cdb {
>> +	union {
>> +		struct osdv1_cdb v1;
>> +		u8 buff[OSD_TOTAL_CDB_LEN];
>> +	};
>> +} __packed;
>> +
>> +static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
>> +{
>> +	return (struct osd_cdb_head *)ocdb->buff;
>> +}
>> +
>> +/* define both version actions
>> + * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
>> + */
>> +#define OSD_ACT___(Name, Num) \
>> +	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
>> +	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
>> +
>> +/* V2 only actions */
>> +#define OSD_ACT_V2(Name, Num) \
>> +	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
>> +
>> +#define OSD_ACT_V1_V2(Name, Num1, Num2) \
>> +	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
>> +	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
>> +
>> +enum osd_service_actions {
>> +	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
>> +	OSD_ACT___(FORMAT_OSD,			0x01)
>> +	OSD_ACT___(CREATE,			0x02)
>> +	OSD_ACT___(LIST,			0x03)
>> +	OSD_ACT_V2(PUNCH,			0x04)
>> +	OSD_ACT___(READ,			0x05)
>> +	OSD_ACT___(WRITE,			0x06)
>> +	OSD_ACT___(APPEND,			0x07)
>> +	OSD_ACT___(FLUSH,			0x08)
>> +	OSD_ACT_V2(CLEAR,			0x09)
>> +	OSD_ACT___(REMOVE,			0x0A)
>> +	OSD_ACT___(CREATE_PARTITION,		0x0B)
>> +	OSD_ACT___(REMOVE_PARTITION,		0x0C)
>> +	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
>> +	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
>> +	OSD_ACT___(CREATE_AND_WRITE,		0x12)
>> +	OSD_ACT___(CREATE_COLLECTION,		0x15)
>> +	OSD_ACT___(REMOVE_COLLECTION,		0x16)
>> +	OSD_ACT___(LIST_COLLECTION,		0x17)
>> +	OSD_ACT___(SET_KEY,			0x18)
>> +	OSD_ACT___(SET_MASTER_KEY,		0x19)
>> +	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
>> +	OSD_ACT___(FLUSH_PARTITION,		0x1B)
>> +	OSD_ACT___(FLUSH_OSD,			0x1C)
>> +
>> +	OSD_ACT_V2(QUERY,			0x20)
>> +	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
>> +	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
>> +	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
>> +	OSD_ACT_V2(READ_MAP,			0x31)
>> +
>> +	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
>> +	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
>> +	/* 0x8F80 to 0x8FFF are Vendor specific */
>> +};
>> +
>> +/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
>> +struct osd_attributes_list_attrid {
>> +	__be32 page;
>> +	__be32 attr_id;
>> +} __packed;
>> +
>> +/*
>> + * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
>> + *                  for setting attributes
>> + */
>> +struct osd_attributes_list_element {
>> +	__be32 page;
>> +	__be32 attr_id;
>> +	__be16 attr_bytes;
>> +	u8 attr_val[0];
>> +} __packed;
>> +
>> +enum {
>> +	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
>> +};
>> +
>> +enum {
>> +	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
>> +	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
>> +};
>> +
>> +static inline unsigned osdv1_attr_list_elem_size(unsigned len)
>> +{
>> +	return ALIGN(len + sizeof(struct osd_attributes_list_element),
>> +		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
>> +}
>> +
>> +/*
>> + * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
>> + */
>> +enum osd_attr_list_types {
>> +	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
>> +	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
>> +	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
>> +	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
>> +};
>> +
>> +/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
>> +struct osd_attributes_list_multi_header {
>> +	__be64 object_id;
>> +	u8 object_type; /* object_type enum below */
>> +	u8 reserved[5];
>> +	__be16 list_bytes;
>> +	/* followed by struct osd_attributes_list_element's */
>> +};
>> +
>> +struct osdv1_attributes_list_header {
>> +	u8 type;	/* low 4-bit only */
>> +	u8 pad;
>> +	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
>> +	/*
>> +	 * type=9 followed by struct osd_attributes_list_element's
>> +	 * type=E followed by struct osd_attributes_list_multi_header's
>> +	 */
>> +} __packed;
>> +
>> +static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
>> +{
>> +	return be16_to_cpu(h->list_bytes);
>> +}
>> +
>> +/* (osd-r10 6.13)
>> + * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
>> + *	for root_lstchg below
>> + */
>> +enum {
>> +	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
>> +	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
>> +};
>> +
>> +/*
>> + * osd2r03: 6.15.2 LIST command parameter data
>> + * (Also for LIST COLLECTION)
>> + */
>> +struct osd_obj_id_list {
>> +	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
>> +	__be64 continuation_id;
>> +	__be32 list_identifier;
>> +	u8 pad[3];
>> +	u8 root_lstchg;
>> +	__be64 object_ids[0];
>> +} __packed;
>> +
>> +static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
>> +	bool *is_changed)
>> +{
>> +	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
>> +	return 0 != list->continuation_id;
>> +}
>> +
>> +/*
>> + * osd2r03: 4.12.4.5 The ALLDATA security method
>> + */
>> +struct osd_data_out_integrity_info {
>> +	__be64 data_bytes;
>> +	__be64 set_attributes_bytes;
>> +	__be64 get_attributes_bytes;
>> +	__be64 integrity_check_value;
>> +} __packed;
>> +
>> +struct osd_data_in_integrity_info {
>> +	__be64 data_bytes;
>> +	__be64 retrieved_attributes_bytes;
>> +	__be64 integrity_check_value;
>> +} __packed;
>> +
>> +struct osd_timestamp {
>> +	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
>> +} __packed;
>> +/* FIXME: define helper functions to convert to/from osd time format */
>> +
>> +/*
>> + * Capability & Security definitions
>> + * osd2r03: 4.11.2.2 Capability format
>> + * osd2r03: 5.2.8 Security parameters
>> + */
>> +
>> +struct osd_key_identifier {
>> +	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
>> +} __packed;
>> +
>> +/* for osd_capability.format */
>> +enum {
>> +	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
>> +	OSD_SEC_CAP_FORMAT_VER1 = 1,
>> +	OSD_SEC_CAP_FORMAT_VER2 = 2,
>> +};
>> +
>> +/* security_method */
>> +enum {
>> +	OSD_SEC_NOSEC = 0,
>> +	OSD_SEC_CAPKEY = 1,
>> +	OSD_SEC_CMDRSP = 2,
>> +	OSD_SEC_ALLDATA = 3,
>> +};
>> +
>> +enum object_type {
>> +	OSD_SEC_OBJ_ROOT = 0x1,
>> +	OSD_SEC_OBJ_PARTITION = 0x2,
>> +	OSD_SEC_OBJ_COLLECTION = 0x40,
>> +	OSD_SEC_OBJ_USER = 0x80,
>> +};
>> +
>> +enum osd_capability_bit_masks {
>> +	OSD_SEC_CAP_APPEND	= (1 << 0),
>> +	OSD_SEC_CAP_OBJ_MGMT	= (1 << 1),
>> +	OSD_SEC_CAP_REMOVE	= (1 << 2),
>> +	OSD_SEC_CAP_CREATE	= (1 << 3),
>> +	OSD_SEC_CAP_SET_ATTR	= (1 << 4),
>> +	OSD_SEC_CAP_GET_ATTR	= (1 << 5),
>> +	OSD_SEC_CAP_WRITE	= (1 << 6),
>> +	OSD_SEC_CAP_READ	= (1 << 7),
>> +
>> +	OSD_SEC_CAP_NONE1	= (1 << 8),
>> +	OSD_SEC_CAP_NONE2	= (1 << 9),
>> +	OSD_SEC_CAP_NONE3	= (1 << 10),
>> +	OSD_SEC_CAP_QUERY	= (1 << 11), /*v2 only*/
>> +	OSD_SEC_CAP_M_OBJECT	= (1 << 12), /*v2 only*/
>> +	OSD_SEC_CAP_POL_SEC	= (1 << 13),
>> +	OSD_SEC_CAP_GLOBAL	= (1 << 14),
>> +	OSD_SEC_CAP_DEV_MGMT	= (1 << 15),
> 
> These could use BIT(nr) from bitops.h.
> 
Thanks. It looks much better with this macro.

>> +};
>> +
>> +/* for object_descriptor_type (hi nibble used) */
>> +enum {
>> +	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
>> +	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
>> +	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
>> +	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
>> +};
>> +
>> +/* (osd-r10:4.9.2.2)
>> + * osd2r03:4.11.2.2 Capability format
>> + */
>> +struct osd_capability_head {
>> +	u8 format; /* low nibble */
>> +	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
>> +	u8 security_method;
>> +	u8 reserved1;
>> +/*04*/	struct osd_timestamp expiration_time;
>> +/*10*/	u8 audit[30-10];
>> +/*30*/	u8 discriminator[42-30];
>> +/*42*/	struct osd_timestamp object_created_time;
>> +/*48*/	u8 object_type;
>> +	u8 permissions_bit_mask[54-49];
> 
> The offset comments are OK with me, but please lose the [b-a] length specifiers.
> 

I would, please, like to keep them. For the user it does not matter.
Because he is not suppose to care if he is doing:
-	memset(och->permissions_bit_mask, 0, 5); // BAD
+	memset(och->permissions_bit_mask, 0, sizeof(och->permissions_bit_mask)); // GOOD

But for the protocol reader / debuggerer this is much easier since this is the
way he will see them on the wire and the way it is laid out in the standard text.

It was much easier to read the standard text and develop the header this way, complicated
by the fact that OSD v2 was a moving target and the changes from OSD v1. And it helped in
finding bugs. Now to go over all of them and calculate the difference and remove it. I'm
loosing information, and I feel sad to loose it.

But if you are totally not convinced I will remove them?

> 
>> +/*54*/	u8 reserved2;
>> +/*55*/	u8 object_descriptor_type; /* high nibble */
>> +} __packed;
>> +
>> +/*56 v1*/
>> +struct osdv1_cap_object_descriptor {
>> +	union {
>> +		struct {
>> +/*56*/			__be32 policy_access_tag;
>> +/*60*/			__be64 allowed_partition_id;
>> +/*68*/			__be64 allowed_object_id;
>> +/*76*/			__be32 reserved;
>> +		} __packed obj_desc;
>> +
>> +		u8 object_descriptor[80-56];/*24*/
>> +	};
>> +} __packed;
>> +/*80 v1*/
>> +
>> +struct osd_capability {
>> +	struct osd_capability_head h;
>> +	struct osdv1_cap_object_descriptor od;
>> +} __packed;
>> +
>> +/**
>> + * osd_sec_set_caps - set cap-bits into the capabilities header
>> + *
>> + * @cap:	The osd_capability_head to set cap bits to.
>> + * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
>> + *
>> + * permissions_bit_mask is unaligned use below to set into caps
>> + * in a version independent way
>> + */
>> +static inline void osd_sec_set_caps(struct osd_capability_head *cap,
>> +	u16 bit_mask)
>> +{
>> +	/*
>> +	 *Note: The bits above are defined LE order this is because this way
>> +	 *      they can grow in the future to more then 16, and still retain
>> +	 *      there constant values.
>> +	 */
>> +	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
>> +}
>> +
>> +#endif /* ndef __OSD_PROTOCOL_H__ */
> 
> ---
> ~Randy

Thanks
Boaz
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 183+ messages in thread

* [PATCH 03/18 ver3] libosd: OSDv1 Headers
  2008-11-10 17:29       ` Randy Dunlap
@ 2008-11-12 13:13           ` Boaz Harrosh
  2008-11-12 13:13           ` Boaz Harrosh
  1 sibling, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-12 13:13 UTC (permalink / raw)
  To: Randy Dunlap, James Bottomley
  Cc: Andrew Morton, Jörn Engel, open-osd development,
	Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-scsi,
	Sami.Iren, linux-kernel


Headers only patch.

osd_protocol.h
	Contains a C-fied definition of the T10 OSD standard
osd_types.h
	Contains CPU order common used types
osd_initiator.h
	API definition of the osd_initiator library
osd_sec.h
	Contains High level API for the security manager.

[Note that checkpatch spews errors on things that are valid in this context
and will not be fixed]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
 include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_sec.h       |   45 ++++
 include/scsi/osd_types.h     |   40 ++++
 4 files changed, 914 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_initiator.h
 create mode 100644 include/scsi/osd_protocol.h
 create mode 100644 include/scsi/osd_sec.h
 create mode 100644 include/scsi/osd_types.h

diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
new file mode 100644
index 0000000..1d92247
--- /dev/null
+++ b/include/scsi/osd_initiator.h
@@ -0,0 +1,332 @@
+/*
+ * osd_initiator.h - OSD initiator API definition
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_INITIATOR_H__
+#define __OSD_INITIATOR_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+#include <linux/blkdev.h>
+
+/* Note: "NI" in comments below means "Not Implemented yet" */
+
+/*
+ * Object-based Storage Device.
+ * This object represents an OSD device.
+ * It is not a full linux device in any way. It is only
+ * a place to hang resources associated with a Linux
+ * request Q and some default properties.
+ */
+struct osd_dev {
+	struct scsi_device *scsi_device;
+	unsigned def_timeout;
+};
+
+void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
+void osd_dev_fini(struct osd_dev *od);
+
+struct osd_request;
+typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
+
+struct osd_request {
+	struct osd_cdb cdb;
+	struct osd_data_out_integrity_info out_data_integ;
+	struct osd_data_in_integrity_info in_data_integ;
+
+	struct osd_dev *osd_dev;
+	struct request *request;
+
+	struct _osd_req_data_segment {
+		void *buff;
+		unsigned alloc_size; /* 0 here means: don't call kfree */
+		unsigned total_bytes;
+	} set_attr, enc_get_attr, get_attr;
+
+	struct _osd_io_info {
+		struct bio *bio;
+		u64 total_bytes;
+		struct request *req;
+		struct _osd_req_data_segment *last_seg;
+		u8 *pad_buff;
+	} out, in;
+
+	gfp_t alloc_flags;
+	unsigned timeout;
+	unsigned retries;
+	u8 sense[OSD_MAX_SENSE_LEN];
+	enum osd_attributes_mode attributes_mode;
+
+	osd_req_done_fn *async_done;
+	void *async_private;
+	int async_error;
+};
+
+/*
+ * How to use the osd library:
+ *
+ * osd_start_request
+ *	Allocates a request.
+ *
+ * osd_req_*
+ *	Call one of, to encode the desired operation.
+ *
+ * osd_add_{get,set}_attr
+ *	Optionally add attributes to the CDB, list or page mode.
+ *
+ * osd_finalize_request
+ *	Computes final data out/in offsets and signs the request,
+ *	making it ready for execution.
+ *
+ * osd_execute_request
+ *	May be called to execute it through the block layer. Other wise submit
+ *	the associated block request in some other way.
+ *
+ * After execution:
+ * osd_req_decode_sense
+ *	Decodes sense information to verify execution results.
+ *
+ * osd_req_decode_get_attr
+ *	Retrieve osd_add_get_attr_list() values if used.
+ *
+ * osd_end_request
+ *	Must be called to deallocate the request.
+ */
+
+/**
+ * osd_start_request - Allocate and initialize an osd_request
+ *
+ * @osd_dev:    OSD device that holds the scsi-device and default values
+ *              that the request is associated with.
+ * @gfp:        The allocation flags to use for request allocation, and all
+ *              subsequent allocations. This will be stored at
+ *              osd_request->alloc_flags, can be changed by user later
+ *
+ * Allocate osd_request and initialize all members to the
+ * default/initial state.
+ */
+struct osd_request *osd_start_request(struct osd_dev *od, gfp_t gfp);
+
+enum osd_req_options {
+	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
+	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
+
+	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
+};
+
+/**
+ * osd_finalize_request - Sign request and prepare request for execution
+ *
+ * @or:		osd_request to prepare
+ * @options:	combination of osd_req_options bit flags or 0.
+ * @cap:	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
+ *              The security manager as capabilities for this cdb.
+ * @cap_key:	The cryptographic key used to sign the cdb/data. Can be null
+ *              if NOSEC is used.
+ *
+ * The actual request and bios are only allocated here, so are the get_attr
+ * buffers that will receive the returned attributes. Copy's @cap to cdb.
+ * Sign the cdb/data with @cap_key.
+ */
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key);
+
+/**
+ * osd_execute_request - Execute the request synchronously through block-layer
+ *
+ * @or:		osd_request to Executed
+ *
+ * Calls blk_execute_rq to q the command and waits for completion.
+ */
+int osd_execute_request(struct osd_request *or);
+
+/**
+ * osd_execute_request_async - Execute the request without waitting.
+ *
+ * @or:                      - osd_request to Executed
+ * @done: (Optional)         - Called at end of execution
+ * @private:                 - Will be passed to @done function
+ *
+ * Calls blk_execute_rq_nowait to queue the command. When execution is done
+ * optionally calls @done with @private as parameter. @or->async_error will
+ * have the return code
+ */
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private);
+
+/**
+ * osd_end_request - return osd_request to free store
+ *
+ * @or:		osd_request to free
+ *
+ * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
+ */
+void osd_end_request(struct osd_request *or);
+
+/*
+ * CDB Encoding
+ *
+ * Note: call only one of the following methods.
+ */
+
+/*
+ * Device commands
+ */
+void osd_req_set_master_seed_xchg(struct osd_request *or, ...);/* NI */
+void osd_req_set_master_key(struct osd_request *or, ...);/* NI */
+
+void osd_req_format(struct osd_request *or, u64 tot_capacity);
+
+/* list all partitions
+ * @list header must be initialized to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values);
+
+void osd_req_perform_scsi_command(struct osd_request *or,
+	const u8 *cdb, ...);/* NI */
+void osd_req_task_management(struct osd_request *or, ...);/* NI */
+
+/*
+ * Partition commands
+ */
+void osd_req_create_partition(struct osd_request *or, osd_id partition);
+void osd_req_remove_partition(struct osd_request *or, osd_id partition);
+
+void osd_req_set_partition_key(struct osd_request *or,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
+
+/* list all collections in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+/* list all objects in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values);
+
+/*
+ * Collection commands
+ */
+void osd_req_create_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+void osd_req_remove_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+
+/* list all objects in the collection */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem);
+
+/* V2 only filtered list of objects in the collection */
+void osd_req_query(struct osd_request *or, ...);/* NI */
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values);
+
+void osd_req_get_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+void osd_req_set_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *);
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);
+void osd_req_append(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out);/* NI */
+void osd_req_create_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
+void osd_req_clear(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
+void osd_req_punch(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
+
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values,
+	/*V2*/ u64 offset, /*V2*/ u64 len);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_in, u64 offset);
+
+/*
+ * Root/Partition/Collection/Object Attributes commands
+ */
+
+/* get before set */
+void osd_req_get_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/* set before get */
+void osd_req_set_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/*
+ * Attributes appended to most commands
+ */
+
+/* Attributes List mode (or V2 CDB) */
+  /*
+   * TODO: In ver2 if at finalize time only one attr was set and no gets,
+   * then the Attributes CDB mode is used automatically to save IO.
+   */
+
+/* set a list of attributes. */
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/* get a list of attributes */
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/*
+ * Attributes list decoding
+ * Must be called after osd_request.request was executed
+ * It is called in a loop to decode the returned get_attr
+ * (see osd_add_get_attr)
+ */
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *, int *nelem, void **iterator);
+
+/* Attributes Page mode */
+
+/*
+ * Read an attribute page and optionally set one attribute
+ *
+ * Retrieves the attribute page directly to a user buffer.
+ * @attr_page_data shall stay valid until end of execution.
+ * See osd_attributes.h for common page structures
+ */
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attr_page_data, unsigned max_page_len,
+	const struct osd_attr *set_one);
+
+#endif /* __OSD_LIB_H__ */
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
new file mode 100644
index 0000000..ce678c5
--- /dev/null
+++ b/include/scsi/osd_protocol.h
@@ -0,0 +1,497 @@
+/*
+ * osd_protocol.h - OSD T10 standard C definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_PROTOCOL_H__
+#define __OSD_PROTOCOL_H__
+
+#include <linux/types.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+enum {
+	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
+	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
+	OSDv1_CAP_LEN = 80,
+	/* Latest supported version */
+	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
+	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
+	OSD_CAP_LEN = OSDv1_CAP_LEN,
+
+	OSD_SYSTEMID_LEN = 20,
+	OSD_CRYPTO_KEYID_SIZE = 20,
+	OSD_CRYPTO_SEED_SIZE = 4,
+	OSD_CRYPTO_NONCE_SIZE = 12,
+	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
+
+	OSD_PARTITION_FIRST_ID = 0x10000,
+	OSD_OBJECT_FIRST_ID = 0x10000,
+};
+
+/* (osd-r10 5.2.4)
+ * osd2r03: 5.2.3 Caching control bits
+ */
+enum osd_options_byte {
+	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
+	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
+};
+
+/*
+ * osd2r03: 5.2.5 Isolation.
+ * First 3 bits, V2-only.
+ * Also for attr 110h "default isolation method" at Root Information page
+ */
+enum osd_options_byte_isolation {
+	OSD_ISOLATION_DEFAULT = 0,
+	OSD_ISOLATION_NONE = 1,
+	OSD_ISOLATION_STRICT = 2,
+	OSD_ISOLATION_RANGE = 4,
+	OSD_ISOLATION_FUNCTIONAL = 5,
+	OSD_ISOLATION_VENDOR = 7,
+};
+
+/* (osd-r10: 6.7)
+ * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
+ */
+enum osd_options_flush_scope_values {
+	OSD_CDB_FLUSH_ALL = 0,
+	OSD_CDB_FLUSH_ATTR_ONLY = 1,
+
+	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
+	/* V2-only */
+	OSD_CDB_FLUSH_ALL_RANGE = 2,
+};
+
+/* osd2r03: 5.2.10 Timestamps control */
+enum {
+	OSD_CDB_NORMAL_TIMESTAMPS = 0,
+	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
+};
+
+/* (osd-r10: 5.2.2.1)
+ * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
+ *	2 bits at second nibble of command_specific_options byte
+ */
+enum osd_attributes_mode {
+	/* V2-only */
+	OSD_CDB_SET_ONE_ATTR = 0x10,
+
+	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
+	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
+
+	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
+};
+
+/* (osd-r10: 4.12.5)
+ * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
+ *	byte offset = mantissa * (2^(exponent+8))
+ *	struct {
+ *		unsigned mantissa: 28;
+ *		int exponent: 04;
+ *	}
+ */
+typedef __be32 __bitwise osd_cdb_offset;
+
+enum {
+	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
+	OSD_OFFSET_MAX_BITS = 28,
+
+	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MAX_SHIFT = 16,
+};
+
+/* Return the smallest allowed encoded offset that contains @offset.
+ *
+ * The actual encoded offset returned is @offset + *padding.
+ * (up to max_shift, non-inclusive)
+ */
+osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
+	int min_shift, int max_shift);
+
+/* Minimum alignment is 256 bytes
+ * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
+ * which is 8 to 23 but IBM code restricts it to 16, so be it.
+ */
+static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
+/* osd2r03: 5.2.1 Overview */
+struct osd_cdb_head {
+	struct scsi_varlen_cdb_hdr varlen_cdb;
+/*10*/	u8		options;
+	u8		command_specific_options;
+	u8		timestamp_control;
+/*13*/	u8		reserved1[3];
+/*16*/	__be64		partition;
+/*24*/	__be64		object;
+/*32*/	union { /* V1 vs V2 alignment differences */
+		struct __osdv1_cdb_addr_len {
+/*32*/			__be32 		list_identifier;/* Rarely used */
+/*36*/			__be64		length;
+/*44*/			__be64		start_address;
+		} __packed v1;
+	};
+/*52*/	union { /* selected attributes mode Page/List/Single */
+		struct osd_attributes_page_mode {
+/*52*/			__be32		get_attr_page;
+/*56*/			__be32		get_attr_alloc_length;
+/*60*/			osd_cdb_offset	get_attr_offset;
+
+/*64*/			__be32		set_attr_page;
+/*68*/			__be32		set_attr_id;
+/*72*/			__be32		set_attr_length;
+/*76*/			osd_cdb_offset	set_attr_offset;
+		} __packed attrs_page;
+
+		struct osd_attributes_list_mode {
+/*52*/			__be32		get_attr_desc_bytes;
+/*56*/			osd_cdb_offset	get_attr_desc_offset;
+
+/*60*/			__be32		get_attr_alloc_length;
+/*64*/			osd_cdb_offset	get_attr_offset;
+
+/*68*/			__be32		set_attr_bytes;
+/*72*/			osd_cdb_offset	set_attr_offset;
+			__be32 not_used;
+		} __packed attrs_list;
+
+		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
+		struct osd_attributes_cdb_mode {
+/*52*/			__be32		set_attr_page;
+/*56*/			__be32		set_attr_id;
+/*60*/			__be16		set_attr_len;
+/*62*/			u8		set_attr_val[80-62];
+		} __packed attrs_cdb;
+/*52*/		u8 get_set_attributes_parameters[80-52];
+	};
+} __packed;
+/*80*/
+
+/*160 v1*/
+struct osd_security_parameters {
+/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*192*/osd_cdb_offset	data_in_integrity_check_offset;
+/*196*/osd_cdb_offset	data_out_integrity_check_offset;
+} __packed;
+/*200 v1*/
+
+struct osdv1_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSDv1_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
+struct osd_cdb {
+	union {
+		struct osdv1_cdb v1;
+		u8 buff[OSD_TOTAL_CDB_LEN];
+	};
+} __packed;
+
+static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
+{
+	return (struct osd_cdb_head *)ocdb->buff;
+}
+
+/* define both version actions
+ * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
+ */
+#define OSD_ACT___(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
+
+/* V2 only actions */
+#define OSD_ACT_V2(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
+
+#define OSD_ACT_V1_V2(Name, Num1, Num2) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
+
+enum osd_service_actions {
+	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
+	OSD_ACT___(FORMAT_OSD,			0x01)
+	OSD_ACT___(CREATE,			0x02)
+	OSD_ACT___(LIST,			0x03)
+	OSD_ACT_V2(PUNCH,			0x04)
+	OSD_ACT___(READ,			0x05)
+	OSD_ACT___(WRITE,			0x06)
+	OSD_ACT___(APPEND,			0x07)
+	OSD_ACT___(FLUSH,			0x08)
+	OSD_ACT_V2(CLEAR,			0x09)
+	OSD_ACT___(REMOVE,			0x0A)
+	OSD_ACT___(CREATE_PARTITION,		0x0B)
+	OSD_ACT___(REMOVE_PARTITION,		0x0C)
+	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
+	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
+	OSD_ACT___(CREATE_AND_WRITE,		0x12)
+	OSD_ACT___(CREATE_COLLECTION,		0x15)
+	OSD_ACT___(REMOVE_COLLECTION,		0x16)
+	OSD_ACT___(LIST_COLLECTION,		0x17)
+	OSD_ACT___(SET_KEY,			0x18)
+	OSD_ACT___(SET_MASTER_KEY,		0x19)
+	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
+	OSD_ACT___(FLUSH_PARTITION,		0x1B)
+	OSD_ACT___(FLUSH_OSD,			0x1C)
+
+	OSD_ACT_V2(QUERY,			0x20)
+	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
+	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
+	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
+	OSD_ACT_V2(READ_MAP,			0x31)
+
+	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
+	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
+	/* 0x8F80 to 0x8FFF are Vendor specific */
+};
+
+/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
+struct osd_attributes_list_attrid {
+	__be32 page;
+	__be32 attr_id;
+} __packed;
+
+/*
+ * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
+ *                  for setting attributes
+ */
+struct osd_attributes_list_element {
+	__be32 page;
+	__be32 attr_id;
+	__be16 attr_bytes;
+	u8 attr_val[0];
+} __packed;
+
+enum {
+	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+};
+
+enum {
+	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
+	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
+};
+
+static inline unsigned osdv1_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
+}
+
+/*
+ * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
+ */
+enum osd_attr_list_types {
+	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
+	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
+	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
+	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
+};
+
+/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
+struct osd_attributes_list_multi_header {
+	__be64 object_id;
+	u8 object_type; /* object_type enum below */
+	u8 reserved[5];
+	__be16 list_bytes;
+	/* followed by struct osd_attributes_list_element's */
+};
+
+struct osdv1_attributes_list_header {
+	u8 type;	/* low 4-bit only */
+	u8 pad;
+	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
+{
+	return be16_to_cpu(h->list_bytes);
+}
+
+/* (osd-r10 6.13)
+ * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
+ *	for root_lstchg below
+ */
+enum {
+	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
+	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
+};
+
+/*
+ * osd2r03: 6.15.2 LIST command parameter data
+ * (Also for LIST COLLECTION)
+ */
+struct osd_obj_id_list {
+	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
+	__be64 continuation_id;
+	__be32 list_identifier;
+	u8 pad[3];
+	u8 root_lstchg;
+	__be64 object_ids[0];
+} __packed;
+
+static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
+	bool *is_changed)
+{
+	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
+	return 0 != list->continuation_id;
+}
+
+/*
+ * osd2r03: 4.12.4.5 The ALLDATA security method
+ */
+struct osd_data_out_integrity_info {
+	__be64 data_bytes;
+	__be64 set_attributes_bytes;
+	__be64 get_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_data_in_integrity_info {
+	__be64 data_bytes;
+	__be64 retrieved_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_timestamp {
+	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
+} __packed;
+/* FIXME: define helper functions to convert to/from osd time format */
+
+/*
+ * Capability & Security definitions
+ * osd2r03: 4.11.2.2 Capability format
+ * osd2r03: 5.2.8 Security parameters
+ */
+
+struct osd_key_identifier {
+	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+} __packed;
+
+/* for osd_capability.format */
+enum {
+	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
+	OSD_SEC_CAP_FORMAT_VER1 = 1,
+	OSD_SEC_CAP_FORMAT_VER2 = 2,
+};
+
+/* security_method */
+enum {
+	OSD_SEC_NOSEC = 0,
+	OSD_SEC_CAPKEY = 1,
+	OSD_SEC_CMDRSP = 2,
+	OSD_SEC_ALLDATA = 3,
+};
+
+enum object_type {
+	OSD_SEC_OBJ_ROOT = 0x1,
+	OSD_SEC_OBJ_PARTITION = 0x2,
+	OSD_SEC_OBJ_COLLECTION = 0x40,
+	OSD_SEC_OBJ_USER = 0x80,
+};
+
+enum osd_capability_bit_masks {
+	OSD_SEC_CAP_APPEND	= BIT(0),
+	OSD_SEC_CAP_OBJ_MGMT	= BIT(1),
+	OSD_SEC_CAP_REMOVE	= BIT(2),
+	OSD_SEC_CAP_CREATE	= BIT(3),
+	OSD_SEC_CAP_SET_ATTR	= BIT(4),
+	OSD_SEC_CAP_GET_ATTR	= BIT(5),
+	OSD_SEC_CAP_WRITE	= BIT(6),
+	OSD_SEC_CAP_READ	= BIT(7),
+
+	OSD_SEC_CAP_NONE1	= BIT(8),
+	OSD_SEC_CAP_NONE2	= BIT(9),
+	OSD_SEC_CAP_NONE3	= BIT(10),
+	OSD_SEC_CAP_QUERY	= BIT(11), /*v2 only*/
+	OSD_SEC_CAP_M_OBJECT	= BIT(12), /*v2 only*/
+	OSD_SEC_CAP_POL_SEC	= BIT(13),
+	OSD_SEC_CAP_GLOBAL	= BIT(14),
+	OSD_SEC_CAP_DEV_MGMT	= BIT(15),
+};
+
+/* for object_descriptor_type (hi nibble used) */
+enum {
+	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
+	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
+	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
+	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
+};
+
+/* (osd-r10:4.9.2.2)
+ * osd2r03:4.11.2.2 Capability format
+ */
+struct osd_capability_head {
+	u8 format; /* low nibble */
+	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
+	u8 security_method;
+	u8 reserved1;
+/*04*/	struct osd_timestamp expiration_time;
+/*10*/	u8 audit[30-10];
+/*30*/	u8 discriminator[42-30];
+/*42*/	struct osd_timestamp object_created_time;
+/*48*/	u8 object_type;
+	u8 permissions_bit_mask[54-49];
+/*54*/	u8 reserved2;
+/*55*/	u8 object_descriptor_type; /* high nibble */
+} __packed;
+
+/*56 v1*/
+struct osdv1_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 policy_access_tag;
+/*60*/			__be64 allowed_partition_id;
+/*68*/			__be64 allowed_object_id;
+/*76*/			__be32 reserved;
+		} __packed obj_desc;
+
+		u8 object_descriptor[80-56];/*24*/
+	};
+} __packed;
+/*80 v1*/
+
+struct osd_capability {
+	struct osd_capability_head h;
+	struct osdv1_cap_object_descriptor od;
+} __packed;
+
+/**
+ * osd_sec_set_caps - set cap-bits into the capabilities header
+ *
+ * @cap:	The osd_capability_head to set cap bits to.
+ * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
+ *
+ * permissions_bit_mask is unaligned use below to set into caps
+ * in a version independent way
+ */
+static inline void osd_sec_set_caps(struct osd_capability_head *cap,
+	u16 bit_mask)
+{
+	/*
+	 *Note: The bits above are defined LE order this is because this way
+	 *      they can grow in the future to more then 16, and still retain
+	 *      there constant values.
+	 */
+	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
+}
+
+#endif /* ndef __OSD_PROTOCOL_H__ */
diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h
new file mode 100644
index 0000000..4c09fee
--- /dev/null
+++ b/include/scsi/osd_sec.h
@@ -0,0 +1,45 @@
+/*
+ * osd_sec.h - OSD security manager API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_SEC_H__
+#define __OSD_SEC_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/*
+ * Contains types and constants of osd capabilities and security
+ * encoding/decoding.
+ * API is trying to keep security abstract so initiator of an object
+ * based pNFS client knows as little as possible about security and
+ * capabilities. It is the Server's osd-initiator place to know more.
+ * Also can be used by osd-target.
+ */
+void osd_sec_encode_caps(void *caps, ...);/* NI */
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1);
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_params);
+
+/* Conditionally sign the CDB according to security setting in ocdb
+ * with cap_key */
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key);
+
+/* Unconditionally sign the BIO data with cap_key.
+ * Check for osd_is_sec_alldata() was done prior to calling this. */
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key);
+
+/* Version independent copy of caps into the cdb */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps);
+
+#endif /* ndef __OSD_SEC_H__ */
diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h
new file mode 100644
index 0000000..ea5372d
--- /dev/null
+++ b/include/scsi/osd_types.h
@@ -0,0 +1,40 @@
+/*
+ * osd_types.h - Types and constants which are not part of the protocol.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Contains types and constants that are implementation specific and are
+ * used by more than one part of the osd library.
+ *     (Eg initiator/target/security_manager/...)
+ */
+#ifndef __OSD_TYPES_H__
+#define __OSD_TYPES_H__
+
+struct osd_systemid {
+	u8 data[OSD_SYSTEMID_LEN];
+};
+
+typedef u64 __bitwise osd_id;
+
+struct osd_obj_id {
+	osd_id partition;
+	osd_id id;
+};
+
+static const struct __weak osd_obj_id osd_root_object = {0, 0};
+
+struct osd_attr {
+	u32 page;
+	u32 attr_id;
+	u16 len;		/* byte count of operand */
+	void *val_ptr;		/* in network order */
+};
+
+#endif /* ndef __OSD_TYPES_H__ */
-- 
1.6.0.1



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 03/18 ver3] libosd: OSDv1 Headers
@ 2008-11-12 13:13           ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-12 13:13 UTC (permalink / raw)
  To: Randy Dunlap, James Bottomley
  Cc: Andrew Morton, Jörn Engel, open-osd development,
	Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-scsi,
	Sami.Iren, linux-kernel


Headers only patch.

osd_protocol.h
	Contains a C-fied definition of the T10 OSD standard
osd_types.h
	Contains CPU order common used types
osd_initiator.h
	API definition of the osd_initiator library
osd_sec.h
	Contains High level API for the security manager.

[Note that checkpatch spews errors on things that are valid in this context
and will not be fixed]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
 include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_sec.h       |   45 ++++
 include/scsi/osd_types.h     |   40 ++++
 4 files changed, 914 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_initiator.h
 create mode 100644 include/scsi/osd_protocol.h
 create mode 100644 include/scsi/osd_sec.h
 create mode 100644 include/scsi/osd_types.h

diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
new file mode 100644
index 0000000..1d92247
--- /dev/null
+++ b/include/scsi/osd_initiator.h
@@ -0,0 +1,332 @@
+/*
+ * osd_initiator.h - OSD initiator API definition
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_INITIATOR_H__
+#define __OSD_INITIATOR_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+#include <linux/blkdev.h>
+
+/* Note: "NI" in comments below means "Not Implemented yet" */
+
+/*
+ * Object-based Storage Device.
+ * This object represents an OSD device.
+ * It is not a full linux device in any way. It is only
+ * a place to hang resources associated with a Linux
+ * request Q and some default properties.
+ */
+struct osd_dev {
+	struct scsi_device *scsi_device;
+	unsigned def_timeout;
+};
+
+void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
+void osd_dev_fini(struct osd_dev *od);
+
+struct osd_request;
+typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
+
+struct osd_request {
+	struct osd_cdb cdb;
+	struct osd_data_out_integrity_info out_data_integ;
+	struct osd_data_in_integrity_info in_data_integ;
+
+	struct osd_dev *osd_dev;
+	struct request *request;
+
+	struct _osd_req_data_segment {
+		void *buff;
+		unsigned alloc_size; /* 0 here means: don't call kfree */
+		unsigned total_bytes;
+	} set_attr, enc_get_attr, get_attr;
+
+	struct _osd_io_info {
+		struct bio *bio;
+		u64 total_bytes;
+		struct request *req;
+		struct _osd_req_data_segment *last_seg;
+		u8 *pad_buff;
+	} out, in;
+
+	gfp_t alloc_flags;
+	unsigned timeout;
+	unsigned retries;
+	u8 sense[OSD_MAX_SENSE_LEN];
+	enum osd_attributes_mode attributes_mode;
+
+	osd_req_done_fn *async_done;
+	void *async_private;
+	int async_error;
+};
+
+/*
+ * How to use the osd library:
+ *
+ * osd_start_request
+ *	Allocates a request.
+ *
+ * osd_req_*
+ *	Call one of, to encode the desired operation.
+ *
+ * osd_add_{get,set}_attr
+ *	Optionally add attributes to the CDB, list or page mode.
+ *
+ * osd_finalize_request
+ *	Computes final data out/in offsets and signs the request,
+ *	making it ready for execution.
+ *
+ * osd_execute_request
+ *	May be called to execute it through the block layer. Other wise submit
+ *	the associated block request in some other way.
+ *
+ * After execution:
+ * osd_req_decode_sense
+ *	Decodes sense information to verify execution results.
+ *
+ * osd_req_decode_get_attr
+ *	Retrieve osd_add_get_attr_list() values if used.
+ *
+ * osd_end_request
+ *	Must be called to deallocate the request.
+ */
+
+/**
+ * osd_start_request - Allocate and initialize an osd_request
+ *
+ * @osd_dev:    OSD device that holds the scsi-device and default values
+ *              that the request is associated with.
+ * @gfp:        The allocation flags to use for request allocation, and all
+ *              subsequent allocations. This will be stored at
+ *              osd_request->alloc_flags, can be changed by user later
+ *
+ * Allocate osd_request and initialize all members to the
+ * default/initial state.
+ */
+struct osd_request *osd_start_request(struct osd_dev *od, gfp_t gfp);
+
+enum osd_req_options {
+	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
+	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
+
+	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
+};
+
+/**
+ * osd_finalize_request - Sign request and prepare request for execution
+ *
+ * @or:		osd_request to prepare
+ * @options:	combination of osd_req_options bit flags or 0.
+ * @cap:	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
+ *              The security manager as capabilities for this cdb.
+ * @cap_key:	The cryptographic key used to sign the cdb/data. Can be null
+ *              if NOSEC is used.
+ *
+ * The actual request and bios are only allocated here, so are the get_attr
+ * buffers that will receive the returned attributes. Copy's @cap to cdb.
+ * Sign the cdb/data with @cap_key.
+ */
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key);
+
+/**
+ * osd_execute_request - Execute the request synchronously through block-layer
+ *
+ * @or:		osd_request to Executed
+ *
+ * Calls blk_execute_rq to q the command and waits for completion.
+ */
+int osd_execute_request(struct osd_request *or);
+
+/**
+ * osd_execute_request_async - Execute the request without waitting.
+ *
+ * @or:                      - osd_request to Executed
+ * @done: (Optional)         - Called at end of execution
+ * @private:                 - Will be passed to @done function
+ *
+ * Calls blk_execute_rq_nowait to queue the command. When execution is done
+ * optionally calls @done with @private as parameter. @or->async_error will
+ * have the return code
+ */
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private);
+
+/**
+ * osd_end_request - return osd_request to free store
+ *
+ * @or:		osd_request to free
+ *
+ * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
+ */
+void osd_end_request(struct osd_request *or);
+
+/*
+ * CDB Encoding
+ *
+ * Note: call only one of the following methods.
+ */
+
+/*
+ * Device commands
+ */
+void osd_req_set_master_seed_xchg(struct osd_request *or, ...);/* NI */
+void osd_req_set_master_key(struct osd_request *or, ...);/* NI */
+
+void osd_req_format(struct osd_request *or, u64 tot_capacity);
+
+/* list all partitions
+ * @list header must be initialized to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values);
+
+void osd_req_perform_scsi_command(struct osd_request *or,
+	const u8 *cdb, ...);/* NI */
+void osd_req_task_management(struct osd_request *or, ...);/* NI */
+
+/*
+ * Partition commands
+ */
+void osd_req_create_partition(struct osd_request *or, osd_id partition);
+void osd_req_remove_partition(struct osd_request *or, osd_id partition);
+
+void osd_req_set_partition_key(struct osd_request *or,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
+
+/* list all collections in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+/* list all objects in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values);
+
+/*
+ * Collection commands
+ */
+void osd_req_create_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+void osd_req_remove_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+
+/* list all objects in the collection */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem);
+
+/* V2 only filtered list of objects in the collection */
+void osd_req_query(struct osd_request *or, ...);/* NI */
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values);
+
+void osd_req_get_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+void osd_req_set_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *);
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);
+void osd_req_append(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out);/* NI */
+void osd_req_create_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
+void osd_req_clear(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
+void osd_req_punch(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
+
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values,
+	/*V2*/ u64 offset, /*V2*/ u64 len);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_in, u64 offset);
+
+/*
+ * Root/Partition/Collection/Object Attributes commands
+ */
+
+/* get before set */
+void osd_req_get_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/* set before get */
+void osd_req_set_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/*
+ * Attributes appended to most commands
+ */
+
+/* Attributes List mode (or V2 CDB) */
+  /*
+   * TODO: In ver2 if at finalize time only one attr was set and no gets,
+   * then the Attributes CDB mode is used automatically to save IO.
+   */
+
+/* set a list of attributes. */
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/* get a list of attributes */
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/*
+ * Attributes list decoding
+ * Must be called after osd_request.request was executed
+ * It is called in a loop to decode the returned get_attr
+ * (see osd_add_get_attr)
+ */
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *, int *nelem, void **iterator);
+
+/* Attributes Page mode */
+
+/*
+ * Read an attribute page and optionally set one attribute
+ *
+ * Retrieves the attribute page directly to a user buffer.
+ * @attr_page_data shall stay valid until end of execution.
+ * See osd_attributes.h for common page structures
+ */
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attr_page_data, unsigned max_page_len,
+	const struct osd_attr *set_one);
+
+#endif /* __OSD_LIB_H__ */
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
new file mode 100644
index 0000000..ce678c5
--- /dev/null
+++ b/include/scsi/osd_protocol.h
@@ -0,0 +1,497 @@
+/*
+ * osd_protocol.h - OSD T10 standard C definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_PROTOCOL_H__
+#define __OSD_PROTOCOL_H__
+
+#include <linux/types.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+enum {
+	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
+	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
+	OSDv1_CAP_LEN = 80,
+	/* Latest supported version */
+	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
+	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
+	OSD_CAP_LEN = OSDv1_CAP_LEN,
+
+	OSD_SYSTEMID_LEN = 20,
+	OSD_CRYPTO_KEYID_SIZE = 20,
+	OSD_CRYPTO_SEED_SIZE = 4,
+	OSD_CRYPTO_NONCE_SIZE = 12,
+	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
+
+	OSD_PARTITION_FIRST_ID = 0x10000,
+	OSD_OBJECT_FIRST_ID = 0x10000,
+};
+
+/* (osd-r10 5.2.4)
+ * osd2r03: 5.2.3 Caching control bits
+ */
+enum osd_options_byte {
+	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
+	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
+};
+
+/*
+ * osd2r03: 5.2.5 Isolation.
+ * First 3 bits, V2-only.
+ * Also for attr 110h "default isolation method" at Root Information page
+ */
+enum osd_options_byte_isolation {
+	OSD_ISOLATION_DEFAULT = 0,
+	OSD_ISOLATION_NONE = 1,
+	OSD_ISOLATION_STRICT = 2,
+	OSD_ISOLATION_RANGE = 4,
+	OSD_ISOLATION_FUNCTIONAL = 5,
+	OSD_ISOLATION_VENDOR = 7,
+};
+
+/* (osd-r10: 6.7)
+ * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
+ */
+enum osd_options_flush_scope_values {
+	OSD_CDB_FLUSH_ALL = 0,
+	OSD_CDB_FLUSH_ATTR_ONLY = 1,
+
+	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
+	/* V2-only */
+	OSD_CDB_FLUSH_ALL_RANGE = 2,
+};
+
+/* osd2r03: 5.2.10 Timestamps control */
+enum {
+	OSD_CDB_NORMAL_TIMESTAMPS = 0,
+	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
+};
+
+/* (osd-r10: 5.2.2.1)
+ * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
+ *	2 bits at second nibble of command_specific_options byte
+ */
+enum osd_attributes_mode {
+	/* V2-only */
+	OSD_CDB_SET_ONE_ATTR = 0x10,
+
+	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
+	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
+
+	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
+};
+
+/* (osd-r10: 4.12.5)
+ * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
+ *	byte offset = mantissa * (2^(exponent+8))
+ *	struct {
+ *		unsigned mantissa: 28;
+ *		int exponent: 04;
+ *	}
+ */
+typedef __be32 __bitwise osd_cdb_offset;
+
+enum {
+	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
+	OSD_OFFSET_MAX_BITS = 28,
+
+	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MAX_SHIFT = 16,
+};
+
+/* Return the smallest allowed encoded offset that contains @offset.
+ *
+ * The actual encoded offset returned is @offset + *padding.
+ * (up to max_shift, non-inclusive)
+ */
+osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
+	int min_shift, int max_shift);
+
+/* Minimum alignment is 256 bytes
+ * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
+ * which is 8 to 23 but IBM code restricts it to 16, so be it.
+ */
+static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
+/* osd2r03: 5.2.1 Overview */
+struct osd_cdb_head {
+	struct scsi_varlen_cdb_hdr varlen_cdb;
+/*10*/	u8		options;
+	u8		command_specific_options;
+	u8		timestamp_control;
+/*13*/	u8		reserved1[3];
+/*16*/	__be64		partition;
+/*24*/	__be64		object;
+/*32*/	union { /* V1 vs V2 alignment differences */
+		struct __osdv1_cdb_addr_len {
+/*32*/			__be32 		list_identifier;/* Rarely used */
+/*36*/			__be64		length;
+/*44*/			__be64		start_address;
+		} __packed v1;
+	};
+/*52*/	union { /* selected attributes mode Page/List/Single */
+		struct osd_attributes_page_mode {
+/*52*/			__be32		get_attr_page;
+/*56*/			__be32		get_attr_alloc_length;
+/*60*/			osd_cdb_offset	get_attr_offset;
+
+/*64*/			__be32		set_attr_page;
+/*68*/			__be32		set_attr_id;
+/*72*/			__be32		set_attr_length;
+/*76*/			osd_cdb_offset	set_attr_offset;
+		} __packed attrs_page;
+
+		struct osd_attributes_list_mode {
+/*52*/			__be32		get_attr_desc_bytes;
+/*56*/			osd_cdb_offset	get_attr_desc_offset;
+
+/*60*/			__be32		get_attr_alloc_length;
+/*64*/			osd_cdb_offset	get_attr_offset;
+
+/*68*/			__be32		set_attr_bytes;
+/*72*/			osd_cdb_offset	set_attr_offset;
+			__be32 not_used;
+		} __packed attrs_list;
+
+		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
+		struct osd_attributes_cdb_mode {
+/*52*/			__be32		set_attr_page;
+/*56*/			__be32		set_attr_id;
+/*60*/			__be16		set_attr_len;
+/*62*/			u8		set_attr_val[80-62];
+		} __packed attrs_cdb;
+/*52*/		u8 get_set_attributes_parameters[80-52];
+	};
+} __packed;
+/*80*/
+
+/*160 v1*/
+struct osd_security_parameters {
+/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*192*/osd_cdb_offset	data_in_integrity_check_offset;
+/*196*/osd_cdb_offset	data_out_integrity_check_offset;
+} __packed;
+/*200 v1*/
+
+struct osdv1_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSDv1_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
+struct osd_cdb {
+	union {
+		struct osdv1_cdb v1;
+		u8 buff[OSD_TOTAL_CDB_LEN];
+	};
+} __packed;
+
+static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
+{
+	return (struct osd_cdb_head *)ocdb->buff;
+}
+
+/* define both version actions
+ * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
+ */
+#define OSD_ACT___(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
+
+/* V2 only actions */
+#define OSD_ACT_V2(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
+
+#define OSD_ACT_V1_V2(Name, Num1, Num2) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
+
+enum osd_service_actions {
+	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
+	OSD_ACT___(FORMAT_OSD,			0x01)
+	OSD_ACT___(CREATE,			0x02)
+	OSD_ACT___(LIST,			0x03)
+	OSD_ACT_V2(PUNCH,			0x04)
+	OSD_ACT___(READ,			0x05)
+	OSD_ACT___(WRITE,			0x06)
+	OSD_ACT___(APPEND,			0x07)
+	OSD_ACT___(FLUSH,			0x08)
+	OSD_ACT_V2(CLEAR,			0x09)
+	OSD_ACT___(REMOVE,			0x0A)
+	OSD_ACT___(CREATE_PARTITION,		0x0B)
+	OSD_ACT___(REMOVE_PARTITION,		0x0C)
+	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
+	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
+	OSD_ACT___(CREATE_AND_WRITE,		0x12)
+	OSD_ACT___(CREATE_COLLECTION,		0x15)
+	OSD_ACT___(REMOVE_COLLECTION,		0x16)
+	OSD_ACT___(LIST_COLLECTION,		0x17)
+	OSD_ACT___(SET_KEY,			0x18)
+	OSD_ACT___(SET_MASTER_KEY,		0x19)
+	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
+	OSD_ACT___(FLUSH_PARTITION,		0x1B)
+	OSD_ACT___(FLUSH_OSD,			0x1C)
+
+	OSD_ACT_V2(QUERY,			0x20)
+	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
+	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
+	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
+	OSD_ACT_V2(READ_MAP,			0x31)
+
+	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
+	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
+	/* 0x8F80 to 0x8FFF are Vendor specific */
+};
+
+/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
+struct osd_attributes_list_attrid {
+	__be32 page;
+	__be32 attr_id;
+} __packed;
+
+/*
+ * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
+ *                  for setting attributes
+ */
+struct osd_attributes_list_element {
+	__be32 page;
+	__be32 attr_id;
+	__be16 attr_bytes;
+	u8 attr_val[0];
+} __packed;
+
+enum {
+	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+};
+
+enum {
+	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
+	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
+};
+
+static inline unsigned osdv1_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
+}
+
+/*
+ * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
+ */
+enum osd_attr_list_types {
+	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
+	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
+	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
+	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
+};
+
+/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
+struct osd_attributes_list_multi_header {
+	__be64 object_id;
+	u8 object_type; /* object_type enum below */
+	u8 reserved[5];
+	__be16 list_bytes;
+	/* followed by struct osd_attributes_list_element's */
+};
+
+struct osdv1_attributes_list_header {
+	u8 type;	/* low 4-bit only */
+	u8 pad;
+	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
+{
+	return be16_to_cpu(h->list_bytes);
+}
+
+/* (osd-r10 6.13)
+ * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
+ *	for root_lstchg below
+ */
+enum {
+	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
+	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
+};
+
+/*
+ * osd2r03: 6.15.2 LIST command parameter data
+ * (Also for LIST COLLECTION)
+ */
+struct osd_obj_id_list {
+	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
+	__be64 continuation_id;
+	__be32 list_identifier;
+	u8 pad[3];
+	u8 root_lstchg;
+	__be64 object_ids[0];
+} __packed;
+
+static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
+	bool *is_changed)
+{
+	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
+	return 0 != list->continuation_id;
+}
+
+/*
+ * osd2r03: 4.12.4.5 The ALLDATA security method
+ */
+struct osd_data_out_integrity_info {
+	__be64 data_bytes;
+	__be64 set_attributes_bytes;
+	__be64 get_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_data_in_integrity_info {
+	__be64 data_bytes;
+	__be64 retrieved_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_timestamp {
+	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
+} __packed;
+/* FIXME: define helper functions to convert to/from osd time format */
+
+/*
+ * Capability & Security definitions
+ * osd2r03: 4.11.2.2 Capability format
+ * osd2r03: 5.2.8 Security parameters
+ */
+
+struct osd_key_identifier {
+	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+} __packed;
+
+/* for osd_capability.format */
+enum {
+	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
+	OSD_SEC_CAP_FORMAT_VER1 = 1,
+	OSD_SEC_CAP_FORMAT_VER2 = 2,
+};
+
+/* security_method */
+enum {
+	OSD_SEC_NOSEC = 0,
+	OSD_SEC_CAPKEY = 1,
+	OSD_SEC_CMDRSP = 2,
+	OSD_SEC_ALLDATA = 3,
+};
+
+enum object_type {
+	OSD_SEC_OBJ_ROOT = 0x1,
+	OSD_SEC_OBJ_PARTITION = 0x2,
+	OSD_SEC_OBJ_COLLECTION = 0x40,
+	OSD_SEC_OBJ_USER = 0x80,
+};
+
+enum osd_capability_bit_masks {
+	OSD_SEC_CAP_APPEND	= BIT(0),
+	OSD_SEC_CAP_OBJ_MGMT	= BIT(1),
+	OSD_SEC_CAP_REMOVE	= BIT(2),
+	OSD_SEC_CAP_CREATE	= BIT(3),
+	OSD_SEC_CAP_SET_ATTR	= BIT(4),
+	OSD_SEC_CAP_GET_ATTR	= BIT(5),
+	OSD_SEC_CAP_WRITE	= BIT(6),
+	OSD_SEC_CAP_READ	= BIT(7),
+
+	OSD_SEC_CAP_NONE1	= BIT(8),
+	OSD_SEC_CAP_NONE2	= BIT(9),
+	OSD_SEC_CAP_NONE3	= BIT(10),
+	OSD_SEC_CAP_QUERY	= BIT(11), /*v2 only*/
+	OSD_SEC_CAP_M_OBJECT	= BIT(12), /*v2 only*/
+	OSD_SEC_CAP_POL_SEC	= BIT(13),
+	OSD_SEC_CAP_GLOBAL	= BIT(14),
+	OSD_SEC_CAP_DEV_MGMT	= BIT(15),
+};
+
+/* for object_descriptor_type (hi nibble used) */
+enum {
+	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
+	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
+	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
+	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
+};
+
+/* (osd-r10:4.9.2.2)
+ * osd2r03:4.11.2.2 Capability format
+ */
+struct osd_capability_head {
+	u8 format; /* low nibble */
+	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
+	u8 security_method;
+	u8 reserved1;
+/*04*/	struct osd_timestamp expiration_time;
+/*10*/	u8 audit[30-10];
+/*30*/	u8 discriminator[42-30];
+/*42*/	struct osd_timestamp object_created_time;
+/*48*/	u8 object_type;
+	u8 permissions_bit_mask[54-49];
+/*54*/	u8 reserved2;
+/*55*/	u8 object_descriptor_type; /* high nibble */
+} __packed;
+
+/*56 v1*/
+struct osdv1_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 policy_access_tag;
+/*60*/			__be64 allowed_partition_id;
+/*68*/			__be64 allowed_object_id;
+/*76*/			__be32 reserved;
+		} __packed obj_desc;
+
+		u8 object_descriptor[80-56];/*24*/
+	};
+} __packed;
+/*80 v1*/
+
+struct osd_capability {
+	struct osd_capability_head h;
+	struct osdv1_cap_object_descriptor od;
+} __packed;
+
+/**
+ * osd_sec_set_caps - set cap-bits into the capabilities header
+ *
+ * @cap:	The osd_capability_head to set cap bits to.
+ * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
+ *
+ * permissions_bit_mask is unaligned use below to set into caps
+ * in a version independent way
+ */
+static inline void osd_sec_set_caps(struct osd_capability_head *cap,
+	u16 bit_mask)
+{
+	/*
+	 *Note: The bits above are defined LE order this is because this way
+	 *      they can grow in the future to more then 16, and still retain
+	 *      there constant values.
+	 */
+	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
+}
+
+#endif /* ndef __OSD_PROTOCOL_H__ */
diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h
new file mode 100644
index 0000000..4c09fee
--- /dev/null
+++ b/include/scsi/osd_sec.h
@@ -0,0 +1,45 @@
+/*
+ * osd_sec.h - OSD security manager API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_SEC_H__
+#define __OSD_SEC_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/*
+ * Contains types and constants of osd capabilities and security
+ * encoding/decoding.
+ * API is trying to keep security abstract so initiator of an object
+ * based pNFS client knows as little as possible about security and
+ * capabilities. It is the Server's osd-initiator place to know more.
+ * Also can be used by osd-target.
+ */
+void osd_sec_encode_caps(void *caps, ...);/* NI */
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1);
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_params);
+
+/* Conditionally sign the CDB according to security setting in ocdb
+ * with cap_key */
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key);
+
+/* Unconditionally sign the BIO data with cap_key.
+ * Check for osd_is_sec_alldata() was done prior to calling this. */
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key);
+
+/* Version independent copy of caps into the cdb */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps);
+
+#endif /* ndef __OSD_SEC_H__ */
diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h
new file mode 100644
index 0000000..ea5372d
--- /dev/null
+++ b/include/scsi/osd_types.h
@@ -0,0 +1,40 @@
+/*
+ * osd_types.h - Types and constants which are not part of the protocol.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Contains types and constants that are implementation specific and are
+ * used by more than one part of the osd library.
+ *     (Eg initiator/target/security_manager/...)
+ */
+#ifndef __OSD_TYPES_H__
+#define __OSD_TYPES_H__
+
+struct osd_systemid {
+	u8 data[OSD_SYSTEMID_LEN];
+};
+
+typedef u64 __bitwise osd_id;
+
+struct osd_obj_id {
+	osd_id partition;
+	osd_id id;
+};
+
+static const struct __weak osd_obj_id osd_root_object = {0, 0};
+
+struct osd_attr {
+	u32 page;
+	u32 attr_id;
+	u16 len;		/* byte count of operand */
+	void *val_ptr;		/* in network order */
+};
+
+#endif /* ndef __OSD_TYPES_H__ */
-- 
1.6.0.1


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver2] libosd: OSDv1 Headers
  2008-11-12 13:10           ` Boaz Harrosh
  (?)
@ 2008-11-12 16:48           ` Randy Dunlap
  2008-11-12 17:09             ` Boaz Harrosh
  2008-11-12 17:15             ` Johannes Berg
  -1 siblings, 2 replies; 183+ messages in thread
From: Randy Dunlap @ 2008-11-12 16:48 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James Bottomley, Andrew Morton, Jörn Engel,
	open-osd development, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, linux-scsi, Sami.Iren, linux-kernel, johannes

Boaz Harrosh wrote:
> 
> Thank you Randy for your review, I will post a fixed
> patch shortly. I have changed according to your comments
> except in one place, see arguments below.
> 
>>> ---
>>>  include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
>>>  include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
>>>  include/scsi/osd_sec.h       |   45 ++++
>>>  include/scsi/osd_types.h     |   40 ++++
>>>  4 files changed, 914 insertions(+), 0 deletions(-)
>>>  create mode 100644 include/scsi/osd_initiator.h
>>>  create mode 100644 include/scsi/osd_protocol.h
>>>  create mode 100644 include/scsi/osd_sec.h
>>>  create mode 100644 include/scsi/osd_types.h

>>> +/**
>> Don't start comment blocks with /** when they are not kernel-doc,
>> like this one is not.
>>
> 
> OK, I must confess my kernel-doc total ignorance. I was imagining that
> each source file's kernel-doc comments are collected into an html file.
> I thought that this comment will be like an introduction to the following
> function-by-function reference. Anyway it's fixed

You can choose to have comments included in the kernel-doc's collected
output.  You do this by using this notation:

/** DOC <topic_name>:
 * <these lines are added to kernel-doc output when you use:
!P<filename> <topic_name>
 * a Documentation/DocBook/*.tmpl file.
 */

See Documentation/DocBook/mac80211.tmpl for examples.

Johannes, I thought that you had some usage documentation for DOC:.
Did you not or did it not get merged??
It needs to be added to Documentation/kernel-doc-nano-HOWTO.txt.


>>> + * How to use the osd library:
>>> + *
>>> + * osd_start_request
>>> + *	Allocates a request.
>>> + *
>>> + * osd_req_*
>>> + *	Call one of, to encode the desired operation.
>>> + *
>>> + * osd_add_{get,set}_attr
>>> + *	Optionally add attributes to the CDB, list or page mode.
>>> + *
>>> + * osd_finalize_request
>>> + *	Computes final data out/in offsets and signs the request,
>>> + *	making it ready for execution.
>>> + *
>>> + * osd_execute_request
>>> + *	May be called to execute it through the block layer. Other wise submit
>>> + *	the associated block request in some other way.
>>> + *
>>> + * After execution:
>>> + * osd_req_decode_sense
>>> + *	Decodes sense information to verify execution results.
>>> + *
>>> + * osd_req_decode_get_attr
>>> + *	Retrieve osd_add_get_attr_list() values if used.
>>> + *
>>> + * osd_end_request
>>> + *	Must be called to deallocate the request.
>>> + */

>>> +int osd_finalize_request(struct osd_request *or,
>>> +	u8 options, const void *cap, const u8 *cap_key);
>>> +
>>> +/**
>>> + * osd_execute_request - Execute the request synchronously through
>>> + *                       the block-layer
>> Function name and short description need to be on one line.
>>
> 
> OK I re-worded so it will fit in one line. What happens if it does not
> fit, both name and description, in 80 characters? is there a continuation
> symbol or something?

Nope.  It can (a) be longer than 80 characters (an exception is made here)
or (b) split up like this:

/**
 * func_name - some short description here
 * @prm1: prm1 description
 * @prmn: prmn description
 *
 * <longer function description here>
 */

>>> + * @or:		osd_request to Executed
>>> + *
>>> + * Calls blk_execute_rq to q the command and waits for completion.
>>> + */
>>> +int osd_execute_request(struct osd_request *or);

>>> diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
>>> new file mode 100644
>>> index 0000000..77a74a3
>>> --- /dev/null
>>> +++ b/include/scsi/osd_protocol.h
>>> @@ -0,0 +1,497 @@
>>> +/*
>>> + * osd_protocol.h - OSD T10 standard C definitions.
>>> + *
>>> + * Copyright (C) 2008 Panasas Inc.  All rights reserved.
>>> + *
>>> + * Authors:
>>> + *   Boaz Harrosh <bharrosh@panasas.com>
>>> + *   Benny Halevy <bhalevy@panasas.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2
>>> + *
>>> + * This file contains types and constants that are defined by the protocol
>>> + * Note: All names and symbols are taken from the OSD standard's text.
>>> + */
>>> +#ifndef __OSD_PROTOCOL_H__
>>> +#define __OSD_PROTOCOL_H__
>>> +
>>> +#include <linux/types.h>
>>> +#include <asm/unaligned.h>
>>> +#include <scsi/scsi.h>

...

>>> +/* (osd-r10:4.9.2.2)
>>> + * osd2r03:4.11.2.2 Capability format
>>> + */
>>> +struct osd_capability_head {
>>> +	u8 format; /* low nibble */
>>> +	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
>>> +	u8 security_method;
>>> +	u8 reserved1;
>>> +/*04*/	struct osd_timestamp expiration_time;
>>> +/*10*/	u8 audit[30-10];
>>> +/*30*/	u8 discriminator[42-30];
>>> +/*42*/	struct osd_timestamp object_created_time;
>>> +/*48*/	u8 object_type;
>>> +	u8 permissions_bit_mask[54-49];
>> The offset comments are OK with me, but please lose the [b-a] length specifiers.
>>
> 
> I would, please, like to keep them. For the user it does not matter.
> Because he is not suppose to care if he is doing:
> -	memset(och->permissions_bit_mask, 0, 5); // BAD
> +	memset(och->permissions_bit_mask, 0, sizeof(och->permissions_bit_mask)); // GOOD
> 
> But for the protocol reader / debuggerer this is much easier since this is the
> way he will see them on the wire and the way it is laid out in the standard text.
> 
> It was much easier to read the standard text and develop the header this way, complicated
> by the fact that OSD v2 was a moving target and the changes from OSD v1. And it helped in
> finding bugs. Now to go over all of them and calculate the difference and remove it. I'm
> loosing information, and I feel sad to loose it.
> 
> But if you are totally not convinced I will remove them?

I've debugged plenty of code so I'll respectfully disagree with you.
It's confusing and ugly.  But I don't control whether it is merged upstream
or not.

>>> +/*54*/	u8 reserved2;
>>> +/*55*/	u8 object_descriptor_type; /* high nibble */
>>> +} __packed;

-- 
~Randy

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver2] libosd: OSDv1 Headers
  2008-11-12 16:48           ` Randy Dunlap
@ 2008-11-12 17:09             ` Boaz Harrosh
  2008-11-12 17:15             ` Johannes Berg
  1 sibling, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-12 17:09 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: James Bottomley, Andrew Morton, Jörn Engel,
	open-osd development, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, linux-scsi, Sami.Iren, linux-kernel, johannes

Randy Dunlap wrote:
> Boaz Harrosh wrote:
>> Thank you Randy for your review, I will post a fixed
>> patch shortly. I have changed according to your comments
>> except in one place, see arguments below.
>>
>>>> ---
>>>>  include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
>>>>  include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
>>>>  include/scsi/osd_sec.h       |   45 ++++
>>>>  include/scsi/osd_types.h     |   40 ++++
>>>>  4 files changed, 914 insertions(+), 0 deletions(-)
>>>>  create mode 100644 include/scsi/osd_initiator.h
>>>>  create mode 100644 include/scsi/osd_protocol.h
>>>>  create mode 100644 include/scsi/osd_sec.h
>>>>  create mode 100644 include/scsi/osd_types.h
> 
>>>> +/**
>>> Don't start comment blocks with /** when they are not kernel-doc,
>>> like this one is not.
>>>
>> OK, I must confess my kernel-doc total ignorance. I was imagining that
>> each source file's kernel-doc comments are collected into an html file.
>> I thought that this comment will be like an introduction to the following
>> function-by-function reference. Anyway it's fixed
> 
> You can choose to have comments included in the kernel-doc's collected
> output.  You do this by using this notation:
> 
> /** DOC <topic_name>:
>  * <these lines are added to kernel-doc output when you use:
> !P<filename> <topic_name>
>  * a Documentation/DocBook/*.tmpl file.
>  */
> 
> See Documentation/DocBook/mac80211.tmpl for examples.
> 
> Johannes, I thought that you had some usage documentation for DOC:.
> Did you not or did it not get merged??
> It needs to be added to Documentation/kernel-doc-nano-HOWTO.txt.
> 

OK Thanks I'll give it a shot

<snip> 
>>>> +/**
>>>> + * osd_execute_request - Execute the request synchronously through
>>>> + *                       the block-layer
>>> Function name and short description need to be on one line.
>>>
>> OK I re-worded so it will fit in one line. What happens if it does not
>> fit, both name and description, in 80 characters? is there a continuation
>> symbol or something?
> 
> Nope.  It can (a) be longer than 80 characters (an exception is made here)
> or (b) split up like this:
> 
> /**
>  * func_name - some short description here
>  * @prm1: prm1 description
>  * @prmn: prmn description
>  *
>  * <longer function description here>
>  */
> 

OK So I guess I took (b). Thanks.

<snip>
>>>> +/* (osd-r10:4.9.2.2)
>>>> + * osd2r03:4.11.2.2 Capability format
>>>> + */
>>>> +struct osd_capability_head {
>>>> +	u8 format; /* low nibble */
>>>> +	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
>>>> +	u8 security_method;
>>>> +	u8 reserved1;
>>>> +/*04*/	struct osd_timestamp expiration_time;
>>>> +/*10*/	u8 audit[30-10];
>>>> +/*30*/	u8 discriminator[42-30];
>>>> +/*42*/	struct osd_timestamp object_created_time;
>>>> +/*48*/	u8 object_type;
>>>> +	u8 permissions_bit_mask[54-49];
>>> The offset comments are OK with me, but please lose the [b-a] length specifiers.
>>>
>> I would, please, like to keep them. For the user it does not matter.
>> Because he is not suppose to care if he is doing:
>> -	memset(och->permissions_bit_mask, 0, 5); // BAD
>> +	memset(och->permissions_bit_mask, 0, sizeof(och->permissions_bit_mask)); // GOOD
>>
>> But for the protocol reader / debuggerer this is much easier since this is the
>> way he will see them on the wire and the way it is laid out in the standard text.
>>
>> It was much easier to read the standard text and develop the header this way, complicated
>> by the fact that OSD v2 was a moving target and the changes from OSD v1. And it helped in
>> finding bugs. Now to go over all of them and calculate the difference and remove it. I'm
>> loosing information, and I feel sad to loose it.
>>
>> But if you are totally not convinced I will remove them?
> 
> I've debugged plenty of code so I'll respectfully disagree with you.
> It's confusing and ugly.  But I don't control whether it is merged upstream
> or not.
> 

If it's "confusing and ugly" then that's bad. I guess I'm so much into the
standard-text, that I like it this way, but not so for an onlooker.
I'll change it. Last thing I want is ugly confusing code.

Thanks again
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver2] libosd: OSDv1 Headers
  2008-11-12 16:48           ` Randy Dunlap
  2008-11-12 17:09             ` Boaz Harrosh
@ 2008-11-12 17:15             ` Johannes Berg
  1 sibling, 0 replies; 183+ messages in thread
From: Johannes Berg @ 2008-11-12 17:15 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Boaz Harrosh, James Bottomley, Andrew Morton, Jörn Engel,
	open-osd development, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, linux-scsi, Sami.Iren, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 617 bytes --]

On Wed, 2008-11-12 at 08:48 -0800, Randy Dunlap wrote:

> /** DOC <topic_name>:
>  * <these lines are added to kernel-doc output when you use:
> !P<filename> <topic_name>
>  * a Documentation/DocBook/*.tmpl file.
>  */
> 
> See Documentation/DocBook/mac80211.tmpl for examples.
> 
> Johannes, I thought that you had some usage documentation for DOC:.
> Did you not or did it not get merged??
> It needs to be added to Documentation/kernel-doc-nano-HOWTO.txt.

I honestly don't remember! Grepping through all my old patches didn't
find anything though, so I suspect I didn't have anything.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver3] libosd: OSDv1 Headers
  2008-11-12 13:13           ` Boaz Harrosh
  (?)
@ 2008-11-12 18:59           ` Randy Dunlap
  2008-11-13  9:38             ` Boaz Harrosh
  2008-11-13 12:25               ` Boaz Harrosh
  -1 siblings, 2 replies; 183+ messages in thread
From: Randy Dunlap @ 2008-11-12 18:59 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James Bottomley, Andrew Morton, Jörn Engel,
	open-osd development, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, linux-scsi, Sami.Iren, linux-kernel

On Wed, 12 Nov 2008 15:13:59 +0200 Boaz Harrosh wrote:

> 
> Headers only patch.
> 
> osd_protocol.h
> 	Contains a C-fied definition of the T10 OSD standard
> osd_types.h
> 	Contains CPU order common used types
> osd_initiator.h
> 	API definition of the osd_initiator library
> osd_sec.h
> 	Contains High level API for the security manager.
> 
> [Note that checkpatch spews errors on things that are valid in this context
> and will not be fixed]
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> Reviewed-by: Benny Halevy <bhalevy@panasas.com>
> ---
>  include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
>  include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
>  include/scsi/osd_sec.h       |   45 ++++
>  include/scsi/osd_types.h     |   40 ++++
>  4 files changed, 914 insertions(+), 0 deletions(-)
>  create mode 100644 include/scsi/osd_initiator.h
>  create mode 100644 include/scsi/osd_protocol.h
>  create mode 100644 include/scsi/osd_sec.h
>  create mode 100644 include/scsi/osd_types.h

> diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
> new file mode 100644
> index 0000000..ce678c5
> --- /dev/null
> +++ b/include/scsi/osd_protocol.h
> @@ -0,0 +1,497 @@
> +#ifndef __OSD_PROTOCOL_H__
> +#define __OSD_PROTOCOL_H__

...

> +/* osd2r03: 5.2.1 Overview */
> +struct osd_cdb_head {
> +	struct scsi_varlen_cdb_hdr varlen_cdb;
> +/*10*/	u8		options;
> +	u8		command_specific_options;
> +	u8		timestamp_control;
> +/*13*/	u8		reserved1[3];
> +/*16*/	__be64		partition;
> +/*24*/	__be64		object;
> +/*32*/	union { /* V1 vs V2 alignment differences */
> +		struct __osdv1_cdb_addr_len {
> +/*32*/			__be32 		list_identifier;/* Rarely used */
> +/*36*/			__be64		length;
> +/*44*/			__be64		start_address;
> +		} __packed v1;
> +	};
> +/*52*/	union { /* selected attributes mode Page/List/Single */
> +		struct osd_attributes_page_mode {
> +/*52*/			__be32		get_attr_page;
> +/*56*/			__be32		get_attr_alloc_length;
> +/*60*/			osd_cdb_offset	get_attr_offset;
> +
> +/*64*/			__be32		set_attr_page;
> +/*68*/			__be32		set_attr_id;
> +/*72*/			__be32		set_attr_length;
> +/*76*/			osd_cdb_offset	set_attr_offset;
> +		} __packed attrs_page;
> +
> +		struct osd_attributes_list_mode {
> +/*52*/			__be32		get_attr_desc_bytes;
> +/*56*/			osd_cdb_offset	get_attr_desc_offset;
> +
> +/*60*/			__be32		get_attr_alloc_length;
> +/*64*/			osd_cdb_offset	get_attr_offset;
> +
> +/*68*/			__be32		set_attr_bytes;
> +/*72*/			osd_cdb_offset	set_attr_offset;
> +			__be32 not_used;
> +		} __packed attrs_list;
> +
> +		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
> +		struct osd_attributes_cdb_mode {
> +/*52*/			__be32		set_attr_page;
> +/*56*/			__be32		set_attr_id;
> +/*60*/			__be16		set_attr_len;
> +/*62*/			u8		set_attr_val[80-62];

ugh

> +		} __packed attrs_cdb;
> +/*52*/		u8 get_set_attributes_parameters[80-52];

ugh

> +	};
> +} __packed;
> +/*80*/


> +/* (osd-r10:4.9.2.2)
> + * osd2r03:4.11.2.2 Capability format
> + */
> +struct osd_capability_head {
> +	u8 format; /* low nibble */
> +	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
> +	u8 security_method;
> +	u8 reserved1;
> +/*04*/	struct osd_timestamp expiration_time;
> +/*10*/	u8 audit[30-10];
> +/*30*/	u8 discriminator[42-30];
> +/*42*/	struct osd_timestamp object_created_time;
> +/*48*/	u8 object_type;
> +	u8 permissions_bit_mask[54-49];

more of the same

> +/*54*/	u8 reserved2;
> +/*55*/	u8 object_descriptor_type; /* high nibble */
> +} __packed;
> +
> +/*56 v1*/
> +struct osdv1_cap_object_descriptor {
> +	union {
> +		struct {
> +/*56*/			__be32 policy_access_tag;
> +/*60*/			__be64 allowed_partition_id;
> +/*68*/			__be64 allowed_object_id;
> +/*76*/			__be32 reserved;
> +		} __packed obj_desc;
> +
> +		u8 object_descriptor[80-56];/*24*/

ditto.  nice comment ;)

> +	};
> +} __packed;
> +/*80 v1*/
> +
> +#endif /* ndef __OSD_PROTOCOL_H__ */


Thanks for the fixes.

---
~Randy

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver3] libosd: OSDv1 Headers
  2008-11-12 18:59           ` Randy Dunlap
@ 2008-11-13  9:38             ` Boaz Harrosh
  2008-11-13 12:25               ` Boaz Harrosh
  1 sibling, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-13  9:38 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: James Bottomley, Andrew Morton, Jörn Engel,
	open-osd development, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, linux-scsi, Sami.Iren, linux-kernel

Randy Dunlap wrote:
> 
> ugh
> 
>> +		} __packed attrs_cdb;
>> +/*52*/		u8 get_set_attributes_parameters[80-52];
> 
> ugh
> 
> 
> more of the same
> 
> 
> ditto.  nice comment ;)
> 
> 
> 
> Thanks for the fixes.
> 

Yes Yes that was version 3 where I was asking if I might convince you
for its merits.

As I said in that reply I will change it. Just did not have the chance
to send out version 4 out yet.

Thanks
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* [PATCH 03/18 ver4] libosd: OSDv1 Headers
  2008-11-12 18:59           ` Randy Dunlap
@ 2008-11-13 12:25               ` Boaz Harrosh
  2008-11-13 12:25               ` Boaz Harrosh
  1 sibling, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-13 12:25 UTC (permalink / raw)
  To: Randy Dunlap, James Bottomley
  Cc: Andrew Morton, Jörn Engel, open-osd development,
	Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-scsi,
	Sami.Iren, linux-kernel


Headers only patch.

osd_protocol.h
	Contains a C-fied definition of the T10 OSD standard
osd_types.h
	Contains CPU order common used types
osd_initiator.h
	API definition of the osd_initiator library
osd_sec.h
	Contains High level API for the security manager.

[Note that checkpatch spews errors on things that are valid in this context
and will not be fixed]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
 include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_sec.h       |   45 ++++
 include/scsi/osd_types.h     |   40 ++++
 4 files changed, 914 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_initiator.h
 create mode 100644 include/scsi/osd_protocol.h
 create mode 100644 include/scsi/osd_sec.h
 create mode 100644 include/scsi/osd_types.h

diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
new file mode 100644
index 0000000..1d92247
--- /dev/null
+++ b/include/scsi/osd_initiator.h
@@ -0,0 +1,332 @@
+/*
+ * osd_initiator.h - OSD initiator API definition
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_INITIATOR_H__
+#define __OSD_INITIATOR_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+#include <linux/blkdev.h>
+
+/* Note: "NI" in comments below means "Not Implemented yet" */
+
+/*
+ * Object-based Storage Device.
+ * This object represents an OSD device.
+ * It is not a full linux device in any way. It is only
+ * a place to hang resources associated with a Linux
+ * request Q and some default properties.
+ */
+struct osd_dev {
+	struct scsi_device *scsi_device;
+	unsigned def_timeout;
+};
+
+void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
+void osd_dev_fini(struct osd_dev *od);
+
+struct osd_request;
+typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
+
+struct osd_request {
+	struct osd_cdb cdb;
+	struct osd_data_out_integrity_info out_data_integ;
+	struct osd_data_in_integrity_info in_data_integ;
+
+	struct osd_dev *osd_dev;
+	struct request *request;
+
+	struct _osd_req_data_segment {
+		void *buff;
+		unsigned alloc_size; /* 0 here means: don't call kfree */
+		unsigned total_bytes;
+	} set_attr, enc_get_attr, get_attr;
+
+	struct _osd_io_info {
+		struct bio *bio;
+		u64 total_bytes;
+		struct request *req;
+		struct _osd_req_data_segment *last_seg;
+		u8 *pad_buff;
+	} out, in;
+
+	gfp_t alloc_flags;
+	unsigned timeout;
+	unsigned retries;
+	u8 sense[OSD_MAX_SENSE_LEN];
+	enum osd_attributes_mode attributes_mode;
+
+	osd_req_done_fn *async_done;
+	void *async_private;
+	int async_error;
+};
+
+/*
+ * How to use the osd library:
+ *
+ * osd_start_request
+ *	Allocates a request.
+ *
+ * osd_req_*
+ *	Call one of, to encode the desired operation.
+ *
+ * osd_add_{get,set}_attr
+ *	Optionally add attributes to the CDB, list or page mode.
+ *
+ * osd_finalize_request
+ *	Computes final data out/in offsets and signs the request,
+ *	making it ready for execution.
+ *
+ * osd_execute_request
+ *	May be called to execute it through the block layer. Other wise submit
+ *	the associated block request in some other way.
+ *
+ * After execution:
+ * osd_req_decode_sense
+ *	Decodes sense information to verify execution results.
+ *
+ * osd_req_decode_get_attr
+ *	Retrieve osd_add_get_attr_list() values if used.
+ *
+ * osd_end_request
+ *	Must be called to deallocate the request.
+ */
+
+/**
+ * osd_start_request - Allocate and initialize an osd_request
+ *
+ * @osd_dev:    OSD device that holds the scsi-device and default values
+ *              that the request is associated with.
+ * @gfp:        The allocation flags to use for request allocation, and all
+ *              subsequent allocations. This will be stored at
+ *              osd_request->alloc_flags, can be changed by user later
+ *
+ * Allocate osd_request and initialize all members to the
+ * default/initial state.
+ */
+struct osd_request *osd_start_request(struct osd_dev *od, gfp_t gfp);
+
+enum osd_req_options {
+	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
+	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
+
+	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
+};
+
+/**
+ * osd_finalize_request - Sign request and prepare request for execution
+ *
+ * @or:		osd_request to prepare
+ * @options:	combination of osd_req_options bit flags or 0.
+ * @cap:	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
+ *              The security manager as capabilities for this cdb.
+ * @cap_key:	The cryptographic key used to sign the cdb/data. Can be null
+ *              if NOSEC is used.
+ *
+ * The actual request and bios are only allocated here, so are the get_attr
+ * buffers that will receive the returned attributes. Copy's @cap to cdb.
+ * Sign the cdb/data with @cap_key.
+ */
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key);
+
+/**
+ * osd_execute_request - Execute the request synchronously through block-layer
+ *
+ * @or:		osd_request to Executed
+ *
+ * Calls blk_execute_rq to q the command and waits for completion.
+ */
+int osd_execute_request(struct osd_request *or);
+
+/**
+ * osd_execute_request_async - Execute the request without waitting.
+ *
+ * @or:                      - osd_request to Executed
+ * @done: (Optional)         - Called at end of execution
+ * @private:                 - Will be passed to @done function
+ *
+ * Calls blk_execute_rq_nowait to queue the command. When execution is done
+ * optionally calls @done with @private as parameter. @or->async_error will
+ * have the return code
+ */
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private);
+
+/**
+ * osd_end_request - return osd_request to free store
+ *
+ * @or:		osd_request to free
+ *
+ * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
+ */
+void osd_end_request(struct osd_request *or);
+
+/*
+ * CDB Encoding
+ *
+ * Note: call only one of the following methods.
+ */
+
+/*
+ * Device commands
+ */
+void osd_req_set_master_seed_xchg(struct osd_request *or, ...);/* NI */
+void osd_req_set_master_key(struct osd_request *or, ...);/* NI */
+
+void osd_req_format(struct osd_request *or, u64 tot_capacity);
+
+/* list all partitions
+ * @list header must be initialized to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values);
+
+void osd_req_perform_scsi_command(struct osd_request *or,
+	const u8 *cdb, ...);/* NI */
+void osd_req_task_management(struct osd_request *or, ...);/* NI */
+
+/*
+ * Partition commands
+ */
+void osd_req_create_partition(struct osd_request *or, osd_id partition);
+void osd_req_remove_partition(struct osd_request *or, osd_id partition);
+
+void osd_req_set_partition_key(struct osd_request *or,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
+
+/* list all collections in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+/* list all objects in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values);
+
+/*
+ * Collection commands
+ */
+void osd_req_create_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+void osd_req_remove_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+
+/* list all objects in the collection */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem);
+
+/* V2 only filtered list of objects in the collection */
+void osd_req_query(struct osd_request *or, ...);/* NI */
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values);
+
+void osd_req_get_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+void osd_req_set_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *);
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);
+void osd_req_append(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out);/* NI */
+void osd_req_create_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
+void osd_req_clear(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
+void osd_req_punch(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
+
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values,
+	/*V2*/ u64 offset, /*V2*/ u64 len);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_in, u64 offset);
+
+/*
+ * Root/Partition/Collection/Object Attributes commands
+ */
+
+/* get before set */
+void osd_req_get_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/* set before get */
+void osd_req_set_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/*
+ * Attributes appended to most commands
+ */
+
+/* Attributes List mode (or V2 CDB) */
+  /*
+   * TODO: In ver2 if at finalize time only one attr was set and no gets,
+   * then the Attributes CDB mode is used automatically to save IO.
+   */
+
+/* set a list of attributes. */
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/* get a list of attributes */
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/*
+ * Attributes list decoding
+ * Must be called after osd_request.request was executed
+ * It is called in a loop to decode the returned get_attr
+ * (see osd_add_get_attr)
+ */
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *, int *nelem, void **iterator);
+
+/* Attributes Page mode */
+
+/*
+ * Read an attribute page and optionally set one attribute
+ *
+ * Retrieves the attribute page directly to a user buffer.
+ * @attr_page_data shall stay valid until end of execution.
+ * See osd_attributes.h for common page structures
+ */
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attr_page_data, unsigned max_page_len,
+	const struct osd_attr *set_one);
+
+#endif /* __OSD_LIB_H__ */
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
new file mode 100644
index 0000000..eeb899b
--- /dev/null
+++ b/include/scsi/osd_protocol.h
@@ -0,0 +1,497 @@
+/*
+ * osd_protocol.h - OSD T10 standard C definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_PROTOCOL_H__
+#define __OSD_PROTOCOL_H__
+
+#include <linux/types.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+enum {
+	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
+	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
+	OSDv1_CAP_LEN = 80,
+	/* Latest supported version */
+	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
+	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
+	OSD_CAP_LEN = OSDv1_CAP_LEN,
+
+	OSD_SYSTEMID_LEN = 20,
+	OSD_CRYPTO_KEYID_SIZE = 20,
+	OSD_CRYPTO_SEED_SIZE = 4,
+	OSD_CRYPTO_NONCE_SIZE = 12,
+	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
+
+	OSD_PARTITION_FIRST_ID = 0x10000,
+	OSD_OBJECT_FIRST_ID = 0x10000,
+};
+
+/* (osd-r10 5.2.4)
+ * osd2r03: 5.2.3 Caching control bits
+ */
+enum osd_options_byte {
+	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
+	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
+};
+
+/*
+ * osd2r03: 5.2.5 Isolation.
+ * First 3 bits, V2-only.
+ * Also for attr 110h "default isolation method" at Root Information page
+ */
+enum osd_options_byte_isolation {
+	OSD_ISOLATION_DEFAULT = 0,
+	OSD_ISOLATION_NONE = 1,
+	OSD_ISOLATION_STRICT = 2,
+	OSD_ISOLATION_RANGE = 4,
+	OSD_ISOLATION_FUNCTIONAL = 5,
+	OSD_ISOLATION_VENDOR = 7,
+};
+
+/* (osd-r10: 6.7)
+ * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
+ */
+enum osd_options_flush_scope_values {
+	OSD_CDB_FLUSH_ALL = 0,
+	OSD_CDB_FLUSH_ATTR_ONLY = 1,
+
+	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
+	/* V2-only */
+	OSD_CDB_FLUSH_ALL_RANGE = 2,
+};
+
+/* osd2r03: 5.2.10 Timestamps control */
+enum {
+	OSD_CDB_NORMAL_TIMESTAMPS = 0,
+	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
+};
+
+/* (osd-r10: 5.2.2.1)
+ * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
+ *	2 bits at second nibble of command_specific_options byte
+ */
+enum osd_attributes_mode {
+	/* V2-only */
+	OSD_CDB_SET_ONE_ATTR = 0x10,
+
+	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
+	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
+
+	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
+};
+
+/* (osd-r10: 4.12.5)
+ * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
+ *	byte offset = mantissa * (2^(exponent+8))
+ *	struct {
+ *		unsigned mantissa: 28;
+ *		int exponent: 04;
+ *	}
+ */
+typedef __be32 __bitwise osd_cdb_offset;
+
+enum {
+	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
+	OSD_OFFSET_MAX_BITS = 28,
+
+	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MAX_SHIFT = 16,
+};
+
+/* Return the smallest allowed encoded offset that contains @offset.
+ *
+ * The actual encoded offset returned is @offset + *padding.
+ * (up to max_shift, non-inclusive)
+ */
+osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
+	int min_shift, int max_shift);
+
+/* Minimum alignment is 256 bytes
+ * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
+ * which is 8 to 23 but IBM code restricts it to 16, so be it.
+ */
+static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
+/* osd2r03: 5.2.1 Overview */
+struct osd_cdb_head {
+	struct scsi_varlen_cdb_hdr varlen_cdb;
+/*10*/	u8		options;
+	u8		command_specific_options;
+	u8		timestamp_control;
+/*13*/	u8		reserved1[3];
+/*16*/	__be64		partition;
+/*24*/	__be64		object;
+/*32*/	union { /* V1 vs V2 alignment differences */
+		struct __osdv1_cdb_addr_len {
+/*32*/			__be32 		list_identifier;/* Rarely used */
+/*36*/			__be64		length;
+/*44*/			__be64		start_address;
+		} __packed v1;
+	};
+/*52*/	union { /* selected attributes mode Page/List/Single */
+		struct osd_attributes_page_mode {
+/*52*/			__be32		get_attr_page;
+/*56*/			__be32		get_attr_alloc_length;
+/*60*/			osd_cdb_offset	get_attr_offset;
+
+/*64*/			__be32		set_attr_page;
+/*68*/			__be32		set_attr_id;
+/*72*/			__be32		set_attr_length;
+/*76*/			osd_cdb_offset	set_attr_offset;
+/*80*/		} __packed attrs_page;
+
+		struct osd_attributes_list_mode {
+/*52*/			__be32		get_attr_desc_bytes;
+/*56*/			osd_cdb_offset	get_attr_desc_offset;
+
+/*60*/			__be32		get_attr_alloc_length;
+/*64*/			osd_cdb_offset	get_attr_offset;
+
+/*68*/			__be32		set_attr_bytes;
+/*72*/			osd_cdb_offset	set_attr_offset;
+			__be32 not_used;
+/*80*/		} __packed attrs_list;
+
+		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
+		struct osd_attributes_cdb_mode {
+/*52*/			__be32		set_attr_page;
+/*56*/			__be32		set_attr_id;
+/*60*/			__be16		set_attr_len;
+/*62*/			u8		set_attr_val[18];
+/*80*/		} __packed attrs_cdb;
+/*52*/		u8 get_set_attributes_parameters[28];
+	};
+} __packed;
+/*80*/
+
+/*160 v1*/
+struct osd_security_parameters {
+/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*192*/osd_cdb_offset	data_in_integrity_check_offset;
+/*196*/osd_cdb_offset	data_out_integrity_check_offset;
+} __packed;
+/*200 v1*/
+
+struct osdv1_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSDv1_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
+struct osd_cdb {
+	union {
+		struct osdv1_cdb v1;
+		u8 buff[OSD_TOTAL_CDB_LEN];
+	};
+} __packed;
+
+static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
+{
+	return (struct osd_cdb_head *)ocdb->buff;
+}
+
+/* define both version actions
+ * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
+ */
+#define OSD_ACT___(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
+
+/* V2 only actions */
+#define OSD_ACT_V2(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
+
+#define OSD_ACT_V1_V2(Name, Num1, Num2) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
+
+enum osd_service_actions {
+	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
+	OSD_ACT___(FORMAT_OSD,			0x01)
+	OSD_ACT___(CREATE,			0x02)
+	OSD_ACT___(LIST,			0x03)
+	OSD_ACT_V2(PUNCH,			0x04)
+	OSD_ACT___(READ,			0x05)
+	OSD_ACT___(WRITE,			0x06)
+	OSD_ACT___(APPEND,			0x07)
+	OSD_ACT___(FLUSH,			0x08)
+	OSD_ACT_V2(CLEAR,			0x09)
+	OSD_ACT___(REMOVE,			0x0A)
+	OSD_ACT___(CREATE_PARTITION,		0x0B)
+	OSD_ACT___(REMOVE_PARTITION,		0x0C)
+	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
+	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
+	OSD_ACT___(CREATE_AND_WRITE,		0x12)
+	OSD_ACT___(CREATE_COLLECTION,		0x15)
+	OSD_ACT___(REMOVE_COLLECTION,		0x16)
+	OSD_ACT___(LIST_COLLECTION,		0x17)
+	OSD_ACT___(SET_KEY,			0x18)
+	OSD_ACT___(SET_MASTER_KEY,		0x19)
+	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
+	OSD_ACT___(FLUSH_PARTITION,		0x1B)
+	OSD_ACT___(FLUSH_OSD,			0x1C)
+
+	OSD_ACT_V2(QUERY,			0x20)
+	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
+	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
+	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
+	OSD_ACT_V2(READ_MAP,			0x31)
+
+	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
+	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
+	/* 0x8F80 to 0x8FFF are Vendor specific */
+};
+
+/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
+struct osd_attributes_list_attrid {
+	__be32 page;
+	__be32 attr_id;
+} __packed;
+
+/*
+ * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
+ *                  for setting attributes
+ */
+struct osd_attributes_list_element {
+	__be32 page;
+	__be32 attr_id;
+	__be16 attr_bytes;
+	u8 attr_val[0];
+} __packed;
+
+enum {
+	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+};
+
+enum {
+	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
+	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
+};
+
+static inline unsigned osdv1_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
+}
+
+/*
+ * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
+ */
+enum osd_attr_list_types {
+	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
+	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
+	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
+	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
+};
+
+/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
+struct osd_attributes_list_multi_header {
+	__be64 object_id;
+	u8 object_type; /* object_type enum below */
+	u8 reserved[5];
+	__be16 list_bytes;
+	/* followed by struct osd_attributes_list_element's */
+};
+
+struct osdv1_attributes_list_header {
+	u8 type;	/* low 4-bit only */
+	u8 pad;
+	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
+{
+	return be16_to_cpu(h->list_bytes);
+}
+
+/* (osd-r10 6.13)
+ * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
+ *	for root_lstchg below
+ */
+enum {
+	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
+	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
+};
+
+/*
+ * osd2r03: 6.15.2 LIST command parameter data
+ * (Also for LIST COLLECTION)
+ */
+struct osd_obj_id_list {
+	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
+	__be64 continuation_id;
+	__be32 list_identifier;
+	u8 pad[3];
+	u8 root_lstchg;
+	__be64 object_ids[0];
+} __packed;
+
+static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
+	bool *is_changed)
+{
+	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
+	return 0 != list->continuation_id;
+}
+
+/*
+ * osd2r03: 4.12.4.5 The ALLDATA security method
+ */
+struct osd_data_out_integrity_info {
+	__be64 data_bytes;
+	__be64 set_attributes_bytes;
+	__be64 get_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_data_in_integrity_info {
+	__be64 data_bytes;
+	__be64 retrieved_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_timestamp {
+	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
+} __packed;
+/* FIXME: define helper functions to convert to/from osd time format */
+
+/*
+ * Capability & Security definitions
+ * osd2r03: 4.11.2.2 Capability format
+ * osd2r03: 5.2.8 Security parameters
+ */
+
+struct osd_key_identifier {
+	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+} __packed;
+
+/* for osd_capability.format */
+enum {
+	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
+	OSD_SEC_CAP_FORMAT_VER1 = 1,
+	OSD_SEC_CAP_FORMAT_VER2 = 2,
+};
+
+/* security_method */
+enum {
+	OSD_SEC_NOSEC = 0,
+	OSD_SEC_CAPKEY = 1,
+	OSD_SEC_CMDRSP = 2,
+	OSD_SEC_ALLDATA = 3,
+};
+
+enum object_type {
+	OSD_SEC_OBJ_ROOT = 0x1,
+	OSD_SEC_OBJ_PARTITION = 0x2,
+	OSD_SEC_OBJ_COLLECTION = 0x40,
+	OSD_SEC_OBJ_USER = 0x80,
+};
+
+enum osd_capability_bit_masks {
+	OSD_SEC_CAP_APPEND	= BIT(0),
+	OSD_SEC_CAP_OBJ_MGMT	= BIT(1),
+	OSD_SEC_CAP_REMOVE	= BIT(2),
+	OSD_SEC_CAP_CREATE	= BIT(3),
+	OSD_SEC_CAP_SET_ATTR	= BIT(4),
+	OSD_SEC_CAP_GET_ATTR	= BIT(5),
+	OSD_SEC_CAP_WRITE	= BIT(6),
+	OSD_SEC_CAP_READ	= BIT(7),
+
+	OSD_SEC_CAP_NONE1	= BIT(8),
+	OSD_SEC_CAP_NONE2	= BIT(9),
+	OSD_SEC_CAP_NONE3	= BIT(10),
+	OSD_SEC_CAP_QUERY	= BIT(11), /*v2 only*/
+	OSD_SEC_CAP_M_OBJECT	= BIT(12), /*v2 only*/
+	OSD_SEC_CAP_POL_SEC	= BIT(13),
+	OSD_SEC_CAP_GLOBAL	= BIT(14),
+	OSD_SEC_CAP_DEV_MGMT	= BIT(15),
+};
+
+/* for object_descriptor_type (hi nibble used) */
+enum {
+	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
+	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
+	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
+	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
+};
+
+/* (osd-r10:4.9.2.2)
+ * osd2r03:4.11.2.2 Capability format
+ */
+struct osd_capability_head {
+	u8 format; /* low nibble */
+	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
+	u8 security_method;
+	u8 reserved1;
+/*04*/	struct osd_timestamp expiration_time;
+/*10*/	u8 audit[20];
+/*30*/	u8 discriminator[12];
+/*42*/	struct osd_timestamp object_created_time;
+/*48*/	u8 object_type;
+/*49*/	u8 permissions_bit_mask[5];
+/*54*/	u8 reserved2;
+/*55*/	u8 object_descriptor_type; /* high nibble */
+} __packed;
+
+/*56 v1*/
+struct osdv1_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 policy_access_tag;
+/*60*/			__be64 allowed_partition_id;
+/*68*/			__be64 allowed_object_id;
+/*76*/			__be32 reserved;
+		} __packed obj_desc;
+
+/*56*/		u8 object_descriptor[24];
+	};
+} __packed;
+/*80 v1*/
+
+struct osd_capability {
+	struct osd_capability_head h;
+	struct osdv1_cap_object_descriptor od;
+} __packed;
+
+/**
+ * osd_sec_set_caps - set cap-bits into the capabilities header
+ *
+ * @cap:	The osd_capability_head to set cap bits to.
+ * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
+ *
+ * permissions_bit_mask is unaligned use below to set into caps
+ * in a version independent way
+ */
+static inline void osd_sec_set_caps(struct osd_capability_head *cap,
+	u16 bit_mask)
+{
+	/*
+	 *Note: The bits above are defined LE order this is because this way
+	 *      they can grow in the future to more then 16, and still retain
+	 *      there constant values.
+	 */
+	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
+}
+
+#endif /* ndef __OSD_PROTOCOL_H__ */
diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h
new file mode 100644
index 0000000..4c09fee
--- /dev/null
+++ b/include/scsi/osd_sec.h
@@ -0,0 +1,45 @@
+/*
+ * osd_sec.h - OSD security manager API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_SEC_H__
+#define __OSD_SEC_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/*
+ * Contains types and constants of osd capabilities and security
+ * encoding/decoding.
+ * API is trying to keep security abstract so initiator of an object
+ * based pNFS client knows as little as possible about security and
+ * capabilities. It is the Server's osd-initiator place to know more.
+ * Also can be used by osd-target.
+ */
+void osd_sec_encode_caps(void *caps, ...);/* NI */
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1);
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_params);
+
+/* Conditionally sign the CDB according to security setting in ocdb
+ * with cap_key */
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key);
+
+/* Unconditionally sign the BIO data with cap_key.
+ * Check for osd_is_sec_alldata() was done prior to calling this. */
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key);
+
+/* Version independent copy of caps into the cdb */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps);
+
+#endif /* ndef __OSD_SEC_H__ */
diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h
new file mode 100644
index 0000000..ea5372d
--- /dev/null
+++ b/include/scsi/osd_types.h
@@ -0,0 +1,40 @@
+/*
+ * osd_types.h - Types and constants which are not part of the protocol.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Contains types and constants that are implementation specific and are
+ * used by more than one part of the osd library.
+ *     (Eg initiator/target/security_manager/...)
+ */
+#ifndef __OSD_TYPES_H__
+#define __OSD_TYPES_H__c6e00c1
+
+struct osd_systemid {
+	u8 data[OSD_SYSTEMID_LEN];
+};
+
+typedef u64 __bitwise osd_id;
+
+struct osd_obj_id {
+	osd_id partition;
+	osd_id id;
+};
+
+static const struct __weak osd_obj_id osd_root_object = {0, 0};
+
+struct osd_attr {
+	u32 page;
+	u32 attr_id;
+	u16 len;		/* byte count of operand */
+	void *val_ptr;		/* in network order */
+};
+
+#endif /* ndef __OSD_TYPES_H__ */
-- 
1.6.0.1



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 03/18 ver4] libosd: OSDv1 Headers
@ 2008-11-13 12:25               ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-13 12:25 UTC (permalink / raw)
  To: Randy Dunlap, James Bottomley
  Cc: Andrew Morton, Jörn Engel, open-osd development,
	Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-scsi,
	Sami.Iren, linux-kernel


Headers only patch.

osd_protocol.h
	Contains a C-fied definition of the T10 OSD standard
osd_types.h
	Contains CPU order common used types
osd_initiator.h
	API definition of the osd_initiator library
osd_sec.h
	Contains High level API for the security manager.

[Note that checkpatch spews errors on things that are valid in this context
and will not be fixed]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
 include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_sec.h       |   45 ++++
 include/scsi/osd_types.h     |   40 ++++
 4 files changed, 914 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_initiator.h
 create mode 100644 include/scsi/osd_protocol.h
 create mode 100644 include/scsi/osd_sec.h
 create mode 100644 include/scsi/osd_types.h

diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
new file mode 100644
index 0000000..1d92247
--- /dev/null
+++ b/include/scsi/osd_initiator.h
@@ -0,0 +1,332 @@
+/*
+ * osd_initiator.h - OSD initiator API definition
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_INITIATOR_H__
+#define __OSD_INITIATOR_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+#include <linux/blkdev.h>
+
+/* Note: "NI" in comments below means "Not Implemented yet" */
+
+/*
+ * Object-based Storage Device.
+ * This object represents an OSD device.
+ * It is not a full linux device in any way. It is only
+ * a place to hang resources associated with a Linux
+ * request Q and some default properties.
+ */
+struct osd_dev {
+	struct scsi_device *scsi_device;
+	unsigned def_timeout;
+};
+
+void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
+void osd_dev_fini(struct osd_dev *od);
+
+struct osd_request;
+typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
+
+struct osd_request {
+	struct osd_cdb cdb;
+	struct osd_data_out_integrity_info out_data_integ;
+	struct osd_data_in_integrity_info in_data_integ;
+
+	struct osd_dev *osd_dev;
+	struct request *request;
+
+	struct _osd_req_data_segment {
+		void *buff;
+		unsigned alloc_size; /* 0 here means: don't call kfree */
+		unsigned total_bytes;
+	} set_attr, enc_get_attr, get_attr;
+
+	struct _osd_io_info {
+		struct bio *bio;
+		u64 total_bytes;
+		struct request *req;
+		struct _osd_req_data_segment *last_seg;
+		u8 *pad_buff;
+	} out, in;
+
+	gfp_t alloc_flags;
+	unsigned timeout;
+	unsigned retries;
+	u8 sense[OSD_MAX_SENSE_LEN];
+	enum osd_attributes_mode attributes_mode;
+
+	osd_req_done_fn *async_done;
+	void *async_private;
+	int async_error;
+};
+
+/*
+ * How to use the osd library:
+ *
+ * osd_start_request
+ *	Allocates a request.
+ *
+ * osd_req_*
+ *	Call one of, to encode the desired operation.
+ *
+ * osd_add_{get,set}_attr
+ *	Optionally add attributes to the CDB, list or page mode.
+ *
+ * osd_finalize_request
+ *	Computes final data out/in offsets and signs the request,
+ *	making it ready for execution.
+ *
+ * osd_execute_request
+ *	May be called to execute it through the block layer. Other wise submit
+ *	the associated block request in some other way.
+ *
+ * After execution:
+ * osd_req_decode_sense
+ *	Decodes sense information to verify execution results.
+ *
+ * osd_req_decode_get_attr
+ *	Retrieve osd_add_get_attr_list() values if used.
+ *
+ * osd_end_request
+ *	Must be called to deallocate the request.
+ */
+
+/**
+ * osd_start_request - Allocate and initialize an osd_request
+ *
+ * @osd_dev:    OSD device that holds the scsi-device and default values
+ *              that the request is associated with.
+ * @gfp:        The allocation flags to use for request allocation, and all
+ *              subsequent allocations. This will be stored at
+ *              osd_request->alloc_flags, can be changed by user later
+ *
+ * Allocate osd_request and initialize all members to the
+ * default/initial state.
+ */
+struct osd_request *osd_start_request(struct osd_dev *od, gfp_t gfp);
+
+enum osd_req_options {
+	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
+	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
+
+	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
+};
+
+/**
+ * osd_finalize_request - Sign request and prepare request for execution
+ *
+ * @or:		osd_request to prepare
+ * @options:	combination of osd_req_options bit flags or 0.
+ * @cap:	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
+ *              The security manager as capabilities for this cdb.
+ * @cap_key:	The cryptographic key used to sign the cdb/data. Can be null
+ *              if NOSEC is used.
+ *
+ * The actual request and bios are only allocated here, so are the get_attr
+ * buffers that will receive the returned attributes. Copy's @cap to cdb.
+ * Sign the cdb/data with @cap_key.
+ */
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key);
+
+/**
+ * osd_execute_request - Execute the request synchronously through block-layer
+ *
+ * @or:		osd_request to Executed
+ *
+ * Calls blk_execute_rq to q the command and waits for completion.
+ */
+int osd_execute_request(struct osd_request *or);
+
+/**
+ * osd_execute_request_async - Execute the request without waitting.
+ *
+ * @or:                      - osd_request to Executed
+ * @done: (Optional)         - Called at end of execution
+ * @private:                 - Will be passed to @done function
+ *
+ * Calls blk_execute_rq_nowait to queue the command. When execution is done
+ * optionally calls @done with @private as parameter. @or->async_error will
+ * have the return code
+ */
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private);
+
+/**
+ * osd_end_request - return osd_request to free store
+ *
+ * @or:		osd_request to free
+ *
+ * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
+ */
+void osd_end_request(struct osd_request *or);
+
+/*
+ * CDB Encoding
+ *
+ * Note: call only one of the following methods.
+ */
+
+/*
+ * Device commands
+ */
+void osd_req_set_master_seed_xchg(struct osd_request *or, ...);/* NI */
+void osd_req_set_master_key(struct osd_request *or, ...);/* NI */
+
+void osd_req_format(struct osd_request *or, u64 tot_capacity);
+
+/* list all partitions
+ * @list header must be initialized to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values);
+
+void osd_req_perform_scsi_command(struct osd_request *or,
+	const u8 *cdb, ...);/* NI */
+void osd_req_task_management(struct osd_request *or, ...);/* NI */
+
+/*
+ * Partition commands
+ */
+void osd_req_create_partition(struct osd_request *or, osd_id partition);
+void osd_req_remove_partition(struct osd_request *or, osd_id partition);
+
+void osd_req_set_partition_key(struct osd_request *or,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
+
+/* list all collections in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+/* list all objects in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values);
+
+/*
+ * Collection commands
+ */
+void osd_req_create_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+void osd_req_remove_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+
+/* list all objects in the collection */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem);
+
+/* V2 only filtered list of objects in the collection */
+void osd_req_query(struct osd_request *or, ...);/* NI */
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values);
+
+void osd_req_get_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+void osd_req_set_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *);
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);
+void osd_req_append(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out);/* NI */
+void osd_req_create_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
+void osd_req_clear(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
+void osd_req_punch(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
+
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values,
+	/*V2*/ u64 offset, /*V2*/ u64 len);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_in, u64 offset);
+
+/*
+ * Root/Partition/Collection/Object Attributes commands
+ */
+
+/* get before set */
+void osd_req_get_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/* set before get */
+void osd_req_set_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/*
+ * Attributes appended to most commands
+ */
+
+/* Attributes List mode (or V2 CDB) */
+  /*
+   * TODO: In ver2 if at finalize time only one attr was set and no gets,
+   * then the Attributes CDB mode is used automatically to save IO.
+   */
+
+/* set a list of attributes. */
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/* get a list of attributes */
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/*
+ * Attributes list decoding
+ * Must be called after osd_request.request was executed
+ * It is called in a loop to decode the returned get_attr
+ * (see osd_add_get_attr)
+ */
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *, int *nelem, void **iterator);
+
+/* Attributes Page mode */
+
+/*
+ * Read an attribute page and optionally set one attribute
+ *
+ * Retrieves the attribute page directly to a user buffer.
+ * @attr_page_data shall stay valid until end of execution.
+ * See osd_attributes.h for common page structures
+ */
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attr_page_data, unsigned max_page_len,
+	const struct osd_attr *set_one);
+
+#endif /* __OSD_LIB_H__ */
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
new file mode 100644
index 0000000..eeb899b
--- /dev/null
+++ b/include/scsi/osd_protocol.h
@@ -0,0 +1,497 @@
+/*
+ * osd_protocol.h - OSD T10 standard C definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_PROTOCOL_H__
+#define __OSD_PROTOCOL_H__
+
+#include <linux/types.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+enum {
+	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
+	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
+	OSDv1_CAP_LEN = 80,
+	/* Latest supported version */
+	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
+	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
+	OSD_CAP_LEN = OSDv1_CAP_LEN,
+
+	OSD_SYSTEMID_LEN = 20,
+	OSD_CRYPTO_KEYID_SIZE = 20,
+	OSD_CRYPTO_SEED_SIZE = 4,
+	OSD_CRYPTO_NONCE_SIZE = 12,
+	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
+
+	OSD_PARTITION_FIRST_ID = 0x10000,
+	OSD_OBJECT_FIRST_ID = 0x10000,
+};
+
+/* (osd-r10 5.2.4)
+ * osd2r03: 5.2.3 Caching control bits
+ */
+enum osd_options_byte {
+	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
+	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
+};
+
+/*
+ * osd2r03: 5.2.5 Isolation.
+ * First 3 bits, V2-only.
+ * Also for attr 110h "default isolation method" at Root Information page
+ */
+enum osd_options_byte_isolation {
+	OSD_ISOLATION_DEFAULT = 0,
+	OSD_ISOLATION_NONE = 1,
+	OSD_ISOLATION_STRICT = 2,
+	OSD_ISOLATION_RANGE = 4,
+	OSD_ISOLATION_FUNCTIONAL = 5,
+	OSD_ISOLATION_VENDOR = 7,
+};
+
+/* (osd-r10: 6.7)
+ * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
+ */
+enum osd_options_flush_scope_values {
+	OSD_CDB_FLUSH_ALL = 0,
+	OSD_CDB_FLUSH_ATTR_ONLY = 1,
+
+	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
+	/* V2-only */
+	OSD_CDB_FLUSH_ALL_RANGE = 2,
+};
+
+/* osd2r03: 5.2.10 Timestamps control */
+enum {
+	OSD_CDB_NORMAL_TIMESTAMPS = 0,
+	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
+};
+
+/* (osd-r10: 5.2.2.1)
+ * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
+ *	2 bits at second nibble of command_specific_options byte
+ */
+enum osd_attributes_mode {
+	/* V2-only */
+	OSD_CDB_SET_ONE_ATTR = 0x10,
+
+	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
+	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
+
+	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
+};
+
+/* (osd-r10: 4.12.5)
+ * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
+ *	byte offset = mantissa * (2^(exponent+8))
+ *	struct {
+ *		unsigned mantissa: 28;
+ *		int exponent: 04;
+ *	}
+ */
+typedef __be32 __bitwise osd_cdb_offset;
+
+enum {
+	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
+	OSD_OFFSET_MAX_BITS = 28,
+
+	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MAX_SHIFT = 16,
+};
+
+/* Return the smallest allowed encoded offset that contains @offset.
+ *
+ * The actual encoded offset returned is @offset + *padding.
+ * (up to max_shift, non-inclusive)
+ */
+osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
+	int min_shift, int max_shift);
+
+/* Minimum alignment is 256 bytes
+ * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
+ * which is 8 to 23 but IBM code restricts it to 16, so be it.
+ */
+static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
+/* osd2r03: 5.2.1 Overview */
+struct osd_cdb_head {
+	struct scsi_varlen_cdb_hdr varlen_cdb;
+/*10*/	u8		options;
+	u8		command_specific_options;
+	u8		timestamp_control;
+/*13*/	u8		reserved1[3];
+/*16*/	__be64		partition;
+/*24*/	__be64		object;
+/*32*/	union { /* V1 vs V2 alignment differences */
+		struct __osdv1_cdb_addr_len {
+/*32*/			__be32 		list_identifier;/* Rarely used */
+/*36*/			__be64		length;
+/*44*/			__be64		start_address;
+		} __packed v1;
+	};
+/*52*/	union { /* selected attributes mode Page/List/Single */
+		struct osd_attributes_page_mode {
+/*52*/			__be32		get_attr_page;
+/*56*/			__be32		get_attr_alloc_length;
+/*60*/			osd_cdb_offset	get_attr_offset;
+
+/*64*/			__be32		set_attr_page;
+/*68*/			__be32		set_attr_id;
+/*72*/			__be32		set_attr_length;
+/*76*/			osd_cdb_offset	set_attr_offset;
+/*80*/		} __packed attrs_page;
+
+		struct osd_attributes_list_mode {
+/*52*/			__be32		get_attr_desc_bytes;
+/*56*/			osd_cdb_offset	get_attr_desc_offset;
+
+/*60*/			__be32		get_attr_alloc_length;
+/*64*/			osd_cdb_offset	get_attr_offset;
+
+/*68*/			__be32		set_attr_bytes;
+/*72*/			osd_cdb_offset	set_attr_offset;
+			__be32 not_used;
+/*80*/		} __packed attrs_list;
+
+		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
+		struct osd_attributes_cdb_mode {
+/*52*/			__be32		set_attr_page;
+/*56*/			__be32		set_attr_id;
+/*60*/			__be16		set_attr_len;
+/*62*/			u8		set_attr_val[18];
+/*80*/		} __packed attrs_cdb;
+/*52*/		u8 get_set_attributes_parameters[28];
+	};
+} __packed;
+/*80*/
+
+/*160 v1*/
+struct osd_security_parameters {
+/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*192*/osd_cdb_offset	data_in_integrity_check_offset;
+/*196*/osd_cdb_offset	data_out_integrity_check_offset;
+} __packed;
+/*200 v1*/
+
+struct osdv1_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSDv1_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
+struct osd_cdb {
+	union {
+		struct osdv1_cdb v1;
+		u8 buff[OSD_TOTAL_CDB_LEN];
+	};
+} __packed;
+
+static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
+{
+	return (struct osd_cdb_head *)ocdb->buff;
+}
+
+/* define both version actions
+ * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
+ */
+#define OSD_ACT___(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
+
+/* V2 only actions */
+#define OSD_ACT_V2(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
+
+#define OSD_ACT_V1_V2(Name, Num1, Num2) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
+
+enum osd_service_actions {
+	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
+	OSD_ACT___(FORMAT_OSD,			0x01)
+	OSD_ACT___(CREATE,			0x02)
+	OSD_ACT___(LIST,			0x03)
+	OSD_ACT_V2(PUNCH,			0x04)
+	OSD_ACT___(READ,			0x05)
+	OSD_ACT___(WRITE,			0x06)
+	OSD_ACT___(APPEND,			0x07)
+	OSD_ACT___(FLUSH,			0x08)
+	OSD_ACT_V2(CLEAR,			0x09)
+	OSD_ACT___(REMOVE,			0x0A)
+	OSD_ACT___(CREATE_PARTITION,		0x0B)
+	OSD_ACT___(REMOVE_PARTITION,		0x0C)
+	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
+	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
+	OSD_ACT___(CREATE_AND_WRITE,		0x12)
+	OSD_ACT___(CREATE_COLLECTION,		0x15)
+	OSD_ACT___(REMOVE_COLLECTION,		0x16)
+	OSD_ACT___(LIST_COLLECTION,		0x17)
+	OSD_ACT___(SET_KEY,			0x18)
+	OSD_ACT___(SET_MASTER_KEY,		0x19)
+	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
+	OSD_ACT___(FLUSH_PARTITION,		0x1B)
+	OSD_ACT___(FLUSH_OSD,			0x1C)
+
+	OSD_ACT_V2(QUERY,			0x20)
+	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
+	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
+	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
+	OSD_ACT_V2(READ_MAP,			0x31)
+
+	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
+	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
+	/* 0x8F80 to 0x8FFF are Vendor specific */
+};
+
+/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
+struct osd_attributes_list_attrid {
+	__be32 page;
+	__be32 attr_id;
+} __packed;
+
+/*
+ * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
+ *                  for setting attributes
+ */
+struct osd_attributes_list_element {
+	__be32 page;
+	__be32 attr_id;
+	__be16 attr_bytes;
+	u8 attr_val[0];
+} __packed;
+
+enum {
+	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+};
+
+enum {
+	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
+	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
+};
+
+static inline unsigned osdv1_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
+}
+
+/*
+ * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
+ */
+enum osd_attr_list_types {
+	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
+	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
+	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
+	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
+};
+
+/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
+struct osd_attributes_list_multi_header {
+	__be64 object_id;
+	u8 object_type; /* object_type enum below */
+	u8 reserved[5];
+	__be16 list_bytes;
+	/* followed by struct osd_attributes_list_element's */
+};
+
+struct osdv1_attributes_list_header {
+	u8 type;	/* low 4-bit only */
+	u8 pad;
+	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
+{
+	return be16_to_cpu(h->list_bytes);
+}
+
+/* (osd-r10 6.13)
+ * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
+ *	for root_lstchg below
+ */
+enum {
+	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
+	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
+};
+
+/*
+ * osd2r03: 6.15.2 LIST command parameter data
+ * (Also for LIST COLLECTION)
+ */
+struct osd_obj_id_list {
+	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
+	__be64 continuation_id;
+	__be32 list_identifier;
+	u8 pad[3];
+	u8 root_lstchg;
+	__be64 object_ids[0];
+} __packed;
+
+static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
+	bool *is_changed)
+{
+	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
+	return 0 != list->continuation_id;
+}
+
+/*
+ * osd2r03: 4.12.4.5 The ALLDATA security method
+ */
+struct osd_data_out_integrity_info {
+	__be64 data_bytes;
+	__be64 set_attributes_bytes;
+	__be64 get_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_data_in_integrity_info {
+	__be64 data_bytes;
+	__be64 retrieved_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_timestamp {
+	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
+} __packed;
+/* FIXME: define helper functions to convert to/from osd time format */
+
+/*
+ * Capability & Security definitions
+ * osd2r03: 4.11.2.2 Capability format
+ * osd2r03: 5.2.8 Security parameters
+ */
+
+struct osd_key_identifier {
+	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+} __packed;
+
+/* for osd_capability.format */
+enum {
+	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
+	OSD_SEC_CAP_FORMAT_VER1 = 1,
+	OSD_SEC_CAP_FORMAT_VER2 = 2,
+};
+
+/* security_method */
+enum {
+	OSD_SEC_NOSEC = 0,
+	OSD_SEC_CAPKEY = 1,
+	OSD_SEC_CMDRSP = 2,
+	OSD_SEC_ALLDATA = 3,
+};
+
+enum object_type {
+	OSD_SEC_OBJ_ROOT = 0x1,
+	OSD_SEC_OBJ_PARTITION = 0x2,
+	OSD_SEC_OBJ_COLLECTION = 0x40,
+	OSD_SEC_OBJ_USER = 0x80,
+};
+
+enum osd_capability_bit_masks {
+	OSD_SEC_CAP_APPEND	= BIT(0),
+	OSD_SEC_CAP_OBJ_MGMT	= BIT(1),
+	OSD_SEC_CAP_REMOVE	= BIT(2),
+	OSD_SEC_CAP_CREATE	= BIT(3),
+	OSD_SEC_CAP_SET_ATTR	= BIT(4),
+	OSD_SEC_CAP_GET_ATTR	= BIT(5),
+	OSD_SEC_CAP_WRITE	= BIT(6),
+	OSD_SEC_CAP_READ	= BIT(7),
+
+	OSD_SEC_CAP_NONE1	= BIT(8),
+	OSD_SEC_CAP_NONE2	= BIT(9),
+	OSD_SEC_CAP_NONE3	= BIT(10),
+	OSD_SEC_CAP_QUERY	= BIT(11), /*v2 only*/
+	OSD_SEC_CAP_M_OBJECT	= BIT(12), /*v2 only*/
+	OSD_SEC_CAP_POL_SEC	= BIT(13),
+	OSD_SEC_CAP_GLOBAL	= BIT(14),
+	OSD_SEC_CAP_DEV_MGMT	= BIT(15),
+};
+
+/* for object_descriptor_type (hi nibble used) */
+enum {
+	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
+	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
+	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
+	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
+};
+
+/* (osd-r10:4.9.2.2)
+ * osd2r03:4.11.2.2 Capability format
+ */
+struct osd_capability_head {
+	u8 format; /* low nibble */
+	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
+	u8 security_method;
+	u8 reserved1;
+/*04*/	struct osd_timestamp expiration_time;
+/*10*/	u8 audit[20];
+/*30*/	u8 discriminator[12];
+/*42*/	struct osd_timestamp object_created_time;
+/*48*/	u8 object_type;
+/*49*/	u8 permissions_bit_mask[5];
+/*54*/	u8 reserved2;
+/*55*/	u8 object_descriptor_type; /* high nibble */
+} __packed;
+
+/*56 v1*/
+struct osdv1_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 policy_access_tag;
+/*60*/			__be64 allowed_partition_id;
+/*68*/			__be64 allowed_object_id;
+/*76*/			__be32 reserved;
+		} __packed obj_desc;
+
+/*56*/		u8 object_descriptor[24];
+	};
+} __packed;
+/*80 v1*/
+
+struct osd_capability {
+	struct osd_capability_head h;
+	struct osdv1_cap_object_descriptor od;
+} __packed;
+
+/**
+ * osd_sec_set_caps - set cap-bits into the capabilities header
+ *
+ * @cap:	The osd_capability_head to set cap bits to.
+ * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
+ *
+ * permissions_bit_mask is unaligned use below to set into caps
+ * in a version independent way
+ */
+static inline void osd_sec_set_caps(struct osd_capability_head *cap,
+	u16 bit_mask)
+{
+	/*
+	 *Note: The bits above are defined LE order this is because this way
+	 *      they can grow in the future to more then 16, and still retain
+	 *      there constant values.
+	 */
+	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
+}
+
+#endif /* ndef __OSD_PROTOCOL_H__ */
diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h
new file mode 100644
index 0000000..4c09fee
--- /dev/null
+++ b/include/scsi/osd_sec.h
@@ -0,0 +1,45 @@
+/*
+ * osd_sec.h - OSD security manager API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_SEC_H__
+#define __OSD_SEC_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/*
+ * Contains types and constants of osd capabilities and security
+ * encoding/decoding.
+ * API is trying to keep security abstract so initiator of an object
+ * based pNFS client knows as little as possible about security and
+ * capabilities. It is the Server's osd-initiator place to know more.
+ * Also can be used by osd-target.
+ */
+void osd_sec_encode_caps(void *caps, ...);/* NI */
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1);
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_params);
+
+/* Conditionally sign the CDB according to security setting in ocdb
+ * with cap_key */
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key);
+
+/* Unconditionally sign the BIO data with cap_key.
+ * Check for osd_is_sec_alldata() was done prior to calling this. */
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key);
+
+/* Version independent copy of caps into the cdb */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps);
+
+#endif /* ndef __OSD_SEC_H__ */
diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h
new file mode 100644
index 0000000..ea5372d
--- /dev/null
+++ b/include/scsi/osd_types.h
@@ -0,0 +1,40 @@
+/*
+ * osd_types.h - Types and constants which are not part of the protocol.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Contains types and constants that are implementation specific and are
+ * used by more than one part of the osd library.
+ *     (Eg initiator/target/security_manager/...)
+ */
+#ifndef __OSD_TYPES_H__
+#define __OSD_TYPES_H__c6e00c1
+
+struct osd_systemid {
+	u8 data[OSD_SYSTEMID_LEN];
+};
+
+typedef u64 __bitwise osd_id;
+
+struct osd_obj_id {
+	osd_id partition;
+	osd_id id;
+};
+
+static const struct __weak osd_obj_id osd_root_object = {0, 0};
+
+struct osd_attr {
+	u32 page;
+	u32 attr_id;
+	u16 len;		/* byte count of operand */
+	void *val_ptr;		/* in network order */
+};
+
+#endif /* ndef __OSD_TYPES_H__ */
-- 
1.6.0.1


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* Re: [osd-dev] [PATCH 03/18 ver4] libosd: OSDv1 Headers
  2008-11-13 18:16               ` Randy Dunlap
@ 2008-11-13 15:41                 ` Benny Halevy
  0 siblings, 0 replies; 183+ messages in thread
From: Benny Halevy @ 2008-11-13 15:41 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: open-osd development, Christie, linux-scsi, Jeff Garzik,
	Jörn Engel, Sami.Iren, Mike, linux-kernel, James Bottomley,
	Andrew Morton

Acked-and-liked-by me too :-)

Benny

On Nov. 13, 2008, 20:16 +0200, Randy Dunlap <randy.dunlap@oracle.com> wrote:
> On Thu, 13 Nov 2008 14:25:35 +0200 Boaz Harrosh wrote:
> 
>> Headers only patch.
>>
>> osd_protocol.h
>> 	Contains a C-fied definition of the T10 OSD standard
>> osd_types.h
>> 	Contains CPU order common used types
>> osd_initiator.h
>> 	API definition of the osd_initiator library
>> osd_sec.h
>> 	Contains High level API for the security manager.
>>
>> [Note that checkpatch spews errors on things that are valid in this context
>> and will not be fixed]
>>
>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>> Reviewed-by: Benny Halevy <bhalevy@panasas.com>
> 
> OK by me.  Thanks for the changes.
> 
>> ---
>>  include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
>>  include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
>>  include/scsi/osd_sec.h       |   45 ++++
>>  include/scsi/osd_types.h     |   40 ++++
>>  4 files changed, 914 insertions(+), 0 deletions(-)
>>  create mode 100644 include/scsi/osd_initiator.h
>>  create mode 100644 include/scsi/osd_protocol.h
>>  create mode 100644 include/scsi/osd_sec.h
>>  create mode 100644 include/scsi/osd_types.h
> 
> ---
> ~Randy
> _______________________________________________
> osd-dev mailing list
> osd-dev@open-osd.org
> http://mailman.open-osd.org/mailman/listinfo/osd-dev


^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 03/18 ver4] libosd: OSDv1 Headers
  2008-11-13 12:25               ` Boaz Harrosh
  (?)
@ 2008-11-13 18:16               ` Randy Dunlap
  2008-11-13 15:41                 ` [osd-dev] " Benny Halevy
  -1 siblings, 1 reply; 183+ messages in thread
From: Randy Dunlap @ 2008-11-13 18:16 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: James Bottomley, Andrew Morton, Jörn Engel,
	open-osd development, Mike Christie, FUJITA Tomonori,
	Jeff Garzik, linux-scsi, Sami.Iren, linux-kernel

On Thu, 13 Nov 2008 14:25:35 +0200 Boaz Harrosh wrote:

> Headers only patch.
> 
> osd_protocol.h
> 	Contains a C-fied definition of the T10 OSD standard
> osd_types.h
> 	Contains CPU order common used types
> osd_initiator.h
> 	API definition of the osd_initiator library
> osd_sec.h
> 	Contains High level API for the security manager.
> 
> [Note that checkpatch spews errors on things that are valid in this context
> and will not be fixed]
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> Reviewed-by: Benny Halevy <bhalevy@panasas.com>

OK by me.  Thanks for the changes.

> ---
>  include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
>  include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
>  include/scsi/osd_sec.h       |   45 ++++
>  include/scsi/osd_types.h     |   40 ++++
>  4 files changed, 914 insertions(+), 0 deletions(-)
>  create mode 100644 include/scsi/osd_initiator.h
>  create mode 100644 include/scsi/osd_protocol.h
>  create mode 100644 include/scsi/osd_sec.h
>  create mode 100644 include/scsi/osd_types.h

---
~Randy

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [osd-dev] [PATCH 01/18] major.h: char-major number for OSD device driver
  2008-11-04 16:17     ` Boaz Harrosh
  (?)
@ 2008-11-26 17:33     ` Boaz Harrosh
  2008-11-26 18:07         ` Randy Dunlap
  -1 siblings, 1 reply; 183+ messages in thread
From: Boaz Harrosh @ 2008-11-26 17:33 UTC (permalink / raw)
  To: open-osd development
  Cc: Torben Mathiasen, James Bottomley, Andrew Morton, Mike Christie,
	FUJITA Tomonori, Jeff Garzik, linux-scsi, Sami.Iren,
	linux-kernel

Boaz Harrosh wrote:
> We need a major for a char device for our OSD device driver.
> Attached is a proposed patch for the Documentation/devices.txt
> and include/linux/major.h files.
> 
> I have allocated the *260* char device as it looked like the next
> available on the lanana.org web-site
> (http://lanana.org/docs/device-list/devices-2.6+.txt)
> 
> Any number will do. Please allocate a number for us
> 
> (See http:/open-osd.org for further information)
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> CC: Torben Mathiasen <device@lanana.org>

Hi Torben Mathiasen

The maintainers file as well as the lanana.org website only states
this <device@lanana.org> email address. I hope it is the right one.

Please you have not confirmed or revoked my ability to use 260 
as a Major for a new char-device. Please review

What git tree should this go through?

Thanks 
Boaz

> ---
>  Documentation/devices.txt |    6 ++++++
>  include/linux/major.h     |    1 +
>  2 files changed, 7 insertions(+), 0 deletions(-)
> 
> diff --git a/Documentation/devices.txt b/Documentation/devices.txt
> index 05c8064..d18070b 100644
> --- a/Documentation/devices.txt
> +++ b/Documentation/devices.txt
> @@ -3142,6 +3142,12 @@ Your cooperation is appreciated.
>  		  1 = /dev/blockrom1	Second ROM card's translation layer interface
>  		  ...
>  
> +260 char	OSD (Object-based-device) SCSI Device
> +		  0 = /dev/osd0		First OSD Device
> +		  1 = /dev/osd1		Second OSD Device
> +		  ...
> +		  255 = /dev/osd255	256th OSD Device
> +
>   ****	ADDITIONAL /dev DIRECTORY ENTRIES
>  
>  This section details additional entries that should or may exist in
> diff --git a/include/linux/major.h b/include/linux/major.h
> index 8824945..058ec15 100644
> --- a/include/linux/major.h
> +++ b/include/linux/major.h
> @@ -171,5 +171,6 @@
>  #define VIOTAPE_MAJOR		230
>  
>  #define BLOCK_EXT_MAJOR		259
> +#define SCSI_OSD_MAJOR		260	/* open-osd's OSD scsi device */
>  
>  #endif


^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [osd-dev] [PATCH 01/18] major.h: char-major number for OSD device driver
  2008-11-26 17:33     ` [osd-dev] " Boaz Harrosh
@ 2008-11-26 18:07         ` Randy Dunlap
  0 siblings, 0 replies; 183+ messages in thread
From: Randy Dunlap @ 2008-11-26 18:07 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: open-osd development, Torben Mathiasen, James Bottomley,
	Andrew Morton, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, Sami.Iren, linux-kernel, device, hpa

[-- Attachment #1: Type: text/plain, Size: 2372 bytes --]

Boaz Harrosh wrote:
> Boaz Harrosh wrote:
>> We need a major for a char device for our OSD device driver.
>> Attached is a proposed patch for the Documentation/devices.txt
>> and include/linux/major.h files.
>>
>> I have allocated the *260* char device as it looked like the next
>> available on the lanana.org web-site
>> (http://lanana.org/docs/device-list/devices-2.6+.txt)
>>
>> Any number will do. Please allocate a number for us
>>
>> (See http:/open-osd.org for further information)
>>
>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>> CC: Torben Mathiasen <device@lanana.org>
> 
> Hi Torben Mathiasen
> 
> The maintainers file as well as the lanana.org website only states
> this <device@lanana.org> email address. I hope it is the right one.
> 
> Please you have not confirmed or revoked my ability to use 260 
> as a Major for a new char-device. Please review

Was it cc-ed to device@lanana.org?  I can't see that.  Adding it now.

John Cagle, can you comment on this, please?

And also have the attached patch merged into the MAINTAINERS file, please.

The www.lanana.org web page also needs to be updated:
  Maintained by Torben Mathiasen
is no longer correct.


> What git tree should this go through?
> 
> Thanks 
> Boaz
> 
>> ---
>>  Documentation/devices.txt |    6 ++++++
>>  include/linux/major.h     |    1 +
>>  2 files changed, 7 insertions(+), 0 deletions(-)
>>
>> diff --git a/Documentation/devices.txt b/Documentation/devices.txt
>> index 05c8064..d18070b 100644
>> --- a/Documentation/devices.txt
>> +++ b/Documentation/devices.txt
>> @@ -3142,6 +3142,12 @@ Your cooperation is appreciated.
>>  		  1 = /dev/blockrom1	Second ROM card's translation layer interface
>>  		  ...
>>  
>> +260 char	OSD (Object-based-device) SCSI Device
>> +		  0 = /dev/osd0		First OSD Device
>> +		  1 = /dev/osd1		Second OSD Device
>> +		  ...
>> +		  255 = /dev/osd255	256th OSD Device
>> +
>>   ****	ADDITIONAL /dev DIRECTORY ENTRIES
>>  
>>  This section details additional entries that should or may exist in
>> diff --git a/include/linux/major.h b/include/linux/major.h
>> index 8824945..058ec15 100644
>> --- a/include/linux/major.h
>> +++ b/include/linux/major.h
>> @@ -171,5 +171,6 @@
>>  #define VIOTAPE_MAJOR		230
>>  
>>  #define BLOCK_EXT_MAJOR		259
>> +#define SCSI_OSD_MAJOR		260	/* open-osd's OSD scsi device */
>>  
>>  #endif
> 


-- 
~Randy

[-- Attachment #2: maint-update-lanana.patch --]
[-- Type: text/x-patch, Size: 547 bytes --]

From: Randy Dunlap <randy.dunlap@oracle.com>

Update the DEVICE NUMBER REGISTRY (LANANA) maintainer entry.

Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
---
 MAINTAINERS |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- linux-next-20081126.orig/MAINTAINERS
+++ linux-next-20081126/MAINTAINERS
@@ -1372,7 +1372,7 @@ M:	Douglas_Warzecha@dell.com
 S:	Maintained
 
 DEVICE NUMBER REGISTRY
-P:	Torben Mathiasen
+P:	John Cagle
 M:	device@lanana.org
 W:	http://lanana.org/docs/device-list/index.html
 L:	linux-kernel@vger.kernel.org

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [osd-dev] [PATCH 01/18] major.h: char-major number for OSD device driver
@ 2008-11-26 18:07         ` Randy Dunlap
  0 siblings, 0 replies; 183+ messages in thread
From: Randy Dunlap @ 2008-11-26 18:07 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: open-osd development, Torben Mathiasen, James Bottomley,
	Andrew Morton, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, Sami.Iren, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2372 bytes --]

Boaz Harrosh wrote:
> Boaz Harrosh wrote:
>> We need a major for a char device for our OSD device driver.
>> Attached is a proposed patch for the Documentation/devices.txt
>> and include/linux/major.h files.
>>
>> I have allocated the *260* char device as it looked like the next
>> available on the lanana.org web-site
>> (http://lanana.org/docs/device-list/devices-2.6+.txt)
>>
>> Any number will do. Please allocate a number for us
>>
>> (See http:/open-osd.org for further information)
>>
>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>> CC: Torben Mathiasen <device@lanana.org>
> 
> Hi Torben Mathiasen
> 
> The maintainers file as well as the lanana.org website only states
> this <device@lanana.org> email address. I hope it is the right one.
> 
> Please you have not confirmed or revoked my ability to use 260 
> as a Major for a new char-device. Please review

Was it cc-ed to device@lanana.org?  I can't see that.  Adding it now.

John Cagle, can you comment on this, please?

And also have the attached patch merged into the MAINTAINERS file, please.

The www.lanana.org web page also needs to be updated:
  Maintained by Torben Mathiasen
is no longer correct.


> What git tree should this go through?
> 
> Thanks 
> Boaz
> 
>> ---
>>  Documentation/devices.txt |    6 ++++++
>>  include/linux/major.h     |    1 +
>>  2 files changed, 7 insertions(+), 0 deletions(-)
>>
>> diff --git a/Documentation/devices.txt b/Documentation/devices.txt
>> index 05c8064..d18070b 100644
>> --- a/Documentation/devices.txt
>> +++ b/Documentation/devices.txt
>> @@ -3142,6 +3142,12 @@ Your cooperation is appreciated.
>>  		  1 = /dev/blockrom1	Second ROM card's translation layer interface
>>  		  ...
>>  
>> +260 char	OSD (Object-based-device) SCSI Device
>> +		  0 = /dev/osd0		First OSD Device
>> +		  1 = /dev/osd1		Second OSD Device
>> +		  ...
>> +		  255 = /dev/osd255	256th OSD Device
>> +
>>   ****	ADDITIONAL /dev DIRECTORY ENTRIES
>>  
>>  This section details additional entries that should or may exist in
>> diff --git a/include/linux/major.h b/include/linux/major.h
>> index 8824945..058ec15 100644
>> --- a/include/linux/major.h
>> +++ b/include/linux/major.h
>> @@ -171,5 +171,6 @@
>>  #define VIOTAPE_MAJOR		230
>>  
>>  #define BLOCK_EXT_MAJOR		259
>> +#define SCSI_OSD_MAJOR		260	/* open-osd's OSD scsi device */
>>  
>>  #endif
> 


-- 
~Randy

[-- Attachment #2: maint-update-lanana.patch --]
[-- Type: text/x-patch, Size: 547 bytes --]

From: Randy Dunlap <randy.dunlap@oracle.com>

Update the DEVICE NUMBER REGISTRY (LANANA) maintainer entry.

Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
---
 MAINTAINERS |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- linux-next-20081126.orig/MAINTAINERS
+++ linux-next-20081126/MAINTAINERS
@@ -1372,7 +1372,7 @@ M:	Douglas_Warzecha@dell.com
 S:	Maintained
 
 DEVICE NUMBER REGISTRY
-P:	Torben Mathiasen
+P:	John Cagle
 M:	device@lanana.org
 W:	http://lanana.org/docs/device-list/index.html
 L:	linux-kernel@vger.kernel.org

^ permalink raw reply	[flat|nested] 183+ messages in thread

* [PATCHSET 00/18] open-osd: OSD Initiator library for Linux
       [not found] <48876009.8010701@panasas.com>
@ 2008-12-22 12:32   ` Boaz Harrosh
  2008-11-04 16:09   ` Boaz Harrosh
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:32 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

OSD (Object-Based Storage Device) is a T10 SCSI command set that is designed
to provide efficient operation of input/output logical units that manage the
allocation, placement, and accessing of variable-size data-storage containers,
called objects. Objects are intended to contain operating system and application
constructs. Each object has associated attributes attached to it, which are
integral part of the object and provide metadata about the object. The standard
defines some common obligatory attributes, but user attributes can be added as
needed.

Whats new from last time:
- sitting in linux-next exposed some warnings in some ARCHs, (you guessed right
  printf of u64 types)
- Removed the user-mode osd_test application, this can be fetched from the
  out-of-tree git.
- Added implementation of, scsi-descriptor based, OSD sense buffer decoding.
  (See [PATCH 15/18])

The patches are cut over scsi-misc but apply cleanly over linus-2.6.28-rc9
and are intended for the 2.6.29 merge window.

To try out and run the library please visit
http://open-osd.org and follow the instructions there.

The submitted patchset is also available via git at:
   git://git.open-osd.org/linux-open-osd.git osd
   http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=osd

Or a compact out-of-tree repository that includes these patches 
plus some extras:
   git://git.open-osd.org/open-osd.git master
   http://git.open-osd.org/gitweb.cgi?p=open-osd.git;a=summary

here is the list of patches:

[PATCH 01/18] major.h: char-major number for OSD device driver
  Request for a new char-device major number

[PATCH 02/18] scsi: OSD_TYPE
  The OSD scsi type constant definition.

[PATCH 03/18] libosd: OSDv1 Headers
[PATCH 04/18] libosd: OSDv1 preliminary implementation
  Most basic, but usable library module (libosd.ko) including
  Kbuild file.

[PATCH 05/18] osd_uld: OSD scsi ULD
[PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel
[PATCH 07/18] osd_ktests: Add basic OSD tests
  These patches add a scsi ULD for OSD type devices. Please see
  commit logs for details.

[PATCH 08/18] libosd: attributes Support
[PATCH 09/18] osd_ktests: Test Attribute lists
[PATCH 10/18] libosd: OSD Security processing stubs
[PATCH 12/18] libosd: Add Flush and List-objects support
[PATCH 12/18] libosd: Not implemented commands
[PATCH 13/18] libosd: OSD version 2 Support
[PATCH 14/18] libosd: OSDv2 auto detection
[PATCH 15/18] libosd: SCSI/OSD Sense decoding support
  Up to here this is a fairly complete body of work, to support
  both OSD1 and OSD2 targets. Main pieces that are still missing
  from the library at this point are: The OSD2 capabilities structure,
  do to lack of an OSD target that supports it, so it was never tested.
  And the absence of any OSD-security methods other then NO_SECURITY.
  These will come in future versions.

[PATCH 16/18] osd: Documentation for OSD library
  Some reading about OSD in general and further usability instructions.
  Please comment on anything missing from this document.

[PATCH 17/18] osd: Kconfig file for in-tree builds
[PATCH 18/18] scsi: Add osd library to build system
  The in-tree compilation is only enabled at the end of the patchset.
  Run your favorite configure-tool to enable the library and osd_uld
  compilation. Default is off.
  The patchset is however fully bisectable, and compilable from the beginning,
  (by applying these 2 patches first).

Boaz Harrosh

^ permalink raw reply	[flat|nested] 183+ messages in thread

* [PATCHSET 00/18] open-osd: OSD Initiator library for Linux
@ 2008-12-22 12:32   ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:32 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

OSD (Object-Based Storage Device) is a T10 SCSI command set that is designed
to provide efficient operation of input/output logical units that manage the
allocation, placement, and accessing of variable-size data-storage containers,
called objects. Objects are intended to contain operating system and application
constructs. Each object has associated attributes attached to it, which are
integral part of the object and provide metadata about the object. The standard
defines some common obligatory attributes, but user attributes can be added as
needed.

Whats new from last time:
- sitting in linux-next exposed some warnings in some ARCHs, (you guessed right
  printf of u64 types)
- Removed the user-mode osd_test application, this can be fetched from the
  out-of-tree git.
- Added implementation of, scsi-descriptor based, OSD sense buffer decoding.
  (See [PATCH 15/18])

The patches are cut over scsi-misc but apply cleanly over linus-2.6.28-rc9
and are intended for the 2.6.29 merge window.

To try out and run the library please visit
http://open-osd.org and follow the instructions there.

The submitted patchset is also available via git at:
   git://git.open-osd.org/linux-open-osd.git osd
   http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=osd

Or a compact out-of-tree repository that includes these patches 
plus some extras:
   git://git.open-osd.org/open-osd.git master
   http://git.open-osd.org/gitweb.cgi?p=open-osd.git;a=summary

here is the list of patches:

[PATCH 01/18] major.h: char-major number for OSD device driver
  Request for a new char-device major number

[PATCH 02/18] scsi: OSD_TYPE
  The OSD scsi type constant definition.

[PATCH 03/18] libosd: OSDv1 Headers
[PATCH 04/18] libosd: OSDv1 preliminary implementation
  Most basic, but usable library module (libosd.ko) including
  Kbuild file.

[PATCH 05/18] osd_uld: OSD scsi ULD
[PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel
[PATCH 07/18] osd_ktests: Add basic OSD tests
  These patches add a scsi ULD for OSD type devices. Please see
  commit logs for details.

[PATCH 08/18] libosd: attributes Support
[PATCH 09/18] osd_ktests: Test Attribute lists
[PATCH 10/18] libosd: OSD Security processing stubs
[PATCH 12/18] libosd: Add Flush and List-objects support
[PATCH 12/18] libosd: Not implemented commands
[PATCH 13/18] libosd: OSD version 2 Support
[PATCH 14/18] libosd: OSDv2 auto detection
[PATCH 15/18] libosd: SCSI/OSD Sense decoding support
  Up to here this is a fairly complete body of work, to support
  both OSD1 and OSD2 targets. Main pieces that are still missing
  from the library at this point are: The OSD2 capabilities structure,
  do to lack of an OSD target that supports it, so it was never tested.
  And the absence of any OSD-security methods other then NO_SECURITY.
  These will come in future versions.

[PATCH 16/18] osd: Documentation for OSD library
  Some reading about OSD in general and further usability instructions.
  Please comment on anything missing from this document.

[PATCH 17/18] osd: Kconfig file for in-tree builds
[PATCH 18/18] scsi: Add osd library to build system
  The in-tree compilation is only enabled at the end of the patchset.
  Run your favorite configure-tool to enable the library and osd_uld
  compilation. Default is off.
  The patchset is however fully bisectable, and compilable from the beginning,
  (by applying these 2 patches first).

Boaz Harrosh

^ permalink raw reply	[flat|nested] 183+ messages in thread

* [PATCH 01/18] major.h: char-major number for OSD device driver
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 12:37     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:37 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

We need a major for a char device for our OSD device driver.
Attached is a proposed patch for the Documentation/devices.txt
and include/linux/major.h files.

I have allocated the *260* char device as it looked like the next
available on the lanana.org web-site
(http://lanana.org/docs/device-list/devices-2.6+.txt)

Any number will do. Please allocate a number for us

(See http:/open-osd.org for further information)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
CC: device at lanana <device@lanana.org>
---
 Documentation/devices.txt |    6 ++++++
 include/linux/major.h     |    1 +
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 2be0824..62254d4 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -3145,6 +3145,12 @@ Your cooperation is appreciated.
 		  1 = /dev/blockrom1	Second ROM card's translation layer interface
 		  ...
 
+260 char	OSD (Object-based-device) SCSI Device
+		  0 = /dev/osd0		First OSD Device
+		  1 = /dev/osd1		Second OSD Device
+		  ...
+		  255 = /dev/osd255	256th OSD Device
+
  ****	ADDITIONAL /dev DIRECTORY ENTRIES
 
 This section details additional entries that should or may exist in
diff --git a/include/linux/major.h b/include/linux/major.h
index 8824945..058ec15 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -171,5 +171,6 @@
 #define VIOTAPE_MAJOR		230
 
 #define BLOCK_EXT_MAJOR		259
+#define SCSI_OSD_MAJOR		260	/* open-osd's OSD scsi device */
 
 #endif
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 01/18] major.h: char-major number for OSD device driver
@ 2008-12-22 12:37     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:37 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

We need a major for a char device for our OSD device driver.
Attached is a proposed patch for the Documentation/devices.txt
and include/linux/major.h files.

I have allocated the *260* char device as it looked like the next
available on the lanana.org web-site
(http://lanana.org/docs/device-list/devices-2.6+.txt)

Any number will do. Please allocate a number for us

(See http:/open-osd.org for further information)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
CC: device at lanana <device@lanana.org>
---
 Documentation/devices.txt |    6 ++++++
 include/linux/major.h     |    1 +
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 2be0824..62254d4 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -3145,6 +3145,12 @@ Your cooperation is appreciated.
 		  1 = /dev/blockrom1	Second ROM card's translation layer interface
 		  ...
 
+260 char	OSD (Object-based-device) SCSI Device
+		  0 = /dev/osd0		First OSD Device
+		  1 = /dev/osd1		Second OSD Device
+		  ...
+		  255 = /dev/osd255	256th OSD Device
+
  ****	ADDITIONAL /dev DIRECTORY ENTRIES
 
 This section details additional entries that should or may exist in
diff --git a/include/linux/major.h b/include/linux/major.h
index 8824945..058ec15 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -171,5 +171,6 @@
 #define VIOTAPE_MAJOR		230
 
 #define BLOCK_EXT_MAJOR		259
+#define SCSI_OSD_MAJOR		260	/* open-osd's OSD scsi device */
 
 #endif
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 02/18] scsi: OSD_TYPE
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 12:39     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:39 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

- Define the OSD_TYPE scsi device and let it show up in scans

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/scsi_scan.c |    1 +
 include/scsi/scsi.h      |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 18486b5..4db6e3e 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -794,6 +794,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
 	case TYPE_ENCLOSURE:
 	case TYPE_COMM:
 	case TYPE_RAID:
+	case TYPE_OSD:
 		sdev->writeable = 1;
 		break;
 	case TYPE_ROM:
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index a109165..de1cef2 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -263,6 +263,7 @@ static inline int scsi_status_is_good(int status)
 #define TYPE_RAID           0x0c
 #define TYPE_ENCLOSURE      0x0d    /* Enclosure Services Device */
 #define TYPE_RBC	    0x0e
+#define TYPE_OSD            0x11
 #define TYPE_NO_LUN         0x7f
 
 /* SCSI protocols; these are taken from SPC-3 section 7.5 */
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 02/18] scsi: OSD_TYPE
@ 2008-12-22 12:39     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:39 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

- Define the OSD_TYPE scsi device and let it show up in scans

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/scsi_scan.c |    1 +
 include/scsi/scsi.h      |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 18486b5..4db6e3e 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -794,6 +794,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
 	case TYPE_ENCLOSURE:
 	case TYPE_COMM:
 	case TYPE_RAID:
+	case TYPE_OSD:
 		sdev->writeable = 1;
 		break;
 	case TYPE_ROM:
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index a109165..de1cef2 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -263,6 +263,7 @@ static inline int scsi_status_is_good(int status)
 #define TYPE_RAID           0x0c
 #define TYPE_ENCLOSURE      0x0d    /* Enclosure Services Device */
 #define TYPE_RBC	    0x0e
+#define TYPE_OSD            0x11
 #define TYPE_NO_LUN         0x7f
 
 /* SCSI protocols; these are taken from SPC-3 section 7.5 */
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 03/18] libosd: OSDv1 Headers
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 12:41     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:41 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 28329 bytes --]

Headers only patch.

osd_protocol.h
	Contains a C-fied definition of the T10 OSD standard
osd_types.h
	Contains CPU order common used types
osd_initiator.h
	API definition of the osd_initiator library
osd_sec.h
	Contains High level API for the security manager.

[Note that checkpatch spews errors on things that are valid in this context
and will not be fixed]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
 include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_sec.h       |   45 ++++
 include/scsi/osd_types.h     |   40 ++++
 4 files changed, 914 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_initiator.h
 create mode 100644 include/scsi/osd_protocol.h
 create mode 100644 include/scsi/osd_sec.h
 create mode 100644 include/scsi/osd_types.h

diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
new file mode 100644
index 0000000..1d92247
--- /dev/null
+++ b/include/scsi/osd_initiator.h
@@ -0,0 +1,332 @@
+/*
+ * osd_initiator.h - OSD initiator API definition
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_INITIATOR_H__
+#define __OSD_INITIATOR_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+#include <linux/blkdev.h>
+
+/* Note: "NI" in comments below means "Not Implemented yet" */
+
+/*
+ * Object-based Storage Device.
+ * This object represents an OSD device.
+ * It is not a full linux device in any way. It is only
+ * a place to hang resources associated with a Linux
+ * request Q and some default properties.
+ */
+struct osd_dev {
+	struct scsi_device *scsi_device;
+	unsigned def_timeout;
+};
+
+void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
+void osd_dev_fini(struct osd_dev *od);
+
+struct osd_request;
+typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
+
+struct osd_request {
+	struct osd_cdb cdb;
+	struct osd_data_out_integrity_info out_data_integ;
+	struct osd_data_in_integrity_info in_data_integ;
+
+	struct osd_dev *osd_dev;
+	struct request *request;
+
+	struct _osd_req_data_segment {
+		void *buff;
+		unsigned alloc_size; /* 0 here means: don't call kfree */
+		unsigned total_bytes;
+	} set_attr, enc_get_attr, get_attr;
+
+	struct _osd_io_info {
+		struct bio *bio;
+		u64 total_bytes;
+		struct request *req;
+		struct _osd_req_data_segment *last_seg;
+		u8 *pad_buff;
+	} out, in;
+
+	gfp_t alloc_flags;
+	unsigned timeout;
+	unsigned retries;
+	u8 sense[OSD_MAX_SENSE_LEN];
+	enum osd_attributes_mode attributes_mode;
+
+	osd_req_done_fn *async_done;
+	void *async_private;
+	int async_error;
+};
+
+/*
+ * How to use the osd library:
+ *
+ * osd_start_request
+ *	Allocates a request.
+ *
+ * osd_req_*
+ *	Call one of, to encode the desired operation.
+ *
+ * osd_add_{get,set}_attr
+ *	Optionally add attributes to the CDB, list or page mode.
+ *
+ * osd_finalize_request
+ *	Computes final data out/in offsets and signs the request,
+ *	making it ready for execution.
+ *
+ * osd_execute_request
+ *	May be called to execute it through the block layer. Other wise submit
+ *	the associated block request in some other way.
+ *
+ * After execution:
+ * osd_req_decode_sense
+ *	Decodes sense information to verify execution results.
+ *
+ * osd_req_decode_get_attr
+ *	Retrieve osd_add_get_attr_list() values if used.
+ *
+ * osd_end_request
+ *	Must be called to deallocate the request.
+ */
+
+/**
+ * osd_start_request - Allocate and initialize an osd_request
+ *
+ * @osd_dev:    OSD device that holds the scsi-device and default values
+ *              that the request is associated with.
+ * @gfp:        The allocation flags to use for request allocation, and all
+ *              subsequent allocations. This will be stored at
+ *              osd_request->alloc_flags, can be changed by user later
+ *
+ * Allocate osd_request and initialize all members to the
+ * default/initial state.
+ */
+struct osd_request *osd_start_request(struct osd_dev *od, gfp_t gfp);
+
+enum osd_req_options {
+	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
+	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
+
+	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
+};
+
+/**
+ * osd_finalize_request - Sign request and prepare request for execution
+ *
+ * @or:		osd_request to prepare
+ * @options:	combination of osd_req_options bit flags or 0.
+ * @cap:	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
+ *              The security manager as capabilities for this cdb.
+ * @cap_key:	The cryptographic key used to sign the cdb/data. Can be null
+ *              if NOSEC is used.
+ *
+ * The actual request and bios are only allocated here, so are the get_attr
+ * buffers that will receive the returned attributes. Copy's @cap to cdb.
+ * Sign the cdb/data with @cap_key.
+ */
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key);
+
+/**
+ * osd_execute_request - Execute the request synchronously through block-layer
+ *
+ * @or:		osd_request to Executed
+ *
+ * Calls blk_execute_rq to q the command and waits for completion.
+ */
+int osd_execute_request(struct osd_request *or);
+
+/**
+ * osd_execute_request_async - Execute the request without waitting.
+ *
+ * @or:                      - osd_request to Executed
+ * @done: (Optional)         - Called at end of execution
+ * @private:                 - Will be passed to @done function
+ *
+ * Calls blk_execute_rq_nowait to queue the command. When execution is done
+ * optionally calls @done with @private as parameter. @or->async_error will
+ * have the return code
+ */
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private);
+
+/**
+ * osd_end_request - return osd_request to free store
+ *
+ * @or:		osd_request to free
+ *
+ * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
+ */
+void osd_end_request(struct osd_request *or);
+
+/*
+ * CDB Encoding
+ *
+ * Note: call only one of the following methods.
+ */
+
+/*
+ * Device commands
+ */
+void osd_req_set_master_seed_xchg(struct osd_request *or, ...);/* NI */
+void osd_req_set_master_key(struct osd_request *or, ...);/* NI */
+
+void osd_req_format(struct osd_request *or, u64 tot_capacity);
+
+/* list all partitions
+ * @list header must be initialized to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values);
+
+void osd_req_perform_scsi_command(struct osd_request *or,
+	const u8 *cdb, ...);/* NI */
+void osd_req_task_management(struct osd_request *or, ...);/* NI */
+
+/*
+ * Partition commands
+ */
+void osd_req_create_partition(struct osd_request *or, osd_id partition);
+void osd_req_remove_partition(struct osd_request *or, osd_id partition);
+
+void osd_req_set_partition_key(struct osd_request *or,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
+
+/* list all collections in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+/* list all objects in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values);
+
+/*
+ * Collection commands
+ */
+void osd_req_create_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+void osd_req_remove_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+
+/* list all objects in the collection */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem);
+
+/* V2 only filtered list of objects in the collection */
+void osd_req_query(struct osd_request *or, ...);/* NI */
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values);
+
+void osd_req_get_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+void osd_req_set_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *);
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);
+void osd_req_append(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out);/* NI */
+void osd_req_create_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
+void osd_req_clear(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
+void osd_req_punch(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
+
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values,
+	/*V2*/ u64 offset, /*V2*/ u64 len);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_in, u64 offset);
+
+/*
+ * Root/Partition/Collection/Object Attributes commands
+ */
+
+/* get before set */
+void osd_req_get_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/* set before get */
+void osd_req_set_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/*
+ * Attributes appended to most commands
+ */
+
+/* Attributes List mode (or V2 CDB) */
+  /*
+   * TODO: In ver2 if at finalize time only one attr was set and no gets,
+   * then the Attributes CDB mode is used automatically to save IO.
+   */
+
+/* set a list of attributes. */
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/* get a list of attributes */
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/*
+ * Attributes list decoding
+ * Must be called after osd_request.request was executed
+ * It is called in a loop to decode the returned get_attr
+ * (see osd_add_get_attr)
+ */
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *, int *nelem, void **iterator);
+
+/* Attributes Page mode */
+
+/*
+ * Read an attribute page and optionally set one attribute
+ *
+ * Retrieves the attribute page directly to a user buffer.
+ * @attr_page_data shall stay valid until end of execution.
+ * See osd_attributes.h for common page structures
+ */
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attr_page_data, unsigned max_page_len,
+	const struct osd_attr *set_one);
+
+#endif /* __OSD_LIB_H__ */
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
new file mode 100644
index 0000000..eeb899b
--- /dev/null
+++ b/include/scsi/osd_protocol.h
@@ -0,0 +1,497 @@
+/*
+ * osd_protocol.h - OSD T10 standard C definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_PROTOCOL_H__
+#define __OSD_PROTOCOL_H__
+
+#include <linux/types.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+enum {
+	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
+	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
+	OSDv1_CAP_LEN = 80,
+	/* Latest supported version */
+	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
+	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
+	OSD_CAP_LEN = OSDv1_CAP_LEN,
+
+	OSD_SYSTEMID_LEN = 20,
+	OSD_CRYPTO_KEYID_SIZE = 20,
+	OSD_CRYPTO_SEED_SIZE = 4,
+	OSD_CRYPTO_NONCE_SIZE = 12,
+	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
+
+	OSD_PARTITION_FIRST_ID = 0x10000,
+	OSD_OBJECT_FIRST_ID = 0x10000,
+};
+
+/* (osd-r10 5.2.4)
+ * osd2r03: 5.2.3 Caching control bits
+ */
+enum osd_options_byte {
+	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
+	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
+};
+
+/*
+ * osd2r03: 5.2.5 Isolation.
+ * First 3 bits, V2-only.
+ * Also for attr 110h "default isolation method" at Root Information page
+ */
+enum osd_options_byte_isolation {
+	OSD_ISOLATION_DEFAULT = 0,
+	OSD_ISOLATION_NONE = 1,
+	OSD_ISOLATION_STRICT = 2,
+	OSD_ISOLATION_RANGE = 4,
+	OSD_ISOLATION_FUNCTIONAL = 5,
+	OSD_ISOLATION_VENDOR = 7,
+};
+
+/* (osd-r10: 6.7)
+ * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
+ */
+enum osd_options_flush_scope_values {
+	OSD_CDB_FLUSH_ALL = 0,
+	OSD_CDB_FLUSH_ATTR_ONLY = 1,
+
+	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
+	/* V2-only */
+	OSD_CDB_FLUSH_ALL_RANGE = 2,
+};
+
+/* osd2r03: 5.2.10 Timestamps control */
+enum {
+	OSD_CDB_NORMAL_TIMESTAMPS = 0,
+	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
+};
+
+/* (osd-r10: 5.2.2.1)
+ * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
+ *	2 bits at second nibble of command_specific_options byte
+ */
+enum osd_attributes_mode {
+	/* V2-only */
+	OSD_CDB_SET_ONE_ATTR = 0x10,
+
+	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
+	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
+
+	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
+};
+
+/* (osd-r10: 4.12.5)
+ * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
+ *	byte offset = mantissa * (2^(exponent+8))
+ *	struct {
+ *		unsigned mantissa: 28;
+ *		int exponent: 04;
+ *	}
+ */
+typedef __be32 __bitwise osd_cdb_offset;
+
+enum {
+	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
+	OSD_OFFSET_MAX_BITS = 28,
+
+	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MAX_SHIFT = 16,
+};
+
+/* Return the smallest allowed encoded offset that contains @offset.
+ *
+ * The actual encoded offset returned is @offset + *padding.
+ * (up to max_shift, non-inclusive)
+ */
+osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
+	int min_shift, int max_shift);
+
+/* Minimum alignment is 256 bytes
+ * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
+ * which is 8 to 23 but IBM code restricts it to 16, so be it.
+ */
+static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
+/* osd2r03: 5.2.1 Overview */
+struct osd_cdb_head {
+	struct scsi_varlen_cdb_hdr varlen_cdb;
+/*10*/	u8		options;
+	u8		command_specific_options;
+	u8		timestamp_control;
+/*13*/	u8		reserved1[3];
+/*16*/	__be64		partition;
+/*24*/	__be64		object;
+/*32*/	union { /* V1 vs V2 alignment differences */
+		struct __osdv1_cdb_addr_len {
+/*32*/			__be32 		list_identifier;/* Rarely used */
+/*36*/			__be64		length;
+/*44*/			__be64		start_address;
+		} __packed v1;
+	};
+/*52*/	union { /* selected attributes mode Page/List/Single */
+		struct osd_attributes_page_mode {
+/*52*/			__be32		get_attr_page;
+/*56*/			__be32		get_attr_alloc_length;
+/*60*/			osd_cdb_offset	get_attr_offset;
+
+/*64*/			__be32		set_attr_page;
+/*68*/			__be32		set_attr_id;
+/*72*/			__be32		set_attr_length;
+/*76*/			osd_cdb_offset	set_attr_offset;
+/*80*/		} __packed attrs_page;
+
+		struct osd_attributes_list_mode {
+/*52*/			__be32		get_attr_desc_bytes;
+/*56*/			osd_cdb_offset	get_attr_desc_offset;
+
+/*60*/			__be32		get_attr_alloc_length;
+/*64*/			osd_cdb_offset	get_attr_offset;
+
+/*68*/			__be32		set_attr_bytes;
+/*72*/			osd_cdb_offset	set_attr_offset;
+			__be32 not_used;
+/*80*/		} __packed attrs_list;
+
+		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
+		struct osd_attributes_cdb_mode {
+/*52*/			__be32		set_attr_page;
+/*56*/			__be32		set_attr_id;
+/*60*/			__be16		set_attr_len;
+/*62*/			u8		set_attr_val[18];
+/*80*/		} __packed attrs_cdb;
+/*52*/		u8 get_set_attributes_parameters[28];
+	};
+} __packed;
+/*80*/
+
+/*160 v1*/
+struct osd_security_parameters {
+/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*192*/osd_cdb_offset	data_in_integrity_check_offset;
+/*196*/osd_cdb_offset	data_out_integrity_check_offset;
+} __packed;
+/*200 v1*/
+
+struct osdv1_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSDv1_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
+struct osd_cdb {
+	union {
+		struct osdv1_cdb v1;
+		u8 buff[OSD_TOTAL_CDB_LEN];
+	};
+} __packed;
+
+static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
+{
+	return (struct osd_cdb_head *)ocdb->buff;
+}
+
+/* define both version actions
+ * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
+ */
+#define OSD_ACT___(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
+
+/* V2 only actions */
+#define OSD_ACT_V2(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
+
+#define OSD_ACT_V1_V2(Name, Num1, Num2) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
+
+enum osd_service_actions {
+	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
+	OSD_ACT___(FORMAT_OSD,			0x01)
+	OSD_ACT___(CREATE,			0x02)
+	OSD_ACT___(LIST,			0x03)
+	OSD_ACT_V2(PUNCH,			0x04)
+	OSD_ACT___(READ,			0x05)
+	OSD_ACT___(WRITE,			0x06)
+	OSD_ACT___(APPEND,			0x07)
+	OSD_ACT___(FLUSH,			0x08)
+	OSD_ACT_V2(CLEAR,			0x09)
+	OSD_ACT___(REMOVE,			0x0A)
+	OSD_ACT___(CREATE_PARTITION,		0x0B)
+	OSD_ACT___(REMOVE_PARTITION,		0x0C)
+	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
+	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
+	OSD_ACT___(CREATE_AND_WRITE,		0x12)
+	OSD_ACT___(CREATE_COLLECTION,		0x15)
+	OSD_ACT___(REMOVE_COLLECTION,		0x16)
+	OSD_ACT___(LIST_COLLECTION,		0x17)
+	OSD_ACT___(SET_KEY,			0x18)
+	OSD_ACT___(SET_MASTER_KEY,		0x19)
+	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
+	OSD_ACT___(FLUSH_PARTITION,		0x1B)
+	OSD_ACT___(FLUSH_OSD,			0x1C)
+
+	OSD_ACT_V2(QUERY,			0x20)
+	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
+	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
+	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
+	OSD_ACT_V2(READ_MAP,			0x31)
+
+	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
+	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
+	/* 0x8F80 to 0x8FFF are Vendor specific */
+};
+
+/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
+struct osd_attributes_list_attrid {
+	__be32 page;
+	__be32 attr_id;
+} __packed;
+
+/*
+ * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
+ *                  for setting attributes
+ */
+struct osd_attributes_list_element {
+	__be32 page;
+	__be32 attr_id;
+	__be16 attr_bytes;
+	u8 attr_val[0];
+} __packed;
+
+enum {
+	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+};
+
+enum {
+	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
+	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
+};
+
+static inline unsigned osdv1_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
+}
+
+/*
+ * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
+ */
+enum osd_attr_list_types {
+	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
+	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
+	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
+	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
+};
+
+/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
+struct osd_attributes_list_multi_header {
+	__be64 object_id;
+	u8 object_type; /* object_type enum below */
+	u8 reserved[5];
+	__be16 list_bytes;
+	/* followed by struct osd_attributes_list_element's */
+};
+
+struct osdv1_attributes_list_header {
+	u8 type;	/* low 4-bit only */
+	u8 pad;
+	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
+{
+	return be16_to_cpu(h->list_bytes);
+}
+
+/* (osd-r10 6.13)
+ * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
+ *	for root_lstchg below
+ */
+enum {
+	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
+	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
+};
+
+/*
+ * osd2r03: 6.15.2 LIST command parameter data
+ * (Also for LIST COLLECTION)
+ */
+struct osd_obj_id_list {
+	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
+	__be64 continuation_id;
+	__be32 list_identifier;
+	u8 pad[3];
+	u8 root_lstchg;
+	__be64 object_ids[0];
+} __packed;
+
+static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
+	bool *is_changed)
+{
+	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
+	return 0 != list->continuation_id;
+}
+
+/*
+ * osd2r03: 4.12.4.5 The ALLDATA security method
+ */
+struct osd_data_out_integrity_info {
+	__be64 data_bytes;
+	__be64 set_attributes_bytes;
+	__be64 get_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_data_in_integrity_info {
+	__be64 data_bytes;
+	__be64 retrieved_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_timestamp {
+	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
+} __packed;
+/* FIXME: define helper functions to convert to/from osd time format */
+
+/*
+ * Capability & Security definitions
+ * osd2r03: 4.11.2.2 Capability format
+ * osd2r03: 5.2.8 Security parameters
+ */
+
+struct osd_key_identifier {
+	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+} __packed;
+
+/* for osd_capability.format */
+enum {
+	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
+	OSD_SEC_CAP_FORMAT_VER1 = 1,
+	OSD_SEC_CAP_FORMAT_VER2 = 2,
+};
+
+/* security_method */
+enum {
+	OSD_SEC_NOSEC = 0,
+	OSD_SEC_CAPKEY = 1,
+	OSD_SEC_CMDRSP = 2,
+	OSD_SEC_ALLDATA = 3,
+};
+
+enum object_type {
+	OSD_SEC_OBJ_ROOT = 0x1,
+	OSD_SEC_OBJ_PARTITION = 0x2,
+	OSD_SEC_OBJ_COLLECTION = 0x40,
+	OSD_SEC_OBJ_USER = 0x80,
+};
+
+enum osd_capability_bit_masks {
+	OSD_SEC_CAP_APPEND	= BIT(0),
+	OSD_SEC_CAP_OBJ_MGMT	= BIT(1),
+	OSD_SEC_CAP_REMOVE	= BIT(2),
+	OSD_SEC_CAP_CREATE	= BIT(3),
+	OSD_SEC_CAP_SET_ATTR	= BIT(4),
+	OSD_SEC_CAP_GET_ATTR	= BIT(5),
+	OSD_SEC_CAP_WRITE	= BIT(6),
+	OSD_SEC_CAP_READ	= BIT(7),
+
+	OSD_SEC_CAP_NONE1	= BIT(8),
+	OSD_SEC_CAP_NONE2	= BIT(9),
+	OSD_SEC_CAP_NONE3	= BIT(10),
+	OSD_SEC_CAP_QUERY	= BIT(11), /*v2 only*/
+	OSD_SEC_CAP_M_OBJECT	= BIT(12), /*v2 only*/
+	OSD_SEC_CAP_POL_SEC	= BIT(13),
+	OSD_SEC_CAP_GLOBAL	= BIT(14),
+	OSD_SEC_CAP_DEV_MGMT	= BIT(15),
+};
+
+/* for object_descriptor_type (hi nibble used) */
+enum {
+	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
+	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
+	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
+	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
+};
+
+/* (osd-r10:4.9.2.2)
+ * osd2r03:4.11.2.2 Capability format
+ */
+struct osd_capability_head {
+	u8 format; /* low nibble */
+	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
+	u8 security_method;
+	u8 reserved1;
+/*04*/	struct osd_timestamp expiration_time;
+/*10*/	u8 audit[20];
+/*30*/	u8 discriminator[12];
+/*42*/	struct osd_timestamp object_created_time;
+/*48*/	u8 object_type;
+/*49*/	u8 permissions_bit_mask[5];
+/*54*/	u8 reserved2;
+/*55*/	u8 object_descriptor_type; /* high nibble */
+} __packed;
+
+/*56 v1*/
+struct osdv1_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 policy_access_tag;
+/*60*/			__be64 allowed_partition_id;
+/*68*/			__be64 allowed_object_id;
+/*76*/			__be32 reserved;
+		} __packed obj_desc;
+
+/*56*/		u8 object_descriptor[24];
+	};
+} __packed;
+/*80 v1*/
+
+struct osd_capability {
+	struct osd_capability_head h;
+	struct osdv1_cap_object_descriptor od;
+} __packed;
+
+/**
+ * osd_sec_set_caps - set cap-bits into the capabilities header
+ *
+ * @cap:	The osd_capability_head to set cap bits to.
+ * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
+ *
+ * permissions_bit_mask is unaligned use below to set into caps
+ * in a version independent way
+ */
+static inline void osd_sec_set_caps(struct osd_capability_head *cap,
+	u16 bit_mask)
+{
+	/*
+	 *Note: The bits above are defined LE order this is because this way
+	 *      they can grow in the future to more then 16, and still retain
+	 *      there constant values.
+	 */
+	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
+}
+
+#endif /* ndef __OSD_PROTOCOL_H__ */
diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h
new file mode 100644
index 0000000..4c09fee
--- /dev/null
+++ b/include/scsi/osd_sec.h
@@ -0,0 +1,45 @@
+/*
+ * osd_sec.h - OSD security manager API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_SEC_H__
+#define __OSD_SEC_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/*
+ * Contains types and constants of osd capabilities and security
+ * encoding/decoding.
+ * API is trying to keep security abstract so initiator of an object
+ * based pNFS client knows as little as possible about security and
+ * capabilities. It is the Server's osd-initiator place to know more.
+ * Also can be used by osd-target.
+ */
+void osd_sec_encode_caps(void *caps, ...);/* NI */
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1);
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_params);
+
+/* Conditionally sign the CDB according to security setting in ocdb
+ * with cap_key */
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key);
+
+/* Unconditionally sign the BIO data with cap_key.
+ * Check for osd_is_sec_alldata() was done prior to calling this. */
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key);
+
+/* Version independent copy of caps into the cdb */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps);
+
+#endif /* ndef __OSD_SEC_H__ */
diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h
new file mode 100644
index 0000000..ea5372d
--- /dev/null
+++ b/include/scsi/osd_types.h
@@ -0,0 +1,40 @@
+/*
+ * osd_types.h - Types and constants which are not part of the protocol.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Contains types and constants that are implementation specific and are
+ * used by more than one part of the osd library.
+ *     (Eg initiator/target/security_manager/...)
+ */
+#ifndef __OSD_TYPES_H__
+#define __OSD_TYPES_H__
+
+struct osd_systemid {
+	u8 data[OSD_SYSTEMID_LEN];
+};
+
+typedef u64 __bitwise osd_id;
+
+struct osd_obj_id {
+	osd_id partition;
+	osd_id id;
+};
+
+static const struct __weak osd_obj_id osd_root_object = {0, 0};
+
+struct osd_attr {
+	u32 page;
+	u32 attr_id;
+	u16 len;		/* byte count of operand */
+	void *val_ptr;		/* in network order */
+};
+
+#endif /* ndef __OSD_TYPES_H__ */
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 03/18] libosd: OSDv1 Headers
@ 2008-12-22 12:41     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:41 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Headers only patch.

osd_protocol.h
	Contains a C-fied definition of the T10 OSD standard
osd_types.h
	Contains CPU order common used types
osd_initiator.h
	API definition of the osd_initiator library
osd_sec.h
	Contains High level API for the security manager.

[Note that checkpatch spews errors on things that are valid in this context
and will not be fixed]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
 include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_sec.h       |   45 ++++
 include/scsi/osd_types.h     |   40 ++++
 4 files changed, 914 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_initiator.h
 create mode 100644 include/scsi/osd_protocol.h
 create mode 100644 include/scsi/osd_sec.h
 create mode 100644 include/scsi/osd_types.h

diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
new file mode 100644
index 0000000..1d92247
--- /dev/null
+++ b/include/scsi/osd_initiator.h
@@ -0,0 +1,332 @@
+/*
+ * osd_initiator.h - OSD initiator API definition
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_INITIATOR_H__
+#define __OSD_INITIATOR_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+#include <linux/blkdev.h>
+
+/* Note: "NI" in comments below means "Not Implemented yet" */
+
+/*
+ * Object-based Storage Device.
+ * This object represents an OSD device.
+ * It is not a full linux device in any way. It is only
+ * a place to hang resources associated with a Linux
+ * request Q and some default properties.
+ */
+struct osd_dev {
+	struct scsi_device *scsi_device;
+	unsigned def_timeout;
+};
+
+void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
+void osd_dev_fini(struct osd_dev *od);
+
+struct osd_request;
+typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
+
+struct osd_request {
+	struct osd_cdb cdb;
+	struct osd_data_out_integrity_info out_data_integ;
+	struct osd_data_in_integrity_info in_data_integ;
+
+	struct osd_dev *osd_dev;
+	struct request *request;
+
+	struct _osd_req_data_segment {
+		void *buff;
+		unsigned alloc_size; /* 0 here means: don't call kfree */
+		unsigned total_bytes;
+	} set_attr, enc_get_attr, get_attr;
+
+	struct _osd_io_info {
+		struct bio *bio;
+		u64 total_bytes;
+		struct request *req;
+		struct _osd_req_data_segment *last_seg;
+		u8 *pad_buff;
+	} out, in;
+
+	gfp_t alloc_flags;
+	unsigned timeout;
+	unsigned retries;
+	u8 sense[OSD_MAX_SENSE_LEN];
+	enum osd_attributes_mode attributes_mode;
+
+	osd_req_done_fn *async_done;
+	void *async_private;
+	int async_error;
+};
+
+/*
+ * How to use the osd library:
+ *
+ * osd_start_request
+ *	Allocates a request.
+ *
+ * osd_req_*
+ *	Call one of, to encode the desired operation.
+ *
+ * osd_add_{get,set}_attr
+ *	Optionally add attributes to the CDB, list or page mode.
+ *
+ * osd_finalize_request
+ *	Computes final data out/in offsets and signs the request,
+ *	making it ready for execution.
+ *
+ * osd_execute_request
+ *	May be called to execute it through the block layer. Other wise submit
+ *	the associated block request in some other way.
+ *
+ * After execution:
+ * osd_req_decode_sense
+ *	Decodes sense information to verify execution results.
+ *
+ * osd_req_decode_get_attr
+ *	Retrieve osd_add_get_attr_list() values if used.
+ *
+ * osd_end_request
+ *	Must be called to deallocate the request.
+ */
+
+/**
+ * osd_start_request - Allocate and initialize an osd_request
+ *
+ * @osd_dev:    OSD device that holds the scsi-device and default values
+ *              that the request is associated with.
+ * @gfp:        The allocation flags to use for request allocation, and all
+ *              subsequent allocations. This will be stored at
+ *              osd_request->alloc_flags, can be changed by user later
+ *
+ * Allocate osd_request and initialize all members to the
+ * default/initial state.
+ */
+struct osd_request *osd_start_request(struct osd_dev *od, gfp_t gfp);
+
+enum osd_req_options {
+	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
+	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
+
+	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
+};
+
+/**
+ * osd_finalize_request - Sign request and prepare request for execution
+ *
+ * @or:		osd_request to prepare
+ * @options:	combination of osd_req_options bit flags or 0.
+ * @cap:	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
+ *              The security manager as capabilities for this cdb.
+ * @cap_key:	The cryptographic key used to sign the cdb/data. Can be null
+ *              if NOSEC is used.
+ *
+ * The actual request and bios are only allocated here, so are the get_attr
+ * buffers that will receive the returned attributes. Copy's @cap to cdb.
+ * Sign the cdb/data with @cap_key.
+ */
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key);
+
+/**
+ * osd_execute_request - Execute the request synchronously through block-layer
+ *
+ * @or:		osd_request to Executed
+ *
+ * Calls blk_execute_rq to q the command and waits for completion.
+ */
+int osd_execute_request(struct osd_request *or);
+
+/**
+ * osd_execute_request_async - Execute the request without waitting.
+ *
+ * @or:                      - osd_request to Executed
+ * @done: (Optional)         - Called at end of execution
+ * @private:                 - Will be passed to @done function
+ *
+ * Calls blk_execute_rq_nowait to queue the command. When execution is done
+ * optionally calls @done with @private as parameter. @or->async_error will
+ * have the return code
+ */
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private);
+
+/**
+ * osd_end_request - return osd_request to free store
+ *
+ * @or:		osd_request to free
+ *
+ * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
+ */
+void osd_end_request(struct osd_request *or);
+
+/*
+ * CDB Encoding
+ *
+ * Note: call only one of the following methods.
+ */
+
+/*
+ * Device commands
+ */
+void osd_req_set_master_seed_xchg(struct osd_request *or, ...);/* NI */
+void osd_req_set_master_key(struct osd_request *or, ...);/* NI */
+
+void osd_req_format(struct osd_request *or, u64 tot_capacity);
+
+/* list all partitions
+ * @list header must be initialized to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values);
+
+void osd_req_perform_scsi_command(struct osd_request *or,
+	const u8 *cdb, ...);/* NI */
+void osd_req_task_management(struct osd_request *or, ...);/* NI */
+
+/*
+ * Partition commands
+ */
+void osd_req_create_partition(struct osd_request *or, osd_id partition);
+void osd_req_remove_partition(struct osd_request *or, osd_id partition);
+
+void osd_req_set_partition_key(struct osd_request *or,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
+
+/* list all collections in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+/* list all objects in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values);
+
+/*
+ * Collection commands
+ */
+void osd_req_create_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+void osd_req_remove_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+
+/* list all objects in the collection */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem);
+
+/* V2 only filtered list of objects in the collection */
+void osd_req_query(struct osd_request *or, ...);/* NI */
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values);
+
+void osd_req_get_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+void osd_req_set_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *);
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);
+void osd_req_append(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out);/* NI */
+void osd_req_create_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
+void osd_req_clear(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
+void osd_req_punch(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
+
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values,
+	/*V2*/ u64 offset, /*V2*/ u64 len);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_in, u64 offset);
+
+/*
+ * Root/Partition/Collection/Object Attributes commands
+ */
+
+/* get before set */
+void osd_req_get_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/* set before get */
+void osd_req_set_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/*
+ * Attributes appended to most commands
+ */
+
+/* Attributes List mode (or V2 CDB) */
+  /*
+   * TODO: In ver2 if at finalize time only one attr was set and no gets,
+   * then the Attributes CDB mode is used automatically to save IO.
+   */
+
+/* set a list of attributes. */
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/* get a list of attributes */
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/*
+ * Attributes list decoding
+ * Must be called after osd_request.request was executed
+ * It is called in a loop to decode the returned get_attr
+ * (see osd_add_get_attr)
+ */
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *, int *nelem, void **iterator);
+
+/* Attributes Page mode */
+
+/*
+ * Read an attribute page and optionally set one attribute
+ *
+ * Retrieves the attribute page directly to a user buffer.
+ * @attr_page_data shall stay valid until end of execution.
+ * See osd_attributes.h for common page structures
+ */
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attr_page_data, unsigned max_page_len,
+	const struct osd_attr *set_one);
+
+#endif /* __OSD_LIB_H__ */
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
new file mode 100644
index 0000000..eeb899b
--- /dev/null
+++ b/include/scsi/osd_protocol.h
@@ -0,0 +1,497 @@
+/*
+ * osd_protocol.h - OSD T10 standard C definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_PROTOCOL_H__
+#define __OSD_PROTOCOL_H__
+
+#include <linux/types.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+enum {
+	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
+	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
+	OSDv1_CAP_LEN = 80,
+	/* Latest supported version */
+	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
+	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
+	OSD_CAP_LEN = OSDv1_CAP_LEN,
+
+	OSD_SYSTEMID_LEN = 20,
+	OSD_CRYPTO_KEYID_SIZE = 20,
+	OSD_CRYPTO_SEED_SIZE = 4,
+	OSD_CRYPTO_NONCE_SIZE = 12,
+	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
+
+	OSD_PARTITION_FIRST_ID = 0x10000,
+	OSD_OBJECT_FIRST_ID = 0x10000,
+};
+
+/* (osd-r10 5.2.4)
+ * osd2r03: 5.2.3 Caching control bits
+ */
+enum osd_options_byte {
+	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
+	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
+};
+
+/*
+ * osd2r03: 5.2.5 Isolation.
+ * First 3 bits, V2-only.
+ * Also for attr 110h "default isolation method" at Root Information page
+ */
+enum osd_options_byte_isolation {
+	OSD_ISOLATION_DEFAULT = 0,
+	OSD_ISOLATION_NONE = 1,
+	OSD_ISOLATION_STRICT = 2,
+	OSD_ISOLATION_RANGE = 4,
+	OSD_ISOLATION_FUNCTIONAL = 5,
+	OSD_ISOLATION_VENDOR = 7,
+};
+
+/* (osd-r10: 6.7)
+ * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
+ */
+enum osd_options_flush_scope_values {
+	OSD_CDB_FLUSH_ALL = 0,
+	OSD_CDB_FLUSH_ATTR_ONLY = 1,
+
+	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
+	/* V2-only */
+	OSD_CDB_FLUSH_ALL_RANGE = 2,
+};
+
+/* osd2r03: 5.2.10 Timestamps control */
+enum {
+	OSD_CDB_NORMAL_TIMESTAMPS = 0,
+	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
+};
+
+/* (osd-r10: 5.2.2.1)
+ * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
+ *	2 bits at second nibble of command_specific_options byte
+ */
+enum osd_attributes_mode {
+	/* V2-only */
+	OSD_CDB_SET_ONE_ATTR = 0x10,
+
+	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
+	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
+
+	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
+};
+
+/* (osd-r10: 4.12.5)
+ * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
+ *	byte offset = mantissa * (2^(exponent+8))
+ *	struct {
+ *		unsigned mantissa: 28;
+ *		int exponent: 04;
+ *	}
+ */
+typedef __be32 __bitwise osd_cdb_offset;
+
+enum {
+	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
+	OSD_OFFSET_MAX_BITS = 28,
+
+	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MAX_SHIFT = 16,
+};
+
+/* Return the smallest allowed encoded offset that contains @offset.
+ *
+ * The actual encoded offset returned is @offset + *padding.
+ * (up to max_shift, non-inclusive)
+ */
+osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
+	int min_shift, int max_shift);
+
+/* Minimum alignment is 256 bytes
+ * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
+ * which is 8 to 23 but IBM code restricts it to 16, so be it.
+ */
+static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
+/* osd2r03: 5.2.1 Overview */
+struct osd_cdb_head {
+	struct scsi_varlen_cdb_hdr varlen_cdb;
+/*10*/	u8		options;
+	u8		command_specific_options;
+	u8		timestamp_control;
+/*13*/	u8		reserved1[3];
+/*16*/	__be64		partition;
+/*24*/	__be64		object;
+/*32*/	union { /* V1 vs V2 alignment differences */
+		struct __osdv1_cdb_addr_len {
+/*32*/			__be32 		list_identifier;/* Rarely used */
+/*36*/			__be64		length;
+/*44*/			__be64		start_address;
+		} __packed v1;
+	};
+/*52*/	union { /* selected attributes mode Page/List/Single */
+		struct osd_attributes_page_mode {
+/*52*/			__be32		get_attr_page;
+/*56*/			__be32		get_attr_alloc_length;
+/*60*/			osd_cdb_offset	get_attr_offset;
+
+/*64*/			__be32		set_attr_page;
+/*68*/			__be32		set_attr_id;
+/*72*/			__be32		set_attr_length;
+/*76*/			osd_cdb_offset	set_attr_offset;
+/*80*/		} __packed attrs_page;
+
+		struct osd_attributes_list_mode {
+/*52*/			__be32		get_attr_desc_bytes;
+/*56*/			osd_cdb_offset	get_attr_desc_offset;
+
+/*60*/			__be32		get_attr_alloc_length;
+/*64*/			osd_cdb_offset	get_attr_offset;
+
+/*68*/			__be32		set_attr_bytes;
+/*72*/			osd_cdb_offset	set_attr_offset;
+			__be32 not_used;
+/*80*/		} __packed attrs_list;
+
+		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
+		struct osd_attributes_cdb_mode {
+/*52*/			__be32		set_attr_page;
+/*56*/			__be32		set_attr_id;
+/*60*/			__be16		set_attr_len;
+/*62*/			u8		set_attr_val[18];
+/*80*/		} __packed attrs_cdb;
+/*52*/		u8 get_set_attributes_parameters[28];
+	};
+} __packed;
+/*80*/
+
+/*160 v1*/
+struct osd_security_parameters {
+/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*192*/osd_cdb_offset	data_in_integrity_check_offset;
+/*196*/osd_cdb_offset	data_out_integrity_check_offset;
+} __packed;
+/*200 v1*/
+
+struct osdv1_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSDv1_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
+struct osd_cdb {
+	union {
+		struct osdv1_cdb v1;
+		u8 buff[OSD_TOTAL_CDB_LEN];
+	};
+} __packed;
+
+static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
+{
+	return (struct osd_cdb_head *)ocdb->buff;
+}
+
+/* define both version actions
+ * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
+ */
+#define OSD_ACT___(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
+
+/* V2 only actions */
+#define OSD_ACT_V2(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
+
+#define OSD_ACT_V1_V2(Name, Num1, Num2) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
+
+enum osd_service_actions {
+	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
+	OSD_ACT___(FORMAT_OSD,			0x01)
+	OSD_ACT___(CREATE,			0x02)
+	OSD_ACT___(LIST,			0x03)
+	OSD_ACT_V2(PUNCH,			0x04)
+	OSD_ACT___(READ,			0x05)
+	OSD_ACT___(WRITE,			0x06)
+	OSD_ACT___(APPEND,			0x07)
+	OSD_ACT___(FLUSH,			0x08)
+	OSD_ACT_V2(CLEAR,			0x09)
+	OSD_ACT___(REMOVE,			0x0A)
+	OSD_ACT___(CREATE_PARTITION,		0x0B)
+	OSD_ACT___(REMOVE_PARTITION,		0x0C)
+	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
+	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
+	OSD_ACT___(CREATE_AND_WRITE,		0x12)
+	OSD_ACT___(CREATE_COLLECTION,		0x15)
+	OSD_ACT___(REMOVE_COLLECTION,		0x16)
+	OSD_ACT___(LIST_COLLECTION,		0x17)
+	OSD_ACT___(SET_KEY,			0x18)
+	OSD_ACT___(SET_MASTER_KEY,		0x19)
+	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
+	OSD_ACT___(FLUSH_PARTITION,		0x1B)
+	OSD_ACT___(FLUSH_OSD,			0x1C)
+
+	OSD_ACT_V2(QUERY,			0x20)
+	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
+	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
+	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
+	OSD_ACT_V2(READ_MAP,			0x31)
+
+	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
+	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
+	/* 0x8F80 to 0x8FFF are Vendor specific */
+};
+
+/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
+struct osd_attributes_list_attrid {
+	__be32 page;
+	__be32 attr_id;
+} __packed;
+
+/*
+ * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
+ *                  for setting attributes
+ */
+struct osd_attributes_list_element {
+	__be32 page;
+	__be32 attr_id;
+	__be16 attr_bytes;
+	u8 attr_val[0];
+} __packed;
+
+enum {
+	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+};
+
+enum {
+	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
+	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
+};
+
+static inline unsigned osdv1_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
+}
+
+/*
+ * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
+ */
+enum osd_attr_list_types {
+	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
+	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
+	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
+	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
+};
+
+/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
+struct osd_attributes_list_multi_header {
+	__be64 object_id;
+	u8 object_type; /* object_type enum below */
+	u8 reserved[5];
+	__be16 list_bytes;
+	/* followed by struct osd_attributes_list_element's */
+};
+
+struct osdv1_attributes_list_header {
+	u8 type;	/* low 4-bit only */
+	u8 pad;
+	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
+{
+	return be16_to_cpu(h->list_bytes);
+}
+
+/* (osd-r10 6.13)
+ * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
+ *	for root_lstchg below
+ */
+enum {
+	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
+	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
+};
+
+/*
+ * osd2r03: 6.15.2 LIST command parameter data
+ * (Also for LIST COLLECTION)
+ */
+struct osd_obj_id_list {
+	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
+	__be64 continuation_id;
+	__be32 list_identifier;
+	u8 pad[3];
+	u8 root_lstchg;
+	__be64 object_ids[0];
+} __packed;
+
+static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
+	bool *is_changed)
+{
+	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
+	return 0 != list->continuation_id;
+}
+
+/*
+ * osd2r03: 4.12.4.5 The ALLDATA security method
+ */
+struct osd_data_out_integrity_info {
+	__be64 data_bytes;
+	__be64 set_attributes_bytes;
+	__be64 get_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_data_in_integrity_info {
+	__be64 data_bytes;
+	__be64 retrieved_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_timestamp {
+	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
+} __packed;
+/* FIXME: define helper functions to convert to/from osd time format */
+
+/*
+ * Capability & Security definitions
+ * osd2r03: 4.11.2.2 Capability format
+ * osd2r03: 5.2.8 Security parameters
+ */
+
+struct osd_key_identifier {
+	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+} __packed;
+
+/* for osd_capability.format */
+enum {
+	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
+	OSD_SEC_CAP_FORMAT_VER1 = 1,
+	OSD_SEC_CAP_FORMAT_VER2 = 2,
+};
+
+/* security_method */
+enum {
+	OSD_SEC_NOSEC = 0,
+	OSD_SEC_CAPKEY = 1,
+	OSD_SEC_CMDRSP = 2,
+	OSD_SEC_ALLDATA = 3,
+};
+
+enum object_type {
+	OSD_SEC_OBJ_ROOT = 0x1,
+	OSD_SEC_OBJ_PARTITION = 0x2,
+	OSD_SEC_OBJ_COLLECTION = 0x40,
+	OSD_SEC_OBJ_USER = 0x80,
+};
+
+enum osd_capability_bit_masks {
+	OSD_SEC_CAP_APPEND	= BIT(0),
+	OSD_SEC_CAP_OBJ_MGMT	= BIT(1),
+	OSD_SEC_CAP_REMOVE	= BIT(2),
+	OSD_SEC_CAP_CREATE	= BIT(3),
+	OSD_SEC_CAP_SET_ATTR	= BIT(4),
+	OSD_SEC_CAP_GET_ATTR	= BIT(5),
+	OSD_SEC_CAP_WRITE	= BIT(6),
+	OSD_SEC_CAP_READ	= BIT(7),
+
+	OSD_SEC_CAP_NONE1	= BIT(8),
+	OSD_SEC_CAP_NONE2	= BIT(9),
+	OSD_SEC_CAP_NONE3	= BIT(10),
+	OSD_SEC_CAP_QUERY	= BIT(11), /*v2 only*/
+	OSD_SEC_CAP_M_OBJECT	= BIT(12), /*v2 only*/
+	OSD_SEC_CAP_POL_SEC	= BIT(13),
+	OSD_SEC_CAP_GLOBAL	= BIT(14),
+	OSD_SEC_CAP_DEV_MGMT	= BIT(15),
+};
+
+/* for object_descriptor_type (hi nibble used) */
+enum {
+	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
+	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
+	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
+	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
+};
+
+/* (osd-r10:4.9.2.2)
+ * osd2r03:4.11.2.2 Capability format
+ */
+struct osd_capability_head {
+	u8 format; /* low nibble */
+	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
+	u8 security_method;
+	u8 reserved1;
+/*04*/	struct osd_timestamp expiration_time;
+/*10*/	u8 audit[20];
+/*30*/	u8 discriminator[12];
+/*42*/	struct osd_timestamp object_created_time;
+/*48*/	u8 object_type;
+/*49*/	u8 permissions_bit_mask[5];
+/*54*/	u8 reserved2;
+/*55*/	u8 object_descriptor_type; /* high nibble */
+} __packed;
+
+/*56 v1*/
+struct osdv1_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 policy_access_tag;
+/*60*/			__be64 allowed_partition_id;
+/*68*/			__be64 allowed_object_id;
+/*76*/			__be32 reserved;
+		} __packed obj_desc;
+
+/*56*/		u8 object_descriptor[24];
+	};
+} __packed;
+/*80 v1*/
+
+struct osd_capability {
+	struct osd_capability_head h;
+	struct osdv1_cap_object_descriptor od;
+} __packed;
+
+/**
+ * osd_sec_set_caps - set cap-bits into the capabilities header
+ *
+ * @cap:	The osd_capability_head to set cap bits to.
+ * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
+ *
+ * permissions_bit_mask is unaligned use below to set into caps
+ * in a version independent way
+ */
+static inline void osd_sec_set_caps(struct osd_capability_head *cap,
+	u16 bit_mask)
+{
+	/*
+	 *Note: The bits above are defined LE order this is because this way
+	 *      they can grow in the future to more then 16, and still retain
+	 *      there constant values.
+	 */
+	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
+}
+
+#endif /* ndef __OSD_PROTOCOL_H__ */
diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h
new file mode 100644
index 0000000..4c09fee
--- /dev/null
+++ b/include/scsi/osd_sec.h
@@ -0,0 +1,45 @@
+/*
+ * osd_sec.h - OSD security manager API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_SEC_H__
+#define __OSD_SEC_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/*
+ * Contains types and constants of osd capabilities and security
+ * encoding/decoding.
+ * API is trying to keep security abstract so initiator of an object
+ * based pNFS client knows as little as possible about security and
+ * capabilities. It is the Server's osd-initiator place to know more.
+ * Also can be used by osd-target.
+ */
+void osd_sec_encode_caps(void *caps, ...);/* NI */
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1);
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_params);
+
+/* Conditionally sign the CDB according to security setting in ocdb
+ * with cap_key */
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key);
+
+/* Unconditionally sign the BIO data with cap_key.
+ * Check for osd_is_sec_alldata() was done prior to calling this. */
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key);
+
+/* Version independent copy of caps into the cdb */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps);
+
+#endif /* ndef __OSD_SEC_H__ */
diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h
new file mode 100644
index 0000000..ea5372d
--- /dev/null
+++ b/include/scsi/osd_types.h
@@ -0,0 +1,40 @@
+/*
+ * osd_types.h - Types and constants which are not part of the protocol.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Contains types and constants that are implementation specific and are
+ * used by more than one part of the osd library.
+ *     (Eg initiator/target/security_manager/...)
+ */
+#ifndef __OSD_TYPES_H__
+#define __OSD_TYPES_H__
+
+struct osd_systemid {
+	u8 data[OSD_SYSTEMID_LEN];
+};
+
+typedef u64 __bitwise osd_id;
+
+struct osd_obj_id {
+	osd_id partition;
+	osd_id id;
+};
+
+static const struct __weak osd_obj_id osd_root_object = {0, 0};
+
+struct osd_attr {
+	u32 page;
+	u32 attr_id;
+	u16 len;		/* byte count of operand */
+	void *val_ptr;		/* in network order */
+};
+
+#endif /* ndef __OSD_TYPES_H__ */
-- 
1.6.0.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 04/18] libosd: OSDv1 preliminary implementation
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 12:43     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:43 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Implementation of the most basic OSD functionality and
infrastructure. Mainly Format, Create/Remove Partition,
Create/Remove Object, and read/write.

- Add Makefile and Kbuild to compile libosd.ko
- osd_initiator.c Implementation file for osd_initiator.h
  and osd_sec.h APIs
- osd_debug.h - Some kprintf macro definitions

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild          |   32 +++
 drivers/scsi/osd/Makefile        |   37 +++
 drivers/scsi/osd/osd_debug.h     |   30 +++
 drivers/scsi/osd/osd_initiator.c |  448 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 547 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kbuild
 create mode 100755 drivers/scsi/osd/Makefile
 create mode 100644 drivers/scsi/osd/osd_debug.h
 create mode 100644 drivers/scsi/osd/osd_initiator.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
new file mode 100644
index 0000000..5672842
--- /dev/null
+++ b/drivers/scsi/osd/Kbuild
@@ -0,0 +1,32 @@
+#
+# Kbuild for the OSD modules
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+
+ifneq ($(OSD_INC),)
+# we are built out-of-tree Kconfigure everything as on
+
+CONFIG_SCSI_OSD_INITIATOR=m
+ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
+
+# Uncomment to turn debug on
+# ccflags-y += -DCONFIG_SCSI_OSD_DEBUG
+
+# if we are built out-of-tree and the hosting kernel has OSD headers
+# then "ccflags-y +=" will not pick the out-off-tree headers. Only by doing
+# this it will work. This might break in future kernels
+KBUILD_CPPFLAGS := -I$(OSD_INC) $(KBUILD_CPPFLAGS)
+
+endif
+
+# libosd.ko - osd-initiator library
+libosd-y := osd_initiator.o
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile
new file mode 100755
index 0000000..d905344
--- /dev/null
+++ b/drivers/scsi/osd/Makefile
@@ -0,0 +1,37 @@
+#
+# Makefile for the OSD modules (out of tree)
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+# This Makefile is used to call the kernel Makefile in case of an out-of-tree
+# build.
+# $KSRC should point to a Kernel source tree otherwise host's default is
+# used. (eg. /lib/modules/`uname -r`/build)
+
+# include path for out-of-tree Headers
+OSD_INC ?= `pwd`/../../../include
+
+# allow users to override these
+# e.g. to compile for a kernel that you aren't currently running
+KSRC ?= /lib/modules/$(shell uname -r)/build
+KBUILD_OUTPUT ?=
+ARCH ?=
+V ?= 0
+
+# this is the basic Kbuild out-of-tree invocation, with the M= option
+KBUILD_BASE = +$(MAKE) -C $(KSRC) M=`pwd` KBUILD_OUTPUT=$(KBUILD_OUTPUT) ARCH=$(ARCH) V=$(V)
+
+all: libosd
+
+libosd: ;
+	$(KBUILD_BASE) OSD_INC=$(OSD_INC) modules
+
+clean:
+	$(KBUILD_BASE) clean
diff --git a/drivers/scsi/osd/osd_debug.h b/drivers/scsi/osd/osd_debug.h
new file mode 100644
index 0000000..579e491
--- /dev/null
+++ b/drivers/scsi/osd/osd_debug.h
@@ -0,0 +1,30 @@
+/*
+ * osd_debug.h - Some kprintf macros
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_DEBUG_H__
+#define __OSD_DEBUG_H__
+
+#define OSD_ERR(fmt, a...) printk(KERN_ERR "osd: " fmt, ##a)
+#define OSD_INFO(fmt, a...) printk(KERN_NOTICE "osd: " fmt, ##a)
+
+#ifdef CONFIG_SCSI_OSD_DEBUG
+#define OSD_DEBUG(fmt, a...) \
+	printk(KERN_NOTICE "osd @%s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define OSD_DEBUG(fmt, a...) do {} while (0)
+#endif
+
+/* u64 has problems with printk this will cast it to unsigned long long */
+#define _LLU(x) (unsigned long long)(x)
+
+#endif /* ndef __OSD_DEBUG_H__ */
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
new file mode 100644
index 0000000..0e6d906
--- /dev/null
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -0,0 +1,448 @@
+/*
+ * osd_initiator - Main body of the osd initiator library.
+ *
+ * Note: The file does not contain the advanced security functionality which
+ * is only needed by the security_manager's initiators.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+#include <scsi/scsi_device.h>
+
+#include "osd_debug.h"
+
+enum { OSD_REQ_RETRIES = 1 };
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd initiator library libosd.ko");
+MODULE_LICENSE("GPL");
+
+static inline void build_test(void)
+{
+	/* structures were not packed */
+	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
+}
+
+static unsigned _osd_req_cdb_len(struct osd_request *or)
+{
+	return OSDv1_TOTAL_CDB_LEN;
+}
+
+void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
+{
+	memset(osdd, 0, sizeof(*osdd));
+	osdd->scsi_device = scsi_device;
+	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+	/* TODO: Allocate pools for osd_request attributes ... */
+}
+EXPORT_SYMBOL(osd_dev_init);
+
+void osd_dev_fini(struct osd_dev *osdd)
+{
+	/* TODO: De-allocate pools */
+
+	osdd->scsi_device = NULL;
+}
+EXPORT_SYMBOL(osd_dev_fini);
+
+static struct osd_request *_osd_request_alloc(gfp_t gfp)
+{
+	struct osd_request *or;
+
+	/* TODO: Use mempool with one saved request */
+	or = kzalloc(sizeof(*or), gfp);
+	return or;
+}
+
+static void _osd_request_free(struct osd_request *or)
+{
+	kfree(or);
+}
+
+struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp)
+{
+	struct osd_request *or;
+
+	or = _osd_request_alloc(gfp);
+	if (!or)
+		return NULL;
+
+	or->osd_dev = dev;
+	or->alloc_flags = gfp;
+	or->timeout = dev->def_timeout;
+	or->retries = OSD_REQ_RETRIES;
+
+	return or;
+}
+EXPORT_SYMBOL(osd_start_request);
+
+/*
+ * If osd_finalize_request() was called but the request was not executed through
+ * the block layer, then we must release BIOs.
+ */
+static void _abort_unexecuted_bios(struct request *rq)
+{
+	struct bio *bio;
+
+	while ((bio = rq->bio) != NULL) {
+		rq->bio = bio->bi_next;
+		bio_endio(bio, 0);
+	}
+}
+
+void osd_end_request(struct osd_request *or)
+{
+	struct request *rq = or->request;
+
+	if (rq) {
+		if (rq->next_rq) {
+			_abort_unexecuted_bios(rq->next_rq);
+			blk_put_request(rq->next_rq);
+		}
+
+		_abort_unexecuted_bios(rq);
+		blk_put_request(rq);
+	}
+	_osd_request_free(or);
+}
+EXPORT_SYMBOL(osd_end_request);
+
+int osd_execute_request(struct osd_request *or)
+{
+	return blk_execute_rq(or->request->q, NULL, or->request, 0);
+}
+EXPORT_SYMBOL(osd_execute_request);
+
+static void osd_request_async_done(struct request *req, int error)
+{
+	struct osd_request *or = req->end_io_data;
+
+	or->async_error = error;
+
+	if (error)
+		OSD_DEBUG("osd_request_async_done error recieved %d\n", error);
+
+	if (or->async_done)
+		or->async_done(or, or->async_private);
+	else
+		osd_end_request(or);
+}
+
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private)
+{
+	or->request->end_io_data = or;
+	or->async_private = private;
+	or->async_done = done;
+
+	blk_execute_rq_nowait(or->request->q, NULL, or->request, 0,
+			      osd_request_async_done);
+	return 0;
+}
+EXPORT_SYMBOL(osd_execute_request_async);
+
+/*
+ * Common to all OSD commands
+ */
+
+static void _osdv1_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv1_cdb *ocdb = &or->cdb.v1;
+
+	/*
+	 * For speed, the commands
+	 *	OSD_ACT_PERFORM_SCSI_COMMAND	, V1 0x8F7E, V2 0x8F7C
+	 *	OSD_ACT_SCSI_TASK_MANAGEMENT	, V1 0x8F7F, V2 0x8F7D
+	 * are not supported here. Should pass zero and set after the call
+	 */
+	act &= cpu_to_be16(~0x0080); /* V1 action code */
+
+	OSD_DEBUG("OSDv1 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v1.length = cpu_to_be64(len);
+	ocdb->h.v1.start_address = cpu_to_be64(offset);
+}
+
+static void _osd_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	_osdv1_req_encode_common(or, act, obj, offset, len);
+}
+
+/*
+ * Device commands
+ */
+void osd_req_format(struct osd_request *or, u64 tot_capacity)
+{
+	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
+				tot_capacity);
+}
+EXPORT_SYMBOL(osd_req_format);
+
+/*
+ * Partition commands
+ */
+static void _osd_req_encode_partition(struct osd_request *or,
+	__be16 act, osd_id partition)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	_osd_req_encode_common(or, act, &par, 0, 0);
+}
+
+void osd_req_create_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_CREATE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_create_partition);
+
+void osd_req_remove_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_REMOVE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_remove_partition);
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_CREATE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_create_object);
+
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_REMOVE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_remove_object);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, bio->bi_size);
+	WARN_ON(or->out.bio || or->out.total_bytes);
+	bio->bi_rw |= (1 << BIO_RW);
+	or->out.bio = bio;
+	or->out.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_write);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_READ, obj, offset, bio->bi_size);
+	WARN_ON(or->in.bio || or->in.total_bytes);
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_read);
+
+/*
+ * osd_finalize_request and helpers
+ */
+
+static int _init_blk_request(struct osd_request *or,
+	bool has_in, bool has_out)
+{
+	gfp_t flags = or->alloc_flags;
+	struct scsi_device *scsi_device = or->osd_dev->scsi_device;
+	struct request_queue *q = scsi_device->request_queue;
+	struct request *req;
+	int ret = -ENOMEM;
+
+	req = blk_get_request(q, has_out, flags);
+	if (!req)
+		goto out;
+
+	or->request = req;
+	req->cmd_type = REQ_TYPE_BLOCK_PC;
+	req->timeout = or->timeout;
+	req->retries = or->retries;
+	req->sense = or->sense;
+	req->sense_len = 0;
+
+	if (has_out) {
+		or->out.req = req;
+		if (has_in) {
+			/* allocate bidi request */
+			req = blk_get_request(q, READ, flags);
+			if (!req) {
+				OSD_DEBUG("blk_get_request for bidi failed\n");
+				goto out;
+			}
+			req->cmd_type = REQ_TYPE_BLOCK_PC;
+			or->in.req = or->request->next_rq = req;
+		}
+	} else if (has_in)
+		or->in.req = req;
+
+	ret = 0;
+out:
+	OSD_DEBUG("or=%p has_in=%d has_out=%d => %d, %p\n",
+			or, has_in, has_out, ret, or->request);
+	return ret;
+}
+
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	bool has_in, has_out;
+	int ret;
+
+	if (options & OSD_REQ_FUA)
+		cdbh->options |= OSD_CDB_FUA;
+
+	if (options & OSD_REQ_DPO)
+		cdbh->options |= OSD_CDB_DPO;
+
+	if (options & OSD_REQ_BYPASS_TIMESTAMPS)
+		cdbh->timestamp_control = OSD_CDB_BYPASS_TIMESTAMPS;
+
+	osd_set_caps(&or->cdb, cap);
+
+	has_in = or->in.bio || or->get_attr.total_bytes;
+	has_out = or->out.bio || or->set_attr.total_bytes ||
+		or->enc_get_attr.total_bytes;
+
+	ret = _init_blk_request(or, has_in, has_out);
+	if (ret) {
+		OSD_DEBUG("_init_blk_request failed\n");
+		return ret;
+	}
+
+	if (or->out.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->out.req,
+					or->out.bio);
+		if (ret) {
+			OSD_DEBUG("blk_rq_append_bio out failed\n");
+			return ret;
+		}
+		OSD_DEBUG("out bytes=%llu (bytes_req=%u)\n",
+			_LLU(or->out.total_bytes), or->out.req->data_len);
+	}
+	if (or->in.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->in.req, or->in.bio);
+		if (ret) {
+			OSD_DEBUG("blk_rq_append_bio in failed\n");
+			return ret;
+		}
+		OSD_DEBUG("in bytes=%llu (bytes_req=%u)\n",
+			_LLU(or->in.total_bytes), or->in.req->data_len);
+	}
+
+	if (!or->attributes_mode)
+		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+	cdbh->command_specific_options |= or->attributes_mode;
+
+	or->request->cmd = or->cdb.buff;
+	or->request->cmd_len = _osd_req_cdb_len(or);
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_finalize_request);
+
+/*
+ * Implementation of osd_sec.h API
+ * TODO: Move to a separate osd_sec.c file at a later stage.
+ */
+
+enum { OSD_SEC_CAP_V1_ALL_CAPS =
+	OSD_SEC_CAP_APPEND | OSD_SEC_CAP_OBJ_MGMT | OSD_SEC_CAP_REMOVE   |
+	OSD_SEC_CAP_CREATE | OSD_SEC_CAP_SET_ATTR | OSD_SEC_CAP_GET_ATTR |
+	OSD_SEC_CAP_WRITE  | OSD_SEC_CAP_READ     | OSD_SEC_CAP_POL_SEC  |
+	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
+};
+
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
+{
+	struct osd_capability *cap = caps;
+	u8 type;
+	u8 descriptor_type;
+
+	if (likely(obj->id)) {
+		if (unlikely(is_collection)) {
+			type = OSD_SEC_OBJ_COLLECTION;
+			descriptor_type = is_v1 ? OSD_SEC_OBJ_DESC_OBJ :
+						  OSD_SEC_OBJ_DESC_COL;
+		} else {
+			type = OSD_SEC_OBJ_USER;
+			descriptor_type = OSD_SEC_OBJ_DESC_OBJ;
+		}
+		WARN_ON(!obj->partition);
+	} else {
+		type = obj->partition ? OSD_SEC_OBJ_PARTITION :
+					OSD_SEC_OBJ_ROOT;
+		descriptor_type = OSD_SEC_OBJ_DESC_PAR;
+	}
+
+	memset(cap, 0, sizeof(*cap));
+
+	cap->h.format = OSD_SEC_CAP_FORMAT_VER1;
+	cap->h.integrity_algorithm__key_version = 0; /* MAKE_BYTE(0, 0); */
+	cap->h.security_method = OSD_SEC_NOSEC;
+/*	cap->expiration_time;
+	cap->AUDIT[30-10];
+	cap->discriminator[42-30];
+	cap->object_created_time; */
+	cap->h.object_type = type;
+	osd_sec_set_caps(&cap->h, OSD_SEC_CAP_V1_ALL_CAPS);
+	cap->h.object_descriptor_type = descriptor_type;
+	cap->od.obj_desc.policy_access_tag = 0;
+	cap->od.obj_desc.allowed_partition_id = cpu_to_be64(obj->partition);
+	cap->od.obj_desc.allowed_object_id = cpu_to_be64(obj->id);
+}
+EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
+
+void osd_set_caps(struct osd_cdb *cdb, const void *caps)
+{
+	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+}
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 04/18] libosd: OSDv1 preliminary implementation
@ 2008-12-22 12:43     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:43 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Implementation of the most basic OSD functionality and
infrastructure. Mainly Format, Create/Remove Partition,
Create/Remove Object, and read/write.

- Add Makefile and Kbuild to compile libosd.ko
- osd_initiator.c Implementation file for osd_initiator.h
  and osd_sec.h APIs
- osd_debug.h - Some kprintf macro definitions

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild          |   32 +++
 drivers/scsi/osd/Makefile        |   37 +++
 drivers/scsi/osd/osd_debug.h     |   30 +++
 drivers/scsi/osd/osd_initiator.c |  448 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 547 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kbuild
 create mode 100755 drivers/scsi/osd/Makefile
 create mode 100644 drivers/scsi/osd/osd_debug.h
 create mode 100644 drivers/scsi/osd/osd_initiator.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
new file mode 100644
index 0000000..5672842
--- /dev/null
+++ b/drivers/scsi/osd/Kbuild
@@ -0,0 +1,32 @@
+#
+# Kbuild for the OSD modules
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+
+ifneq ($(OSD_INC),)
+# we are built out-of-tree Kconfigure everything as on
+
+CONFIG_SCSI_OSD_INITIATOR=m
+ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
+
+# Uncomment to turn debug on
+# ccflags-y += -DCONFIG_SCSI_OSD_DEBUG
+
+# if we are built out-of-tree and the hosting kernel has OSD headers
+# then "ccflags-y +=" will not pick the out-off-tree headers. Only by doing
+# this it will work. This might break in future kernels
+KBUILD_CPPFLAGS := -I$(OSD_INC) $(KBUILD_CPPFLAGS)
+
+endif
+
+# libosd.ko - osd-initiator library
+libosd-y := osd_initiator.o
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile
new file mode 100755
index 0000000..d905344
--- /dev/null
+++ b/drivers/scsi/osd/Makefile
@@ -0,0 +1,37 @@
+#
+# Makefile for the OSD modules (out of tree)
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+# This Makefile is used to call the kernel Makefile in case of an out-of-tree
+# build.
+# $KSRC should point to a Kernel source tree otherwise host's default is
+# used. (eg. /lib/modules/`uname -r`/build)
+
+# include path for out-of-tree Headers
+OSD_INC ?= `pwd`/../../../include
+
+# allow users to override these
+# e.g. to compile for a kernel that you aren't currently running
+KSRC ?= /lib/modules/$(shell uname -r)/build
+KBUILD_OUTPUT ?=
+ARCH ?=
+V ?= 0
+
+# this is the basic Kbuild out-of-tree invocation, with the M= option
+KBUILD_BASE = +$(MAKE) -C $(KSRC) M=`pwd` KBUILD_OUTPUT=$(KBUILD_OUTPUT) ARCH=$(ARCH) V=$(V)
+
+all: libosd
+
+libosd: ;
+	$(KBUILD_BASE) OSD_INC=$(OSD_INC) modules
+
+clean:
+	$(KBUILD_BASE) clean
diff --git a/drivers/scsi/osd/osd_debug.h b/drivers/scsi/osd/osd_debug.h
new file mode 100644
index 0000000..579e491
--- /dev/null
+++ b/drivers/scsi/osd/osd_debug.h
@@ -0,0 +1,30 @@
+/*
+ * osd_debug.h - Some kprintf macros
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_DEBUG_H__
+#define __OSD_DEBUG_H__
+
+#define OSD_ERR(fmt, a...) printk(KERN_ERR "osd: " fmt, ##a)
+#define OSD_INFO(fmt, a...) printk(KERN_NOTICE "osd: " fmt, ##a)
+
+#ifdef CONFIG_SCSI_OSD_DEBUG
+#define OSD_DEBUG(fmt, a...) \
+	printk(KERN_NOTICE "osd @%s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define OSD_DEBUG(fmt, a...) do {} while (0)
+#endif
+
+/* u64 has problems with printk this will cast it to unsigned long long */
+#define _LLU(x) (unsigned long long)(x)
+
+#endif /* ndef __OSD_DEBUG_H__ */
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
new file mode 100644
index 0000000..0e6d906
--- /dev/null
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -0,0 +1,448 @@
+/*
+ * osd_initiator - Main body of the osd initiator library.
+ *
+ * Note: The file does not contain the advanced security functionality which
+ * is only needed by the security_manager's initiators.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+#include <scsi/scsi_device.h>
+
+#include "osd_debug.h"
+
+enum { OSD_REQ_RETRIES = 1 };
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd initiator library libosd.ko");
+MODULE_LICENSE("GPL");
+
+static inline void build_test(void)
+{
+	/* structures were not packed */
+	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
+}
+
+static unsigned _osd_req_cdb_len(struct osd_request *or)
+{
+	return OSDv1_TOTAL_CDB_LEN;
+}
+
+void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
+{
+	memset(osdd, 0, sizeof(*osdd));
+	osdd->scsi_device = scsi_device;
+	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+	/* TODO: Allocate pools for osd_request attributes ... */
+}
+EXPORT_SYMBOL(osd_dev_init);
+
+void osd_dev_fini(struct osd_dev *osdd)
+{
+	/* TODO: De-allocate pools */
+
+	osdd->scsi_device = NULL;
+}
+EXPORT_SYMBOL(osd_dev_fini);
+
+static struct osd_request *_osd_request_alloc(gfp_t gfp)
+{
+	struct osd_request *or;
+
+	/* TODO: Use mempool with one saved request */
+	or = kzalloc(sizeof(*or), gfp);
+	return or;
+}
+
+static void _osd_request_free(struct osd_request *or)
+{
+	kfree(or);
+}
+
+struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp)
+{
+	struct osd_request *or;
+
+	or = _osd_request_alloc(gfp);
+	if (!or)
+		return NULL;
+
+	or->osd_dev = dev;
+	or->alloc_flags = gfp;
+	or->timeout = dev->def_timeout;
+	or->retries = OSD_REQ_RETRIES;
+
+	return or;
+}
+EXPORT_SYMBOL(osd_start_request);
+
+/*
+ * If osd_finalize_request() was called but the request was not executed through
+ * the block layer, then we must release BIOs.
+ */
+static void _abort_unexecuted_bios(struct request *rq)
+{
+	struct bio *bio;
+
+	while ((bio = rq->bio) != NULL) {
+		rq->bio = bio->bi_next;
+		bio_endio(bio, 0);
+	}
+}
+
+void osd_end_request(struct osd_request *or)
+{
+	struct request *rq = or->request;
+
+	if (rq) {
+		if (rq->next_rq) {
+			_abort_unexecuted_bios(rq->next_rq);
+			blk_put_request(rq->next_rq);
+		}
+
+		_abort_unexecuted_bios(rq);
+		blk_put_request(rq);
+	}
+	_osd_request_free(or);
+}
+EXPORT_SYMBOL(osd_end_request);
+
+int osd_execute_request(struct osd_request *or)
+{
+	return blk_execute_rq(or->request->q, NULL, or->request, 0);
+}
+EXPORT_SYMBOL(osd_execute_request);
+
+static void osd_request_async_done(struct request *req, int error)
+{
+	struct osd_request *or = req->end_io_data;
+
+	or->async_error = error;
+
+	if (error)
+		OSD_DEBUG("osd_request_async_done error recieved %d\n", error);
+
+	if (or->async_done)
+		or->async_done(or, or->async_private);
+	else
+		osd_end_request(or);
+}
+
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private)
+{
+	or->request->end_io_data = or;
+	or->async_private = private;
+	or->async_done = done;
+
+	blk_execute_rq_nowait(or->request->q, NULL, or->request, 0,
+			      osd_request_async_done);
+	return 0;
+}
+EXPORT_SYMBOL(osd_execute_request_async);
+
+/*
+ * Common to all OSD commands
+ */
+
+static void _osdv1_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv1_cdb *ocdb = &or->cdb.v1;
+
+	/*
+	 * For speed, the commands
+	 *	OSD_ACT_PERFORM_SCSI_COMMAND	, V1 0x8F7E, V2 0x8F7C
+	 *	OSD_ACT_SCSI_TASK_MANAGEMENT	, V1 0x8F7F, V2 0x8F7D
+	 * are not supported here. Should pass zero and set after the call
+	 */
+	act &= cpu_to_be16(~0x0080); /* V1 action code */
+
+	OSD_DEBUG("OSDv1 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v1.length = cpu_to_be64(len);
+	ocdb->h.v1.start_address = cpu_to_be64(offset);
+}
+
+static void _osd_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	_osdv1_req_encode_common(or, act, obj, offset, len);
+}
+
+/*
+ * Device commands
+ */
+void osd_req_format(struct osd_request *or, u64 tot_capacity)
+{
+	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
+				tot_capacity);
+}
+EXPORT_SYMBOL(osd_req_format);
+
+/*
+ * Partition commands
+ */
+static void _osd_req_encode_partition(struct osd_request *or,
+	__be16 act, osd_id partition)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	_osd_req_encode_common(or, act, &par, 0, 0);
+}
+
+void osd_req_create_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_CREATE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_create_partition);
+
+void osd_req_remove_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_REMOVE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_remove_partition);
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_CREATE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_create_object);
+
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_REMOVE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_remove_object);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, bio->bi_size);
+	WARN_ON(or->out.bio || or->out.total_bytes);
+	bio->bi_rw |= (1 << BIO_RW);
+	or->out.bio = bio;
+	or->out.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_write);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_READ, obj, offset, bio->bi_size);
+	WARN_ON(or->in.bio || or->in.total_bytes);
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_read);
+
+/*
+ * osd_finalize_request and helpers
+ */
+
+static int _init_blk_request(struct osd_request *or,
+	bool has_in, bool has_out)
+{
+	gfp_t flags = or->alloc_flags;
+	struct scsi_device *scsi_device = or->osd_dev->scsi_device;
+	struct request_queue *q = scsi_device->request_queue;
+	struct request *req;
+	int ret = -ENOMEM;
+
+	req = blk_get_request(q, has_out, flags);
+	if (!req)
+		goto out;
+
+	or->request = req;
+	req->cmd_type = REQ_TYPE_BLOCK_PC;
+	req->timeout = or->timeout;
+	req->retries = or->retries;
+	req->sense = or->sense;
+	req->sense_len = 0;
+
+	if (has_out) {
+		or->out.req = req;
+		if (has_in) {
+			/* allocate bidi request */
+			req = blk_get_request(q, READ, flags);
+			if (!req) {
+				OSD_DEBUG("blk_get_request for bidi failed\n");
+				goto out;
+			}
+			req->cmd_type = REQ_TYPE_BLOCK_PC;
+			or->in.req = or->request->next_rq = req;
+		}
+	} else if (has_in)
+		or->in.req = req;
+
+	ret = 0;
+out:
+	OSD_DEBUG("or=%p has_in=%d has_out=%d => %d, %p\n",
+			or, has_in, has_out, ret, or->request);
+	return ret;
+}
+
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	bool has_in, has_out;
+	int ret;
+
+	if (options & OSD_REQ_FUA)
+		cdbh->options |= OSD_CDB_FUA;
+
+	if (options & OSD_REQ_DPO)
+		cdbh->options |= OSD_CDB_DPO;
+
+	if (options & OSD_REQ_BYPASS_TIMESTAMPS)
+		cdbh->timestamp_control = OSD_CDB_BYPASS_TIMESTAMPS;
+
+	osd_set_caps(&or->cdb, cap);
+
+	has_in = or->in.bio || or->get_attr.total_bytes;
+	has_out = or->out.bio || or->set_attr.total_bytes ||
+		or->enc_get_attr.total_bytes;
+
+	ret = _init_blk_request(or, has_in, has_out);
+	if (ret) {
+		OSD_DEBUG("_init_blk_request failed\n");
+		return ret;
+	}
+
+	if (or->out.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->out.req,
+					or->out.bio);
+		if (ret) {
+			OSD_DEBUG("blk_rq_append_bio out failed\n");
+			return ret;
+		}
+		OSD_DEBUG("out bytes=%llu (bytes_req=%u)\n",
+			_LLU(or->out.total_bytes), or->out.req->data_len);
+	}
+	if (or->in.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->in.req, or->in.bio);
+		if (ret) {
+			OSD_DEBUG("blk_rq_append_bio in failed\n");
+			return ret;
+		}
+		OSD_DEBUG("in bytes=%llu (bytes_req=%u)\n",
+			_LLU(or->in.total_bytes), or->in.req->data_len);
+	}
+
+	if (!or->attributes_mode)
+		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+	cdbh->command_specific_options |= or->attributes_mode;
+
+	or->request->cmd = or->cdb.buff;
+	or->request->cmd_len = _osd_req_cdb_len(or);
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_finalize_request);
+
+/*
+ * Implementation of osd_sec.h API
+ * TODO: Move to a separate osd_sec.c file at a later stage.
+ */
+
+enum { OSD_SEC_CAP_V1_ALL_CAPS =
+	OSD_SEC_CAP_APPEND | OSD_SEC_CAP_OBJ_MGMT | OSD_SEC_CAP_REMOVE   |
+	OSD_SEC_CAP_CREATE | OSD_SEC_CAP_SET_ATTR | OSD_SEC_CAP_GET_ATTR |
+	OSD_SEC_CAP_WRITE  | OSD_SEC_CAP_READ     | OSD_SEC_CAP_POL_SEC  |
+	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
+};
+
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
+{
+	struct osd_capability *cap = caps;
+	u8 type;
+	u8 descriptor_type;
+
+	if (likely(obj->id)) {
+		if (unlikely(is_collection)) {
+			type = OSD_SEC_OBJ_COLLECTION;
+			descriptor_type = is_v1 ? OSD_SEC_OBJ_DESC_OBJ :
+						  OSD_SEC_OBJ_DESC_COL;
+		} else {
+			type = OSD_SEC_OBJ_USER;
+			descriptor_type = OSD_SEC_OBJ_DESC_OBJ;
+		}
+		WARN_ON(!obj->partition);
+	} else {
+		type = obj->partition ? OSD_SEC_OBJ_PARTITION :
+					OSD_SEC_OBJ_ROOT;
+		descriptor_type = OSD_SEC_OBJ_DESC_PAR;
+	}
+
+	memset(cap, 0, sizeof(*cap));
+
+	cap->h.format = OSD_SEC_CAP_FORMAT_VER1;
+	cap->h.integrity_algorithm__key_version = 0; /* MAKE_BYTE(0, 0); */
+	cap->h.security_method = OSD_SEC_NOSEC;
+/*	cap->expiration_time;
+	cap->AUDIT[30-10];
+	cap->discriminator[42-30];
+	cap->object_created_time; */
+	cap->h.object_type = type;
+	osd_sec_set_caps(&cap->h, OSD_SEC_CAP_V1_ALL_CAPS);
+	cap->h.object_descriptor_type = descriptor_type;
+	cap->od.obj_desc.policy_access_tag = 0;
+	cap->od.obj_desc.allowed_partition_id = cpu_to_be64(obj->partition);
+	cap->od.obj_desc.allowed_object_id = cpu_to_be64(obj->id);
+}
+EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
+
+void osd_set_caps(struct osd_cdb *cdb, const void *caps)
+{
+	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+}
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 05/18] osd_uld: OSD scsi ULD
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 12:46     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:46 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Add a Linux driver module that registers as a SCSI ULD and probes
for OSD type SCSI devices.

When an OSD-type SCSI device is found a character device is created
in the form of /dev/osdX - where X goes from 0 up to hard coded 64.
The Major character device number used is *260*, which is free
(as of Linux v2.6.28-rc8).

A single ioctl is currently supported that will invoke an in-kernel
test on the specified OSD device (lun).

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild       |    7 +
 drivers/scsi/osd/osd_ktests.h |   27 +++
 drivers/scsi/osd/osd_uld.c    |  388 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 422 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_ktests.h
 create mode 100644 drivers/scsi/osd/osd_uld.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index 5672842..4730cdc 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -17,6 +17,9 @@ ifneq ($(OSD_INC),)
 CONFIG_SCSI_OSD_INITIATOR=m
 ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
 
+CONFIG_SCSI_OSD_ULD=m
+ccflags-y += -DCONFIG_SCSI_OSD_ULD -DCONFIG_SCSI_OSD_ULD_MODULE
+
 # Uncomment to turn debug on
 # ccflags-y += -DCONFIG_SCSI_OSD_DEBUG
 
@@ -30,3 +33,7 @@ endif
 # libosd.ko - osd-initiator library
 libosd-y := osd_initiator.o
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
+
+# osd.ko - SCSI ULD and char-device
+osd-y := osd_uld.o
+obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
diff --git a/drivers/scsi/osd/osd_ktests.h b/drivers/scsi/osd/osd_ktests.h
new file mode 100644
index 0000000..a9e5e00
--- /dev/null
+++ b/drivers/scsi/osd/osd_ktests.h
@@ -0,0 +1,27 @@
+/*
+ * osd_ktests.h - Define the ktests.c API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_KTESTS_H__
+#define __OSD_KTESTS_H__
+
+/* Tests from osd_ktests.c */
+/* TODO: Only one simple test for now. Later I will add a test definition
+ *	structure that will define what tests to preform and with some
+ *	parametrization, so concurrent tests could be run on same OSD lun
+ *	without stepping on each other. (E.g. Format called when other tests
+ *	are in progress)
+ */
+
+enum { OSD_TEST_ALL = 17 };
+
+#endif /*ndef __OSD_KTESTS_H__*/
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
new file mode 100644
index 0000000..bd6c018
--- /dev/null
+++ b/drivers/scsi/osd/osd_uld.c
@@ -0,0 +1,388 @@
+/*
+ * osd_uld.c - OSD Upper Layer Driver
+ *
+ * A Linux driver module that registers as a SCSI ULD and probes
+ * for OSD type SCSI devices.
+ * It's main function is to export osd devices to in-kernel users like
+ * osdfs and pNFS-objects-LD. It also provides one ioctl for running
+ * in Kernel tests.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/major.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_ioctl.h>
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+
+#include "osd_ktests.h"
+#include "osd_debug.h"
+
+#ifndef TYPE_OSD
+#  define TYPE_OSD 0x11
+#endif
+
+#ifndef SCSI_OSD_MAJOR
+#  define SCSI_OSD_MAJOR 260
+#endif
+#define SCSI_OSD_MAX_MINOR 64
+
+static const char osd_name[] = "osd";
+static const char *osd_version_string = "open-osd 0.1.0";
+const char osd_symlink[] = "scsi_osd";
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SCSI_OSD_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_OSD);
+
+struct osd_uld_device {
+	int minor;
+	struct kref kref;
+	struct cdev cdev;
+	struct osd_dev od;
+	struct gendisk *disk;
+	struct device *class_member;
+};
+
+static void __uld_get(struct osd_uld_device *oud);
+static void __uld_put(struct osd_uld_device *oud);
+
+/*
+ * Char Device operations
+ */
+
+static int osd_uld_open(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *oud = container_of(inode->i_cdev,
+					struct osd_uld_device, cdev);
+
+	__uld_get(oud);
+	/* cache osd_uld_device on file handle */
+	file->private_data = oud;
+	OSD_DEBUG("osd_uld_open %p\n", oud);
+	return 0;
+}
+
+static int osd_uld_release(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *oud = file->private_data;
+
+	OSD_DEBUG("osd_uld_release %p\n", file->private_data);
+	file->private_data = NULL;
+	__uld_put(oud);
+	return 0;
+}
+
+static long osd_uld_ioctl(struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	struct osd_uld_device *oud = file->private_data;
+	int ret;
+
+	switch (cmd) {
+	case OSD_TEST_ALL:
+		OSD_DEBUG("Kernel test %d: osd_uld_device=%p\n", cmd, oud);
+		ret = 0;
+		break;
+	default:
+		OSD_ERR("Unknown osd_uld_ioctl %d\n", cmd);
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+static const struct file_operations osd_fops = {
+	.owner          = THIS_MODULE,
+	.open           = osd_uld_open,
+	.release        = osd_uld_release,
+	.unlocked_ioctl = osd_uld_ioctl,
+};
+
+/*
+ * Scsi Device operations
+ */
+
+static int __detect_osd(struct osd_uld_device *oud)
+{
+	struct scsi_device *scsi_device = oud->od.scsi_device;
+	int error;
+
+	/* sending a test_unit_ready as first command seems to be needed
+	 * by some targets
+	 */
+	OSD_DEBUG("start scsi_test_unit_ready %p %p %p\n",
+			oud, scsi_device, scsi_device->request_queue);
+	error = scsi_test_unit_ready(scsi_device, 10*HZ, 5, NULL);
+	if (error)
+		OSD_ERR("warning: scsi_test_unit_ready failed\n");
+
+	return 0;
+}
+
+static struct class *osd_sysfs_class;
+static DEFINE_IDA(osd_minor_ida);
+
+static int osd_probe(struct device *dev)
+{
+	struct scsi_device *scsi_device = to_scsi_device(dev);
+	struct gendisk *disk;
+	struct osd_uld_device *oud;
+	int minor;
+	int error;
+
+	if (scsi_device->type != TYPE_OSD)
+		return -ENODEV;
+
+	do {
+		if (!ida_pre_get(&osd_minor_ida, GFP_KERNEL))
+			return -ENODEV;
+
+		error = ida_get_new(&osd_minor_ida, &minor);
+	} while (error == -EAGAIN);
+
+	if (error)
+		return error;
+	if (minor >= SCSI_OSD_MAX_MINOR) {
+		error = -EBUSY;
+		goto err_retract_minor;
+	}
+
+	error = -ENOMEM;
+	oud = kzalloc(sizeof(*oud), GFP_KERNEL);
+	if (NULL == oud)
+		goto err_retract_minor;
+
+	kref_init(&oud->kref);
+	dev_set_drvdata(dev, oud);
+	oud->minor = minor;
+
+	/* allocate a disk and set it up */
+	/* FIXME: do we need this since sg has already done that */
+	disk = alloc_disk(1);
+	if (!disk) {
+		OSD_ERR("alloc_disk failed\n");
+		goto err_free_osd;
+	}
+	disk->major = SCSI_OSD_MAJOR;
+	disk->first_minor = oud->minor;
+	sprintf(disk->disk_name, "osd%d", oud->minor);
+	oud->disk = disk;
+
+	/* hold one more reference to the scsi_device that will get released
+	 * in __release, in case a logout is happening while fs is mounted
+	 */
+	scsi_device_get(scsi_device);
+	osd_dev_init(&oud->od, scsi_device);
+
+	/* Detect the OSD Version */
+	error = __detect_osd(oud);
+	if (error) {
+		OSD_ERR("osd detection failed, non-compatible OSD device\n");
+		goto err_put_disk;
+	}
+
+	/* init the char-device for communication with user-mode */
+	cdev_init(&oud->cdev, &osd_fops);
+	oud->cdev.owner = THIS_MODULE;
+	error = cdev_add(&oud->cdev,
+			 MKDEV(SCSI_OSD_MAJOR, oud->minor), 1);
+	if (error) {
+		OSD_ERR("cdev_add failed\n");
+		goto err_put_disk;
+	}
+	kobject_get(&oud->cdev.kobj); /* 2nd ref see osd_remove() */
+
+	/* class_member */
+	oud->class_member = device_create(osd_sysfs_class, dev,
+		MKDEV(SCSI_OSD_MAJOR, oud->minor), "%s", disk->disk_name);
+	if (IS_ERR(oud->class_member)) {
+		OSD_ERR("class_device_create failed\n");
+		error = PTR_ERR(oud->class_member);
+		goto err_put_cdev;
+	}
+
+	dev_set_drvdata(oud->class_member, oud);
+	error = sysfs_create_link(&scsi_device->sdev_gendev.kobj,
+				  &oud->class_member->kobj, osd_symlink);
+	if (error)
+		OSD_ERR("warning: unable to make symlink\n");
+
+	OSD_INFO("osd_probe %s\n", disk->disk_name);
+	return 0;
+
+err_put_cdev:
+	cdev_del(&oud->cdev);
+err_put_disk:
+	scsi_device_put(scsi_device);
+	put_disk(disk);
+err_free_osd:
+	dev_set_drvdata(dev, NULL);
+	kfree(oud);
+err_retract_minor:
+	ida_remove(&osd_minor_ida, minor);
+	return error;
+}
+
+static int osd_remove(struct device *dev)
+{
+	struct scsi_device *scsi_device = to_scsi_device(dev);
+	struct osd_uld_device *oud = dev_get_drvdata(dev);
+
+	if (!oud || (oud->od.scsi_device != scsi_device)) {
+		OSD_ERR("Half cooked osd-device %p,%p || %p!=%p",
+			dev, oud, oud ? oud->od.scsi_device : NULL,
+			scsi_device);
+	}
+
+	sysfs_remove_link(&oud->od.scsi_device->sdev_gendev.kobj, osd_symlink);
+
+	if (oud->class_member)
+		device_destroy(osd_sysfs_class,
+			       MKDEV(SCSI_OSD_MAJOR, oud->minor));
+
+	/* We have 2 references to the cdev. One is released here
+	 * and also takes down the /dev/osdX mapping. The second
+	 * Will be released in __remove() after all users have released
+	 * the osd_uld_device.
+	 */
+	if (oud->cdev.owner)
+		cdev_del(&oud->cdev);
+
+	__uld_put(oud);
+	return 0;
+}
+
+static void __remove(struct kref *kref)
+{
+	struct osd_uld_device *oud = container_of(kref,
+					struct osd_uld_device, kref);
+	struct scsi_device *scsi_device = oud->od.scsi_device;
+
+	/* now let delete the char_dev */
+	kobject_put(&oud->cdev.kobj);
+
+	osd_dev_fini(&oud->od);
+	scsi_device_put(scsi_device);
+
+	OSD_INFO("osd_remove %s\n",
+		 oud->disk ? oud->disk->disk_name : NULL);
+
+	if (oud->disk)
+		put_disk(oud->disk);
+
+	ida_remove(&osd_minor_ida, oud->minor);
+	kfree(oud);
+}
+
+static void __uld_get(struct osd_uld_device *oud)
+{
+	kref_get(&oud->kref);
+}
+
+static void __uld_put(struct osd_uld_device *oud)
+{
+	kref_put(&oud->kref, __remove);
+}
+
+/*
+ * Global driver and scsi registration
+ */
+
+static struct scsi_driver osd_driver = {
+	.owner			= THIS_MODULE,
+	.gendrv = {
+		.name		= osd_name,
+		.probe		= osd_probe,
+		.remove		= osd_remove,
+	}
+};
+
+static int __init osd_uld_init(void)
+{
+	int err;
+
+	osd_sysfs_class = class_create(THIS_MODULE, osd_symlink);
+	if (IS_ERR(osd_sysfs_class)) {
+		OSD_ERR("Unable to register sysfs class => %ld\n",
+			PTR_ERR(osd_sysfs_class));
+		return PTR_ERR(osd_sysfs_class);
+	}
+
+	err = register_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0),
+				     SCSI_OSD_MAX_MINOR, osd_name);
+	if (err) {
+		OSD_ERR("Unable to register major %d for osd ULD => %d\n",
+			SCSI_OSD_MAJOR, err);
+		goto err_out;
+	}
+
+	err = scsi_register_driver(&osd_driver.gendrv);
+	if (err) {
+		OSD_ERR("scsi_register_driver failed => %d\n", err);
+		goto err_out_chrdev;
+	}
+
+	OSD_INFO("LOADED %s\n", osd_version_string);
+	return 0;
+
+err_out_chrdev:
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+err_out:
+	class_destroy(osd_sysfs_class);
+	return err;
+}
+
+static void __exit osd_uld_exit(void)
+{
+	scsi_unregister_driver(&osd_driver.gendrv);
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+	class_destroy(osd_sysfs_class);
+	OSD_INFO("UNLOADED %s\n", osd_version_string);
+}
+
+module_init(osd_uld_init);
+module_exit(osd_uld_exit);
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 05/18] osd_uld: OSD scsi ULD
@ 2008-12-22 12:46     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:46 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Add a Linux driver module that registers as a SCSI ULD and probes
for OSD type SCSI devices.

When an OSD-type SCSI device is found a character device is created
in the form of /dev/osdX - where X goes from 0 up to hard coded 64.
The Major character device number used is *260*, which is free
(as of Linux v2.6.28-rc8).

A single ioctl is currently supported that will invoke an in-kernel
test on the specified OSD device (lun).

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild       |    7 +
 drivers/scsi/osd/osd_ktests.h |   27 +++
 drivers/scsi/osd/osd_uld.c    |  388 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 422 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_ktests.h
 create mode 100644 drivers/scsi/osd/osd_uld.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index 5672842..4730cdc 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -17,6 +17,9 @@ ifneq ($(OSD_INC),)
 CONFIG_SCSI_OSD_INITIATOR=m
 ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
 
+CONFIG_SCSI_OSD_ULD=m
+ccflags-y += -DCONFIG_SCSI_OSD_ULD -DCONFIG_SCSI_OSD_ULD_MODULE
+
 # Uncomment to turn debug on
 # ccflags-y += -DCONFIG_SCSI_OSD_DEBUG
 
@@ -30,3 +33,7 @@ endif
 # libosd.ko - osd-initiator library
 libosd-y := osd_initiator.o
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
+
+# osd.ko - SCSI ULD and char-device
+osd-y := osd_uld.o
+obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
diff --git a/drivers/scsi/osd/osd_ktests.h b/drivers/scsi/osd/osd_ktests.h
new file mode 100644
index 0000000..a9e5e00
--- /dev/null
+++ b/drivers/scsi/osd/osd_ktests.h
@@ -0,0 +1,27 @@
+/*
+ * osd_ktests.h - Define the ktests.c API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_KTESTS_H__
+#define __OSD_KTESTS_H__
+
+/* Tests from osd_ktests.c */
+/* TODO: Only one simple test for now. Later I will add a test definition
+ *	structure that will define what tests to preform and with some
+ *	parametrization, so concurrent tests could be run on same OSD lun
+ *	without stepping on each other. (E.g. Format called when other tests
+ *	are in progress)
+ */
+
+enum { OSD_TEST_ALL = 17 };
+
+#endif /*ndef __OSD_KTESTS_H__*/
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
new file mode 100644
index 0000000..bd6c018
--- /dev/null
+++ b/drivers/scsi/osd/osd_uld.c
@@ -0,0 +1,388 @@
+/*
+ * osd_uld.c - OSD Upper Layer Driver
+ *
+ * A Linux driver module that registers as a SCSI ULD and probes
+ * for OSD type SCSI devices.
+ * It's main function is to export osd devices to in-kernel users like
+ * osdfs and pNFS-objects-LD. It also provides one ioctl for running
+ * in Kernel tests.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/major.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_ioctl.h>
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+
+#include "osd_ktests.h"
+#include "osd_debug.h"
+
+#ifndef TYPE_OSD
+#  define TYPE_OSD 0x11
+#endif
+
+#ifndef SCSI_OSD_MAJOR
+#  define SCSI_OSD_MAJOR 260
+#endif
+#define SCSI_OSD_MAX_MINOR 64
+
+static const char osd_name[] = "osd";
+static const char *osd_version_string = "open-osd 0.1.0";
+const char osd_symlink[] = "scsi_osd";
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SCSI_OSD_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_OSD);
+
+struct osd_uld_device {
+	int minor;
+	struct kref kref;
+	struct cdev cdev;
+	struct osd_dev od;
+	struct gendisk *disk;
+	struct device *class_member;
+};
+
+static void __uld_get(struct osd_uld_device *oud);
+static void __uld_put(struct osd_uld_device *oud);
+
+/*
+ * Char Device operations
+ */
+
+static int osd_uld_open(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *oud = container_of(inode->i_cdev,
+					struct osd_uld_device, cdev);
+
+	__uld_get(oud);
+	/* cache osd_uld_device on file handle */
+	file->private_data = oud;
+	OSD_DEBUG("osd_uld_open %p\n", oud);
+	return 0;
+}
+
+static int osd_uld_release(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *oud = file->private_data;
+
+	OSD_DEBUG("osd_uld_release %p\n", file->private_data);
+	file->private_data = NULL;
+	__uld_put(oud);
+	return 0;
+}
+
+static long osd_uld_ioctl(struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	struct osd_uld_device *oud = file->private_data;
+	int ret;
+
+	switch (cmd) {
+	case OSD_TEST_ALL:
+		OSD_DEBUG("Kernel test %d: osd_uld_device=%p\n", cmd, oud);
+		ret = 0;
+		break;
+	default:
+		OSD_ERR("Unknown osd_uld_ioctl %d\n", cmd);
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+static const struct file_operations osd_fops = {
+	.owner          = THIS_MODULE,
+	.open           = osd_uld_open,
+	.release        = osd_uld_release,
+	.unlocked_ioctl = osd_uld_ioctl,
+};
+
+/*
+ * Scsi Device operations
+ */
+
+static int __detect_osd(struct osd_uld_device *oud)
+{
+	struct scsi_device *scsi_device = oud->od.scsi_device;
+	int error;
+
+	/* sending a test_unit_ready as first command seems to be needed
+	 * by some targets
+	 */
+	OSD_DEBUG("start scsi_test_unit_ready %p %p %p\n",
+			oud, scsi_device, scsi_device->request_queue);
+	error = scsi_test_unit_ready(scsi_device, 10*HZ, 5, NULL);
+	if (error)
+		OSD_ERR("warning: scsi_test_unit_ready failed\n");
+
+	return 0;
+}
+
+static struct class *osd_sysfs_class;
+static DEFINE_IDA(osd_minor_ida);
+
+static int osd_probe(struct device *dev)
+{
+	struct scsi_device *scsi_device = to_scsi_device(dev);
+	struct gendisk *disk;
+	struct osd_uld_device *oud;
+	int minor;
+	int error;
+
+	if (scsi_device->type != TYPE_OSD)
+		return -ENODEV;
+
+	do {
+		if (!ida_pre_get(&osd_minor_ida, GFP_KERNEL))
+			return -ENODEV;
+
+		error = ida_get_new(&osd_minor_ida, &minor);
+	} while (error == -EAGAIN);
+
+	if (error)
+		return error;
+	if (minor >= SCSI_OSD_MAX_MINOR) {
+		error = -EBUSY;
+		goto err_retract_minor;
+	}
+
+	error = -ENOMEM;
+	oud = kzalloc(sizeof(*oud), GFP_KERNEL);
+	if (NULL == oud)
+		goto err_retract_minor;
+
+	kref_init(&oud->kref);
+	dev_set_drvdata(dev, oud);
+	oud->minor = minor;
+
+	/* allocate a disk and set it up */
+	/* FIXME: do we need this since sg has already done that */
+	disk = alloc_disk(1);
+	if (!disk) {
+		OSD_ERR("alloc_disk failed\n");
+		goto err_free_osd;
+	}
+	disk->major = SCSI_OSD_MAJOR;
+	disk->first_minor = oud->minor;
+	sprintf(disk->disk_name, "osd%d", oud->minor);
+	oud->disk = disk;
+
+	/* hold one more reference to the scsi_device that will get released
+	 * in __release, in case a logout is happening while fs is mounted
+	 */
+	scsi_device_get(scsi_device);
+	osd_dev_init(&oud->od, scsi_device);
+
+	/* Detect the OSD Version */
+	error = __detect_osd(oud);
+	if (error) {
+		OSD_ERR("osd detection failed, non-compatible OSD device\n");
+		goto err_put_disk;
+	}
+
+	/* init the char-device for communication with user-mode */
+	cdev_init(&oud->cdev, &osd_fops);
+	oud->cdev.owner = THIS_MODULE;
+	error = cdev_add(&oud->cdev,
+			 MKDEV(SCSI_OSD_MAJOR, oud->minor), 1);
+	if (error) {
+		OSD_ERR("cdev_add failed\n");
+		goto err_put_disk;
+	}
+	kobject_get(&oud->cdev.kobj); /* 2nd ref see osd_remove() */
+
+	/* class_member */
+	oud->class_member = device_create(osd_sysfs_class, dev,
+		MKDEV(SCSI_OSD_MAJOR, oud->minor), "%s", disk->disk_name);
+	if (IS_ERR(oud->class_member)) {
+		OSD_ERR("class_device_create failed\n");
+		error = PTR_ERR(oud->class_member);
+		goto err_put_cdev;
+	}
+
+	dev_set_drvdata(oud->class_member, oud);
+	error = sysfs_create_link(&scsi_device->sdev_gendev.kobj,
+				  &oud->class_member->kobj, osd_symlink);
+	if (error)
+		OSD_ERR("warning: unable to make symlink\n");
+
+	OSD_INFO("osd_probe %s\n", disk->disk_name);
+	return 0;
+
+err_put_cdev:
+	cdev_del(&oud->cdev);
+err_put_disk:
+	scsi_device_put(scsi_device);
+	put_disk(disk);
+err_free_osd:
+	dev_set_drvdata(dev, NULL);
+	kfree(oud);
+err_retract_minor:
+	ida_remove(&osd_minor_ida, minor);
+	return error;
+}
+
+static int osd_remove(struct device *dev)
+{
+	struct scsi_device *scsi_device = to_scsi_device(dev);
+	struct osd_uld_device *oud = dev_get_drvdata(dev);
+
+	if (!oud || (oud->od.scsi_device != scsi_device)) {
+		OSD_ERR("Half cooked osd-device %p,%p || %p!=%p",
+			dev, oud, oud ? oud->od.scsi_device : NULL,
+			scsi_device);
+	}
+
+	sysfs_remove_link(&oud->od.scsi_device->sdev_gendev.kobj, osd_symlink);
+
+	if (oud->class_member)
+		device_destroy(osd_sysfs_class,
+			       MKDEV(SCSI_OSD_MAJOR, oud->minor));
+
+	/* We have 2 references to the cdev. One is released here
+	 * and also takes down the /dev/osdX mapping. The second
+	 * Will be released in __remove() after all users have released
+	 * the osd_uld_device.
+	 */
+	if (oud->cdev.owner)
+		cdev_del(&oud->cdev);
+
+	__uld_put(oud);
+	return 0;
+}
+
+static void __remove(struct kref *kref)
+{
+	struct osd_uld_device *oud = container_of(kref,
+					struct osd_uld_device, kref);
+	struct scsi_device *scsi_device = oud->od.scsi_device;
+
+	/* now let delete the char_dev */
+	kobject_put(&oud->cdev.kobj);
+
+	osd_dev_fini(&oud->od);
+	scsi_device_put(scsi_device);
+
+	OSD_INFO("osd_remove %s\n",
+		 oud->disk ? oud->disk->disk_name : NULL);
+
+	if (oud->disk)
+		put_disk(oud->disk);
+
+	ida_remove(&osd_minor_ida, oud->minor);
+	kfree(oud);
+}
+
+static void __uld_get(struct osd_uld_device *oud)
+{
+	kref_get(&oud->kref);
+}
+
+static void __uld_put(struct osd_uld_device *oud)
+{
+	kref_put(&oud->kref, __remove);
+}
+
+/*
+ * Global driver and scsi registration
+ */
+
+static struct scsi_driver osd_driver = {
+	.owner			= THIS_MODULE,
+	.gendrv = {
+		.name		= osd_name,
+		.probe		= osd_probe,
+		.remove		= osd_remove,
+	}
+};
+
+static int __init osd_uld_init(void)
+{
+	int err;
+
+	osd_sysfs_class = class_create(THIS_MODULE, osd_symlink);
+	if (IS_ERR(osd_sysfs_class)) {
+		OSD_ERR("Unable to register sysfs class => %ld\n",
+			PTR_ERR(osd_sysfs_class));
+		return PTR_ERR(osd_sysfs_class);
+	}
+
+	err = register_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0),
+				     SCSI_OSD_MAX_MINOR, osd_name);
+	if (err) {
+		OSD_ERR("Unable to register major %d for osd ULD => %d\n",
+			SCSI_OSD_MAJOR, err);
+		goto err_out;
+	}
+
+	err = scsi_register_driver(&osd_driver.gendrv);
+	if (err) {
+		OSD_ERR("scsi_register_driver failed => %d\n", err);
+		goto err_out_chrdev;
+	}
+
+	OSD_INFO("LOADED %s\n", osd_version_string);
+	return 0;
+
+err_out_chrdev:
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+err_out:
+	class_destroy(osd_sysfs_class);
+	return err;
+}
+
+static void __exit osd_uld_exit(void)
+{
+	scsi_unregister_driver(&osd_driver.gendrv);
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+	class_destroy(osd_sysfs_class);
+	OSD_INFO("UNLOADED %s\n", osd_version_string);
+}
+
+module_init(osd_uld_init);
+module_exit(osd_uld_exit);
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 12:49     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:49 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Kernel clients like exofs can retrieve struct osd_dev(s)
by means of below API.

+ osduld_path_lookup() - given a path (e.g "/dev/osd0") locks and
returns the corresponding struct osd_dev, which is then needed
for subsequent libosd use.

+ osduld_put_device() - free up use of an osd_dev.

Devices can be shared by multiple clients. The osd_uld_device's
life time is governed by an embedded kref structure.

The osd_uld_device holds an extra reference to both it's
char-device and it's scsi_device, and will release these just
before the final deallocation.

There are three possible lock sources of the osd_uld_device
1. First and for most is the probe() function called by
  scsi-ml upon a successful login into a target. Released in release()
  when logout.
2. Second by user-mode file handles opened on the char-dev.
3. Third is here by Kernel users.
All three locks must be removed before the osd_uld_device is freed.

The MODULE has three lock sources as well:
1. scsi-ml at probe() time, removed after release(). (login/logout)
2. The user-mode file handles open/close.
3. Import symbols by client modules like exofs.

TODO:
  This API is not enough for the pNFS-objects LD. A more versatile
  API will be needed. Proposed API could be:
  struct osd_dev *osduld_sysid_lookup(const char id[OSD_SYSTEMID_LEN]);

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/osd/osd_uld.c   |   64 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_initiator.h |    5 +++
 2 files changed, 69 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index bd6c018..b8cb141 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -42,6 +42,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <linux/namei.h>
 #include <linux/cdev.h>
 #include <linux/fs.h>
 #include <linux/module.h>
@@ -142,6 +143,69 @@ static const struct file_operations osd_fops = {
 	.unlocked_ioctl = osd_uld_ioctl,
 };
 
+struct osd_dev *osduld_path_lookup(const char *path)
+{
+	struct nameidata nd;
+	struct inode *inode;
+	struct cdev *cdev;
+	struct osd_uld_device *uninitialized_var(oud);
+	int error;
+
+	if (!path || !*path) {
+		OSD_ERR("Mount with !path || !*path\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	error = path_lookup(path, LOOKUP_FOLLOW, &nd);
+	if (error) {
+		OSD_ERR("path_lookup of %s faild=>%d\n", path, error);
+		return ERR_PTR(error);
+	}
+
+	inode = nd.path.dentry->d_inode;
+	error = -EINVAL; /* Not the right device e.g osd_uld_device */
+	if (!S_ISCHR(inode->i_mode)) {
+		OSD_DEBUG("!S_ISCHR()\n");
+		goto out;
+	}
+
+	cdev = inode->i_cdev;
+	if (!cdev) {
+		OSD_ERR("Before mounting an OSD Based filesystem\n");
+		OSD_ERR("  user-mode must open+close the %s device\n", path);
+		OSD_ERR("  Example: bash: echo < %s\n", path);
+		goto out;
+	}
+
+	/* The Magic wand. Is it our char-dev */
+	/* TODO: Support sg devices */
+	if (cdev->owner != THIS_MODULE) {
+		OSD_ERR("Error mounting %s - is not an OSD device\n", path);
+		goto out;
+	}
+
+	oud = container_of(cdev, struct osd_uld_device, cdev);
+
+	__uld_get(oud);
+	error = 0;
+
+out:
+	path_put(&nd.path);
+	return error ? ERR_PTR(error) : &oud->od;
+}
+EXPORT_SYMBOL(osduld_path_lookup);
+
+void osduld_put_device(struct osd_dev *od)
+{
+	if (od) {
+		struct osd_uld_device *oud = container_of(od,
+						struct osd_uld_device, od);
+
+		__uld_put(oud);
+	}
+}
+EXPORT_SYMBOL(osduld_put_device);
+
 /*
  * Scsi Device operations
  */
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 1d92247..93fa86b 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -33,6 +33,11 @@ struct osd_dev {
 	unsigned def_timeout;
 };
 
+/* Retrieve/return osd_dev(s) for use by Kernel clients */
+struct osd_dev *osduld_path_lookup(const char *dev_name); /*Use IS_ERR/ERR_PTR*/
+void osduld_put_device(struct osd_dev *od);
+
+/* These are called by uld at probe time */
 void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
 void osd_dev_fini(struct osd_dev *od);
 
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel
@ 2008-12-22 12:49     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:49 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Kernel clients like exofs can retrieve struct osd_dev(s)
by means of below API.

+ osduld_path_lookup() - given a path (e.g "/dev/osd0") locks and
returns the corresponding struct osd_dev, which is then needed
for subsequent libosd use.

+ osduld_put_device() - free up use of an osd_dev.

Devices can be shared by multiple clients. The osd_uld_device's
life time is governed by an embedded kref structure.

The osd_uld_device holds an extra reference to both it's
char-device and it's scsi_device, and will release these just
before the final deallocation.

There are three possible lock sources of the osd_uld_device
1. First and for most is the probe() function called by
  scsi-ml upon a successful login into a target. Released in release()
  when logout.
2. Second by user-mode file handles opened on the char-dev.
3. Third is here by Kernel users.
All three locks must be removed before the osd_uld_device is freed.

The MODULE has three lock sources as well:
1. scsi-ml at probe() time, removed after release(). (login/logout)
2. The user-mode file handles open/close.
3. Import symbols by client modules like exofs.

TODO:
  This API is not enough for the pNFS-objects LD. A more versatile
  API will be needed. Proposed API could be:
  struct osd_dev *osduld_sysid_lookup(const char id[OSD_SYSTEMID_LEN]);

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/osd/osd_uld.c   |   64 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_initiator.h |    5 +++
 2 files changed, 69 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index bd6c018..b8cb141 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -42,6 +42,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <linux/namei.h>
 #include <linux/cdev.h>
 #include <linux/fs.h>
 #include <linux/module.h>
@@ -142,6 +143,69 @@ static const struct file_operations osd_fops = {
 	.unlocked_ioctl = osd_uld_ioctl,
 };
 
+struct osd_dev *osduld_path_lookup(const char *path)
+{
+	struct nameidata nd;
+	struct inode *inode;
+	struct cdev *cdev;
+	struct osd_uld_device *uninitialized_var(oud);
+	int error;
+
+	if (!path || !*path) {
+		OSD_ERR("Mount with !path || !*path\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	error = path_lookup(path, LOOKUP_FOLLOW, &nd);
+	if (error) {
+		OSD_ERR("path_lookup of %s faild=>%d\n", path, error);
+		return ERR_PTR(error);
+	}
+
+	inode = nd.path.dentry->d_inode;
+	error = -EINVAL; /* Not the right device e.g osd_uld_device */
+	if (!S_ISCHR(inode->i_mode)) {
+		OSD_DEBUG("!S_ISCHR()\n");
+		goto out;
+	}
+
+	cdev = inode->i_cdev;
+	if (!cdev) {
+		OSD_ERR("Before mounting an OSD Based filesystem\n");
+		OSD_ERR("  user-mode must open+close the %s device\n", path);
+		OSD_ERR("  Example: bash: echo < %s\n", path);
+		goto out;
+	}
+
+	/* The Magic wand. Is it our char-dev */
+	/* TODO: Support sg devices */
+	if (cdev->owner != THIS_MODULE) {
+		OSD_ERR("Error mounting %s - is not an OSD device\n", path);
+		goto out;
+	}
+
+	oud = container_of(cdev, struct osd_uld_device, cdev);
+
+	__uld_get(oud);
+	error = 0;
+
+out:
+	path_put(&nd.path);
+	return error ? ERR_PTR(error) : &oud->od;
+}
+EXPORT_SYMBOL(osduld_path_lookup);
+
+void osduld_put_device(struct osd_dev *od)
+{
+	if (od) {
+		struct osd_uld_device *oud = container_of(od,
+						struct osd_uld_device, od);
+
+		__uld_put(oud);
+	}
+}
+EXPORT_SYMBOL(osduld_put_device);
+
 /*
  * Scsi Device operations
  */
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 1d92247..93fa86b 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -33,6 +33,11 @@ struct osd_dev {
 	unsigned def_timeout;
 };
 
+/* Retrieve/return osd_dev(s) for use by Kernel clients */
+struct osd_dev *osduld_path_lookup(const char *dev_name); /*Use IS_ERR/ERR_PTR*/
+void osduld_put_device(struct osd_dev *od);
+
+/* These are called by uld at probe time */
 void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
 void osd_dev_fini(struct osd_dev *od);
 
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 07/18] osd_ktests: Add basic OSD tests
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 12:51     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:51 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Currently testing what is implemented in the osd_initiator library.
That is - format, create/remove partition, create/remove object,
read and write to objects.

This test passes against the IBM-OSD-SIM OSDv1 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild       |    2 +-
 drivers/scsi/osd/osd_ktests.c |  331 +++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/osd/osd_ktests.h |    4 +
 drivers/scsi/osd/osd_uld.c    |    2 +-
 4 files changed, 337 insertions(+), 2 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_ktests.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index 4730cdc..6fb823f 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -35,5 +35,5 @@ libosd-y := osd_initiator.o
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
 
 # osd.ko - SCSI ULD and char-device
-osd-y := osd_uld.o
+osd-y := osd_uld.o osd_ktests.o
 obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
new file mode 100644
index 0000000..fba4934
--- /dev/null
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -0,0 +1,331 @@
+/*
+ * osd_ktests.c - An osd_initiator library in-kernel test suite
+ *              called by the osd_uld module
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <asm/unaligned.h>
+#include <linux/vmalloc.h>
+#include <scsi/scsi_device.h>
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+
+#include "osd_ktests.h"
+#include "osd_debug.h"
+
+enum {
+	K = 1024,
+	M = 1024 * K,
+	G = 1024 * M,
+};
+
+const u64 format_total_capacity = 128 * M;
+const osd_id first_par_id = 0x17171717L;
+const osd_id first_obj_id = 0x18181818L;
+const unsigned BUFF_SIZE = PAGE_SIZE;
+
+const int num_partitions = 1;
+const int num_objects = 2; /* per partition */
+
+int test_exec(struct osd_request *or, void *caps, const struct osd_obj_id *obj)
+{
+	int ret;
+
+	osd_sec_init_nosec_doall_caps(caps, obj, false, true);
+	ret = osd_finalize_request(or, 0, caps, NULL);
+	if (ret)
+		return ret;
+
+	ret = osd_execute_request(or);
+	/* osd_req_decode_sense(or, ret); */
+	return ret;
+}
+
+#define KTEST_START_REQ(osd_dev, or) do { \
+	or = osd_start_request(osd_dev, GFP_KERNEL); \
+	if (!or) { \
+		OSD_ERR("Error @%s:%d: osd_start_request", __func__,\
+			__LINE__); \
+		return -ENOMEM; \
+	} \
+} while (0)
+
+#define KTEST_EXEC_END(or, obj, g_caps, msg) do { \
+	ret = test_exec(or, g_caps, obj); \
+	osd_end_request(or); \
+	if (ret) { \
+		OSD_ERR("Error executing "msg" => %d\n", ret); \
+		return ret; \
+	} \
+	OSD_DEBUG(msg "\n"); \
+} while (0)
+
+int ktest_format(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+
+	KTEST_START_REQ(osd_dev, or);
+	osd_req_format(or, format_total_capacity);
+	KTEST_EXEC_END(or, &osd_root_object, g_caps, "format");
+	return 0;
+}
+
+int ktest_creat_par(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p;
+
+	for (p = 0; p < num_partitions; p++) {
+		struct osd_obj_id par = {
+			.partition = first_par_id + p,
+			.id = 0
+		};
+
+		KTEST_START_REQ(osd_dev, or);
+		osd_req_create_partition(or, par.partition);
+		KTEST_EXEC_END(or, &par, g_caps, "create_partition");
+	}
+
+	return 0;
+}
+
+int ktest_creat_obj(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			osd_req_create_object(or, &obj);
+			KTEST_EXEC_END(or, &obj, g_caps, "create_object");
+		}
+
+	return 0;
+}
+
+int ktest_write_obj(struct osd_dev *osd_dev, void *write_buff)
+{
+	struct request_queue *req_q = osd_dev->scsi_device->request_queue;
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o; u64 offset = 0;
+	struct bio *write_bio;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			write_bio = bio_map_kern(req_q, write_buff,
+						 BUFF_SIZE, GFP_KERNEL);
+			if (!write_bio) {
+				OSD_ERR("!!! Failed to allocate write BIO\n");
+				return -ENOMEM;
+			}
+
+			osd_req_write(or, &obj, write_bio, offset);
+			KTEST_EXEC_END(or, &obj, g_caps, "write");
+			write_bio = NULL; /* released by scsi_midlayer */
+			offset += BUFF_SIZE;
+		}
+
+	return 0;
+}
+
+int ktest_read_obj(struct osd_dev *osd_dev, void *write_buff, void *read_buff)
+{
+	struct request_queue *req_q = osd_dev->scsi_device->request_queue;
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o; u64 offset = 0;
+	struct bio *read_bio;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			read_bio = bio_map_kern(req_q, read_buff,
+						BUFF_SIZE, GFP_KERNEL);
+			if (!read_bio) {
+				OSD_ERR("!!! Failed to allocate read BIO\n");
+				return -ENOMEM;
+			}
+
+			osd_req_read(or, &obj, read_bio, offset);
+			KTEST_EXEC_END(or, &obj, g_caps, "read");
+			read_bio = NULL;
+			if (memcmp(read_buff, write_buff, BUFF_SIZE))
+				OSD_ERR("!!! Read did not compare");
+			offset += BUFF_SIZE;
+		}
+
+	return 0;
+}
+
+int ktest_remove_obj(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			osd_req_remove_object(or, &obj);
+			KTEST_EXEC_END(or, &obj, g_caps, "remove_object");
+		}
+
+	return 0;
+}
+
+int ktest_remove_par(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p;
+
+	for (p = 0; p < num_partitions; p++) {
+		struct osd_obj_id par = {
+			.partition = first_par_id + p,
+			.id = 0
+		};
+
+		KTEST_START_REQ(osd_dev, or);
+		osd_req_remove_partition(or, par.partition);
+		KTEST_EXEC_END(or, &par, g_caps, "remove_partition");
+	}
+
+	return 0;
+}
+
+int do_test_17(struct osd_dev *od)
+{
+	void *write_buff = NULL;
+	void *read_buff = NULL;
+	int ret = -ENOMEM, i;
+
+/* osd_format */
+	if (ktest_format(od))
+		goto dev_fini;
+
+/* create some partition */
+	if (ktest_creat_par(od))
+		goto dev_fini;
+/* list partition see if they're all there */
+/* create some objects on some partitions */
+	if (ktest_creat_obj(od))
+		goto dev_fini;
+
+/* Alloc some buffers and bios */
+/*	write_buff = kmalloc(BUFF_SIZE, or->alloc_flags);*/
+/*	read_buff = kmalloc(BUFF_SIZE, or->alloc_flags);*/
+	write_buff = (void *)__get_free_page(GFP_KERNEL);
+	read_buff = (void *)__get_free_page(GFP_KERNEL);
+	if (!write_buff || !read_buff) {
+		OSD_ERR("!!! Failed to allocate memory for test\n");
+		goto dev_fini;
+	}
+	for (i = 0; i < BUFF_SIZE / 4; i++)
+		((int *)write_buff)[i] = i;
+	OSD_DEBUG("allocate buffers\n");
+
+/* write to objects */
+	ret = ktest_write_obj(od, write_buff);
+	if (ret)
+		goto dev_fini;
+
+/* read from objects and compare to write */
+	ret = ktest_read_obj(od, write_buff, read_buff);
+	if (ret)
+		goto dev_fini;
+
+/* List all objects */
+
+/* Write with get_attr */
+/* Write with set_attr */
+/* Write with set_attr + get_attr */
+/* Read with set_attr */
+/* Read with get_attr */
+/* Read with get_attr + set_attr */
+/* remove objects */
+	ret = ktest_remove_obj(od);
+	if (ret)
+		goto dev_fini;
+
+/* remove partitions */
+	ret = ktest_remove_par(od);
+	if (ret)
+		goto dev_fini;
+
+/* good and done */
+	OSD_INFO("test17: All good and done\n");
+dev_fini:
+	if (read_buff)
+		free_page((ulong)read_buff);
+	if (write_buff)
+		free_page((ulong)write_buff);
+
+	return ret;
+}
diff --git a/drivers/scsi/osd/osd_ktests.h b/drivers/scsi/osd/osd_ktests.h
index a9e5e00..b625ee5 100644
--- a/drivers/scsi/osd/osd_ktests.h
+++ b/drivers/scsi/osd/osd_ktests.h
@@ -24,4 +24,8 @@
 
 enum { OSD_TEST_ALL = 17 };
 
+#ifdef __KERNEL__
+extern int do_test_17(struct osd_dev *od);
+#endif /* __KERNEL__ */
+
 #endif /*ndef __OSD_KTESTS_H__*/
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index b8cb141..5ba7654 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -127,7 +127,7 @@ static long osd_uld_ioctl(struct file *file, unsigned int cmd,
 	switch (cmd) {
 	case OSD_TEST_ALL:
 		OSD_DEBUG("Kernel test %d: osd_uld_device=%p\n", cmd, oud);
-		ret = 0;
+		ret = do_test_17(&oud->od);
 		break;
 	default:
 		OSD_ERR("Unknown osd_uld_ioctl %d\n", cmd);
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 07/18] osd_ktests: Add basic OSD tests
@ 2008-12-22 12:51     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:51 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Currently testing what is implemented in the osd_initiator library.
That is - format, create/remove partition, create/remove object,
read and write to objects.

This test passes against the IBM-OSD-SIM OSDv1 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild       |    2 +-
 drivers/scsi/osd/osd_ktests.c |  331 +++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/osd/osd_ktests.h |    4 +
 drivers/scsi/osd/osd_uld.c    |    2 +-
 4 files changed, 337 insertions(+), 2 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_ktests.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index 4730cdc..6fb823f 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -35,5 +35,5 @@ libosd-y := osd_initiator.o
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
 
 # osd.ko - SCSI ULD and char-device
-osd-y := osd_uld.o
+osd-y := osd_uld.o osd_ktests.o
 obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
new file mode 100644
index 0000000..fba4934
--- /dev/null
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -0,0 +1,331 @@
+/*
+ * osd_ktests.c - An osd_initiator library in-kernel test suite
+ *              called by the osd_uld module
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <asm/unaligned.h>
+#include <linux/vmalloc.h>
+#include <scsi/scsi_device.h>
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+
+#include "osd_ktests.h"
+#include "osd_debug.h"
+
+enum {
+	K = 1024,
+	M = 1024 * K,
+	G = 1024 * M,
+};
+
+const u64 format_total_capacity = 128 * M;
+const osd_id first_par_id = 0x17171717L;
+const osd_id first_obj_id = 0x18181818L;
+const unsigned BUFF_SIZE = PAGE_SIZE;
+
+const int num_partitions = 1;
+const int num_objects = 2; /* per partition */
+
+int test_exec(struct osd_request *or, void *caps, const struct osd_obj_id *obj)
+{
+	int ret;
+
+	osd_sec_init_nosec_doall_caps(caps, obj, false, true);
+	ret = osd_finalize_request(or, 0, caps, NULL);
+	if (ret)
+		return ret;
+
+	ret = osd_execute_request(or);
+	/* osd_req_decode_sense(or, ret); */
+	return ret;
+}
+
+#define KTEST_START_REQ(osd_dev, or) do { \
+	or = osd_start_request(osd_dev, GFP_KERNEL); \
+	if (!or) { \
+		OSD_ERR("Error @%s:%d: osd_start_request", __func__,\
+			__LINE__); \
+		return -ENOMEM; \
+	} \
+} while (0)
+
+#define KTEST_EXEC_END(or, obj, g_caps, msg) do { \
+	ret = test_exec(or, g_caps, obj); \
+	osd_end_request(or); \
+	if (ret) { \
+		OSD_ERR("Error executing "msg" => %d\n", ret); \
+		return ret; \
+	} \
+	OSD_DEBUG(msg "\n"); \
+} while (0)
+
+int ktest_format(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+
+	KTEST_START_REQ(osd_dev, or);
+	osd_req_format(or, format_total_capacity);
+	KTEST_EXEC_END(or, &osd_root_object, g_caps, "format");
+	return 0;
+}
+
+int ktest_creat_par(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p;
+
+	for (p = 0; p < num_partitions; p++) {
+		struct osd_obj_id par = {
+			.partition = first_par_id + p,
+			.id = 0
+		};
+
+		KTEST_START_REQ(osd_dev, or);
+		osd_req_create_partition(or, par.partition);
+		KTEST_EXEC_END(or, &par, g_caps, "create_partition");
+	}
+
+	return 0;
+}
+
+int ktest_creat_obj(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			osd_req_create_object(or, &obj);
+			KTEST_EXEC_END(or, &obj, g_caps, "create_object");
+		}
+
+	return 0;
+}
+
+int ktest_write_obj(struct osd_dev *osd_dev, void *write_buff)
+{
+	struct request_queue *req_q = osd_dev->scsi_device->request_queue;
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o; u64 offset = 0;
+	struct bio *write_bio;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			write_bio = bio_map_kern(req_q, write_buff,
+						 BUFF_SIZE, GFP_KERNEL);
+			if (!write_bio) {
+				OSD_ERR("!!! Failed to allocate write BIO\n");
+				return -ENOMEM;
+			}
+
+			osd_req_write(or, &obj, write_bio, offset);
+			KTEST_EXEC_END(or, &obj, g_caps, "write");
+			write_bio = NULL; /* released by scsi_midlayer */
+			offset += BUFF_SIZE;
+		}
+
+	return 0;
+}
+
+int ktest_read_obj(struct osd_dev *osd_dev, void *write_buff, void *read_buff)
+{
+	struct request_queue *req_q = osd_dev->scsi_device->request_queue;
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o; u64 offset = 0;
+	struct bio *read_bio;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			read_bio = bio_map_kern(req_q, read_buff,
+						BUFF_SIZE, GFP_KERNEL);
+			if (!read_bio) {
+				OSD_ERR("!!! Failed to allocate read BIO\n");
+				return -ENOMEM;
+			}
+
+			osd_req_read(or, &obj, read_bio, offset);
+			KTEST_EXEC_END(or, &obj, g_caps, "read");
+			read_bio = NULL;
+			if (memcmp(read_buff, write_buff, BUFF_SIZE))
+				OSD_ERR("!!! Read did not compare");
+			offset += BUFF_SIZE;
+		}
+
+	return 0;
+}
+
+int ktest_remove_obj(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			osd_req_remove_object(or, &obj);
+			KTEST_EXEC_END(or, &obj, g_caps, "remove_object");
+		}
+
+	return 0;
+}
+
+int ktest_remove_par(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p;
+
+	for (p = 0; p < num_partitions; p++) {
+		struct osd_obj_id par = {
+			.partition = first_par_id + p,
+			.id = 0
+		};
+
+		KTEST_START_REQ(osd_dev, or);
+		osd_req_remove_partition(or, par.partition);
+		KTEST_EXEC_END(or, &par, g_caps, "remove_partition");
+	}
+
+	return 0;
+}
+
+int do_test_17(struct osd_dev *od)
+{
+	void *write_buff = NULL;
+	void *read_buff = NULL;
+	int ret = -ENOMEM, i;
+
+/* osd_format */
+	if (ktest_format(od))
+		goto dev_fini;
+
+/* create some partition */
+	if (ktest_creat_par(od))
+		goto dev_fini;
+/* list partition see if they're all there */
+/* create some objects on some partitions */
+	if (ktest_creat_obj(od))
+		goto dev_fini;
+
+/* Alloc some buffers and bios */
+/*	write_buff = kmalloc(BUFF_SIZE, or->alloc_flags);*/
+/*	read_buff = kmalloc(BUFF_SIZE, or->alloc_flags);*/
+	write_buff = (void *)__get_free_page(GFP_KERNEL);
+	read_buff = (void *)__get_free_page(GFP_KERNEL);
+	if (!write_buff || !read_buff) {
+		OSD_ERR("!!! Failed to allocate memory for test\n");
+		goto dev_fini;
+	}
+	for (i = 0; i < BUFF_SIZE / 4; i++)
+		((int *)write_buff)[i] = i;
+	OSD_DEBUG("allocate buffers\n");
+
+/* write to objects */
+	ret = ktest_write_obj(od, write_buff);
+	if (ret)
+		goto dev_fini;
+
+/* read from objects and compare to write */
+	ret = ktest_read_obj(od, write_buff, read_buff);
+	if (ret)
+		goto dev_fini;
+
+/* List all objects */
+
+/* Write with get_attr */
+/* Write with set_attr */
+/* Write with set_attr + get_attr */
+/* Read with set_attr */
+/* Read with get_attr */
+/* Read with get_attr + set_attr */
+/* remove objects */
+	ret = ktest_remove_obj(od);
+	if (ret)
+		goto dev_fini;
+
+/* remove partitions */
+	ret = ktest_remove_par(od);
+	if (ret)
+		goto dev_fini;
+
+/* good and done */
+	OSD_INFO("test17: All good and done\n");
+dev_fini:
+	if (read_buff)
+		free_page((ulong)read_buff);
+	if (write_buff)
+		free_page((ulong)write_buff);
+
+	return ret;
+}
diff --git a/drivers/scsi/osd/osd_ktests.h b/drivers/scsi/osd/osd_ktests.h
index a9e5e00..b625ee5 100644
--- a/drivers/scsi/osd/osd_ktests.h
+++ b/drivers/scsi/osd/osd_ktests.h
@@ -24,4 +24,8 @@
 
 enum { OSD_TEST_ALL = 17 };
 
+#ifdef __KERNEL__
+extern int do_test_17(struct osd_dev *od);
+#endif /* __KERNEL__ */
+
 #endif /*ndef __OSD_KTESTS_H__*/
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index b8cb141..5ba7654 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -127,7 +127,7 @@ static long osd_uld_ioctl(struct file *file, unsigned int cmd,
 	switch (cmd) {
 	case OSD_TEST_ALL:
 		OSD_DEBUG("Kernel test %d: osd_uld_device=%p\n", cmd, oud);
-		ret = 0;
+		ret = do_test_17(&oud->od);
 		break;
 	default:
 		OSD_ERR("Unknown osd_uld_ioctl %d\n", cmd);
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 08/18] libosd: attributes Support
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 12:55     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:55 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Support for both List-Mode and Page-Mode osd attributes. One of
these operations may be added to most other operations.

Define the OSD standard's attribute pages constants and structures
(osd_attributes.h)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  574 ++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_attributes.h    |  327 ++++++++++++++++++++++
 2 files changed, 901 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_attributes.h

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 0e6d906..c760d7a 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -63,6 +63,50 @@ static unsigned _osd_req_cdb_len(struct osd_request *or)
 	return OSDv1_TOTAL_CDB_LEN;
 }
 
+static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
+{
+	return osdv1_attr_list_elem_size(len);
+}
+
+static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
+{
+	return osdv1_list_size(list_head);
+}
+
+static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
+{
+	return sizeof(struct osdv1_attributes_list_header);
+}
+
+static void _osd_req_set_alist_type(struct osd_request *or,
+	void *list, int list_type)
+{
+	struct osdv1_attributes_list_header *attr_list = list;
+
+	memset(attr_list, 0, sizeof(*attr_list));
+	attr_list->type = list_type;
+}
+
+static bool _osd_req_is_alist_type(struct osd_request *or,
+	void *list, int list_type)
+{
+	if (!list)
+		return false;
+
+	if (1) {
+		struct osdv1_attributes_list_header *attr_list = list;
+
+		return attr_list->type == list_type;
+	}
+}
+
+static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
+	u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
 {
 	memset(osdd, 0, sizeof(*osdd));
@@ -125,10 +169,25 @@ static void _abort_unexecuted_bios(struct request *rq)
 	}
 }
 
+static void _osd_free_seg(struct osd_request *or,
+	struct _osd_req_data_segment *seg)
+{
+	if (!seg->buff || !seg->alloc_size)
+		return;
+
+	kfree(seg->buff);
+	seg->buff = NULL;
+	seg->alloc_size = 0;
+}
+
 void osd_end_request(struct osd_request *or)
 {
 	struct request *rq = or->request;
 
+	_osd_free_seg(or, &or->set_attr);
+	_osd_free_seg(or, &or->enc_get_attr);
+	_osd_free_seg(or, &or->get_attr);
+
 	if (rq) {
 		if (rq->next_rq) {
 			_abort_unexecuted_bios(rq->next_rq);
@@ -176,6 +235,54 @@ int osd_execute_request_async(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_execute_request_async);
 
+u8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+u8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+
+static int _osd_realloc_seg(struct osd_request *or,
+	struct _osd_req_data_segment *seg, unsigned max_bytes)
+{
+	void *buff;
+
+	if (seg->alloc_size >= max_bytes)
+		return 0;
+
+	buff = krealloc(seg->buff, max_bytes, or->alloc_flags);
+	if (!buff) {
+		OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes,
+			seg->alloc_size);
+		return -ENOMEM;
+	}
+
+	memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size);
+	seg->buff = buff;
+	seg->alloc_size = max_bytes;
+	return 0;
+}
+
+static int _alloc_set_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem, unsigned add_bytes)
+{
+	unsigned total_bytes = add_bytes;
+
+	for (; nelem; --nelem, ++oa)
+		total_bytes += _osd_req_alist_elem_size(or, oa->len);
+
+	OSD_DEBUG("total_bytes=%d\n", total_bytes);
+	return _osd_realloc_seg(or, &or->set_attr, total_bytes);
+}
+
+static int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes)
+{
+	OSD_DEBUG("total_bytes=%d\n", max_bytes);
+	return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes);
+}
+
+static int _alloc_get_attr_list(struct osd_request *or)
+{
+	OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes);
+	return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes);
+}
+
 /*
  * Common to all OSD commands
  */
@@ -284,6 +391,409 @@ void osd_req_read(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_read);
 
+void osd_req_get_attributes(struct osd_request *or,
+	const struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_get_attributes);
+
+void osd_req_set_attributes(struct osd_request *or,
+	const struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_set_attributes);
+
+/*
+ * Attributes List-mode
+ */
+
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem)
+{
+	unsigned total_bytes = or->set_attr.total_bytes;
+	void *attr_last;
+	int ret;
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+	if (!total_bytes) { /* first-time: allocate and put list header */
+		total_bytes = _osd_req_sizeof_alist_header(or);
+		ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+		if (ret)
+			return ret;
+		_osd_req_set_alist_type(or, or->set_attr.buff,
+					OSD_ATTR_LIST_SET_RETRIEVE);
+	}
+	attr_last = or->set_attr.buff + total_bytes;
+
+	for (; nelem; --nelem) {
+		struct osd_attributes_list_element *attr;
+		unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
+
+		total_bytes += elem_size;
+		if (unlikely(or->set_attr.alloc_size < total_bytes)) {
+			or->set_attr.total_bytes = total_bytes - elem_size;
+			ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+			if (ret)
+				return ret;
+			attr_last =
+				or->set_attr.buff + or->set_attr.total_bytes;
+		}
+
+		attr = attr_last;
+		attr->page = cpu_to_be32(oa->page);
+		attr->attr_id = cpu_to_be32(oa->attr_id);
+		attr->attr_bytes = cpu_to_be16(oa->len);
+		memcpy(attr->attr_val, oa->val_ptr, oa->len);
+
+		attr_last += elem_size;
+		++oa;
+	}
+
+	or->set_attr.total_bytes = total_bytes;
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_set_attr_list);
+
+static int _append_map_kern(struct request *req,
+	void *buff, unsigned len, gfp_t flags)
+{
+	struct bio *bio;
+	int ret;
+
+	bio = bio_map_kern(req->q, buff, len, flags);
+	if (IS_ERR(bio)) {
+		OSD_ERR("Failed bio_map_kern(%p, %d) => %ld\n", buff, len,
+			PTR_ERR(bio));
+		return PTR_ERR(bio);
+	}
+	ret = blk_rq_append_bio(req->q, req, bio);
+	if (ret) {
+		OSD_ERR("Failed blk_rq_append_bio(%p) => %d\n", bio, ret);
+		bio_put(bio);
+	}
+	return ret;
+}
+
+static int _req_append_segment(struct osd_request *or,
+	int padding, struct _osd_req_data_segment *seg,
+	struct _osd_req_data_segment *last_seg, struct _osd_io_info *io)
+{
+	void *pad_buff;
+	int ret;
+
+	if (padding) {
+		/* check if we can just add it to last buffer */
+		if (last_seg &&
+		    (padding <= last_seg->alloc_size - last_seg->total_bytes))
+			pad_buff = last_seg->buff + last_seg->total_bytes;
+		else
+			pad_buff = io->pad_buff;
+
+		ret = _append_map_kern(io->req, pad_buff, padding,
+				       or->alloc_flags);
+		if (ret)
+			return ret;
+		io->total_bytes += padding;
+	}
+
+	ret = _append_map_kern(io->req, seg->buff, seg->total_bytes,
+			       or->alloc_flags);
+	if (ret)
+		return ret;
+
+	io->total_bytes += seg->total_bytes;
+	OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff,
+		  seg->total_bytes);
+	return 0;
+}
+
+static int _osd_req_finalize_set_attr_list(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	int padding;
+	int ret;
+
+	if (!or->set_attr.total_bytes) {
+		cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED;
+		return 0;
+	}
+
+	cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes);
+	cdbh->attrs_list.set_attr_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &padding);
+
+	ret = _req_append_segment(or, padding, &or->set_attr,
+				  or->out.last_seg, &or->out);
+	if (ret)
+		return ret;
+
+	or->out.last_seg = &or->set_attr;
+	return 0;
+}
+
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem)
+{
+	unsigned total_bytes = or->enc_get_attr.total_bytes;
+	void *attr_last;
+	int ret;
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+	/* first time calc data-in list header size */
+	if (!or->get_attr.total_bytes)
+		or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or);
+
+	/* calc data-out info */
+	if (!total_bytes) { /* first-time: allocate and put list header */
+		unsigned max_bytes;
+
+		total_bytes = _osd_req_sizeof_alist_header(or);
+		max_bytes = total_bytes +
+			nelem * sizeof(struct osd_attributes_list_attrid);
+		ret = _alloc_get_attr_desc(or, max_bytes);
+		if (ret)
+			return ret;
+
+		_osd_req_set_alist_type(or, or->enc_get_attr.buff,
+					OSD_ATTR_LIST_GET);
+	}
+	attr_last = or->enc_get_attr.buff + total_bytes;
+
+	for (; nelem; --nelem) {
+		struct osd_attributes_list_attrid *attrid;
+		const unsigned cur_size = sizeof(*attrid);
+
+		total_bytes += cur_size;
+		if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) {
+			or->enc_get_attr.total_bytes = total_bytes - cur_size;
+			ret = _alloc_get_attr_desc(or,
+					total_bytes + nelem * sizeof(*attrid));
+			if (ret)
+				return ret;
+			attr_last = or->enc_get_attr.buff +
+				or->enc_get_attr.total_bytes;
+		}
+
+		attrid = attr_last;
+		attrid->page = cpu_to_be32(oa->page);
+		attrid->attr_id = cpu_to_be32(oa->attr_id);
+
+		attr_last += cur_size;
+
+		/* calc data-in size */
+		or->get_attr.total_bytes +=
+			_osd_req_alist_elem_size(or, oa->len);
+		++oa;
+	}
+
+	or->enc_get_attr.total_bytes = total_bytes;
+
+	OSD_DEBUG(
+	       "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n",
+	       or->get_attr.total_bytes,
+	       or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or),
+	       or->enc_get_attr.total_bytes,
+	       (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or))
+			/ sizeof(struct osd_attributes_list_attrid));
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_list);
+
+static int _osd_req_finalize_get_attr_list(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	unsigned out_padding;
+	unsigned in_padding;
+	int ret;
+
+	if (!or->enc_get_attr.total_bytes) {
+		cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED;
+		cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED;
+		return 0;
+	}
+
+	ret = _alloc_get_attr_list(or);
+	if (ret)
+		return ret;
+
+	/* The out-going buffer info update */
+	OSD_DEBUG("out-going\n");
+	cdbh->attrs_list.get_attr_desc_bytes =
+		cpu_to_be32(or->enc_get_attr.total_bytes);
+
+	cdbh->attrs_list.get_attr_desc_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+	ret = _req_append_segment(or, out_padding, &or->enc_get_attr,
+				  or->out.last_seg, &or->out);
+	if (ret)
+		return ret;
+	or->out.last_seg = &or->enc_get_attr;
+
+	/* The incoming buffer info update */
+	OSD_DEBUG("in-coming\n");
+	cdbh->attrs_list.get_attr_alloc_length =
+		cpu_to_be32(or->get_attr.total_bytes);
+
+	cdbh->attrs_list.get_attr_offset =
+		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+				  &or->in);
+	if (ret)
+		return ret;
+	or->in.last_seg = &or->get_attr;
+
+	return 0;
+}
+
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *oa, int *nelem, void **iterator)
+{
+	unsigned cur_bytes, returned_bytes, n;
+	const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or);
+	void *cur_p;
+
+	if (!_osd_req_is_alist_type(or, or->get_attr.buff,
+				    OSD_ATTR_LIST_SET_RETRIEVE)) {
+		oa->page = 0;
+		oa->attr_id = 0;
+		oa->val_ptr = NULL;
+		oa->len = 0;
+		*iterator = NULL;
+		return 0;
+	}
+
+	if (*iterator) {
+		BUG_ON((*iterator < or->get_attr.buff) ||
+		     (or->get_attr.buff + or->get_attr.alloc_size < *iterator));
+		cur_p = *iterator;
+		cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list;
+		returned_bytes = or->get_attr.total_bytes;
+	} else { /* first time decode the list header */
+		cur_bytes = sizeof_attr_list;
+		returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) +
+					sizeof_attr_list;
+
+		cur_p = or->get_attr.buff + sizeof_attr_list;
+
+		if (returned_bytes > or->get_attr.alloc_size) {
+			OSD_DEBUG("target report: space was not big enough! "
+				  "Allocate=%u Needed=%u\n",
+				  or->get_attr.alloc_size,
+				  returned_bytes + sizeof_attr_list);
+
+			returned_bytes =
+				or->get_attr.alloc_size - sizeof_attr_list;
+		}
+		or->get_attr.total_bytes = returned_bytes;
+	}
+
+	for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
+		struct osd_attributes_list_element *attr = cur_p;
+		unsigned inc;
+
+		oa->len = be16_to_cpu(attr->attr_bytes);
+		inc = _osd_req_alist_elem_size(or, oa->len);
+		OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n",
+			  oa->len, inc, cur_bytes);
+		cur_bytes += inc;
+		if (cur_bytes > returned_bytes) {
+			OSD_ERR("BAD FOOD from target. list not valid!"
+				"c=%d r=%d n=%d\n",
+				cur_bytes, returned_bytes, n);
+			oa->val_ptr = NULL;
+			break;
+		}
+
+		oa->page = be32_to_cpu(attr->page);
+		oa->attr_id = be32_to_cpu(attr->attr_id);
+		oa->val_ptr = attr->attr_val;
+
+		cur_p += inc;
+		++oa;
+	}
+
+	*iterator = (returned_bytes - cur_bytes) ? cur_p : NULL;
+	*nelem = n;
+	return returned_bytes - cur_bytes;
+}
+EXPORT_SYMBOL(osd_req_decode_get_attr_list);
+
+/*
+ * Attributes Page-mode
+ */
+
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attar_page, unsigned max_page_len,
+	const struct osd_attr *set_one_attr)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE;
+
+	or->get_attr.buff = attar_page;
+	or->get_attr.total_bytes = max_page_len;
+
+	or->set_attr.buff = set_one_attr->val_ptr;
+	or->set_attr.total_bytes = set_one_attr->len;
+
+	cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id);
+	cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len);
+	/* ocdb->attrs_page.get_attr_offset; */
+
+	cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->page);
+	cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id);
+	cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len);
+	/* ocdb->attrs_page.set_attr_offset; */
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_page);
+
+static int _osd_req_finalize_attr_page(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	int in_padding, out_padding;
+	int ret;
+
+	/* returned page */
+	cdbh->attrs_page.get_attr_offset =
+		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+				  &or->in);
+	if (ret)
+		return ret;
+
+	/* set one value */
+	cdbh->attrs_page.set_attr_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+	ret = _req_append_segment(or, out_padding, &or->enc_get_attr, NULL,
+				  &or->out);
+	return ret;
+}
+
 /*
  * osd_finalize_request and helpers
  */
@@ -378,9 +888,31 @@ int osd_finalize_request(struct osd_request *or,
 			_LLU(or->in.total_bytes), or->in.req->data_len);
 	}
 
+	or->out.pad_buff = sg_out_pad_buffer;
+	or->in.pad_buff = sg_in_pad_buffer;
+
 	if (!or->attributes_mode)
 		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
 	cdbh->command_specific_options |= or->attributes_mode;
+	if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+		ret = _osd_req_finalize_attr_page(or);
+	} else {
+		/* TODO: I think that for the GET_ATTR command these 2 should
+		 * be reversed to keep them in execution order (for embeded
+		 * targets with low memory footprint)
+		 */
+		ret = _osd_req_finalize_set_attr_list(or);
+		if (ret) {
+			OSD_DEBUG("_osd_req_finalize_set_attr_list failed\n");
+			return ret;
+		}
+
+		ret = _osd_req_finalize_get_attr_list(or);
+		if (ret) {
+			OSD_DEBUG("_osd_req_finalize_get_attr_list failed\n");
+			return ret;
+		}
+	}
 
 	or->request->cmd = or->cdb.buff;
 	or->request->cmd_len = _osd_req_cdb_len(or);
@@ -446,3 +978,45 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 {
 	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
 }
+
+/*
+ * Declared in osd_protocol.h
+ * 4.12.5 Data-In and Data-Out buffer offsets
+ * byte offset = mantissa * (2^(exponent+8))
+ * Returns the smallest allowed encoded offset that contains given @offset
+ * The actual encoded offset returned is @offset + *@padding.
+ */
+osd_cdb_offset __osd_encode_offset(
+	u64 offset, unsigned *padding, int min_shift, int max_shift)
+{
+	u64 try_offset = -1, mod, align;
+	osd_cdb_offset be32_offset;
+	int shift;
+
+	*padding = 0;
+	if (!offset)
+		return 0;
+
+	for (shift = min_shift; shift < max_shift; ++shift) {
+		try_offset = offset >> shift;
+		if (try_offset < (1 << OSD_OFFSET_MAX_BITS))
+			break;
+	}
+
+	BUG_ON(shift == max_shift);
+
+	align = 1 << shift;
+	mod = offset & (align - 1);
+	if (mod) {
+		*padding = align - mod;
+		try_offset += 1;
+	}
+
+	try_offset |= ((shift - 8) & 0xf) << 28;
+	be32_offset = cpu_to_be32((u32)try_offset);
+
+	OSD_DEBUG("offset=%llu mantissa=%llu exp=%d encoded=%x pad=%d\n",
+		 _LLU(offset), _LLU(try_offset & 0x0FFFFFFF), shift,
+		 be32_offset, *padding);
+	return be32_offset;
+}
diff --git a/include/scsi/osd_attributes.h b/include/scsi/osd_attributes.h
new file mode 100644
index 0000000..c53f49b
--- /dev/null
+++ b/include/scsi/osd_attributes.h
@@ -0,0 +1,327 @@
+#ifndef __OSD_ATTRIBUTES_H__
+#define __OSD_ATTRIBUTES_H__
+
+#include "osd_protocol.h"
+
+/*
+ * Contains types and constants that define attribute pages and attribute
+ * numbers and their data types.
+ */
+
+#define ATTR_SET(pg, id, l, ptr) \
+	{ .page = pg, .attr_id = id, .len = l, .val_ptr = ptr }
+
+#define ATTR_DEF(pg, id, l) ATTR_SET(pg, id, l, NULL)
+
+/* osd-r10 4.7.3 Attributes pages */
+enum {
+	OSD_APAGE_OBJECT_FIRST		= 0x0,
+	OSD_APAGE_OBJECT_DIRECTORY	= 0,
+	OSD_APAGE_OBJECT_INFORMATION	= 1,
+	OSD_APAGE_OBJECT_QUOTAS		= 2,
+	OSD_APAGE_OBJECT_TIMESTAMP	= 3,
+	OSD_APAGE_OBJECT_COLLECTIONS	= 4,
+	OSD_APAGE_OBJECT_SECURITY	= 5,
+	OSD_APAGE_OBJECT_LAST		= 0x2fffffff,
+
+	OSD_APAGE_PARTITION_FIRST	= 0x30000000,
+	OSD_APAGE_PARTITION_DIRECTORY	= OSD_APAGE_PARTITION_FIRST + 0,
+	OSD_APAGE_PARTITION_INFORMATION = OSD_APAGE_PARTITION_FIRST + 1,
+	OSD_APAGE_PARTITION_QUOTAS	= OSD_APAGE_PARTITION_FIRST + 2,
+	OSD_APAGE_PARTITION_TIMESTAMP	= OSD_APAGE_PARTITION_FIRST + 3,
+	OSD_APAGE_PARTITION_SECURITY	= OSD_APAGE_PARTITION_FIRST + 5,
+	OSD_APAGE_PARTITION_LAST	= 0x5FFFFFFF,
+
+	OSD_APAGE_COLLECTION_FIRST	= 0x60000000,
+	OSD_APAGE_COLLECTION_DIRECTORY	= OSD_APAGE_COLLECTION_FIRST + 0,
+	OSD_APAGE_COLLECTION_INFORMATION = OSD_APAGE_COLLECTION_FIRST + 1,
+	OSD_APAGE_COLLECTION_TIMESTAMP	= OSD_APAGE_COLLECTION_FIRST + 3,
+	OSD_APAGE_COLLECTION_SECURITY	= OSD_APAGE_COLLECTION_FIRST + 5,
+	OSD_APAGE_COLLECTION_LAST	= 0x8FFFFFFF,
+
+	OSD_APAGE_ROOT_FIRST		= 0x90000000,
+	OSD_APAGE_ROOT_DIRECTORY	= OSD_APAGE_ROOT_FIRST + 0,
+	OSD_APAGE_ROOT_INFORMATION	= OSD_APAGE_ROOT_FIRST + 1,
+	OSD_APAGE_ROOT_QUOTAS		= OSD_APAGE_ROOT_FIRST + 2,
+	OSD_APAGE_ROOT_TIMESTAMP	= OSD_APAGE_ROOT_FIRST + 3,
+	OSD_APAGE_ROOT_SECURITY		= OSD_APAGE_ROOT_FIRST + 5,
+	OSD_APAGE_ROOT_LAST		= 0xBFFFFFFF,
+
+	OSD_APAGE_RESERVED_TYPE_FIRST	= 0xC0000000,
+	OSD_APAGE_RESERVED_TYPE_LAST	= 0xEFFFFFFF,
+
+	OSD_APAGE_COMMON_FIRST		= 0xF0000000,
+	OSD_APAGE_COMMON_LAST		= 0xFFFFFFFE,
+
+	OSD_APAGE_REQUEST_ALL		= 0xFFFFFFFF,
+};
+
+/* subcategories of attr pages within each range above */
+enum {
+	OSD_APAGE_STD_FIRST		= 0x0,
+	OSD_APAGE_STD_DIRECTORY		= 0,
+	OSD_APAGE_STD_INFORMATION	= 1,
+	OSD_APAGE_STD_QUOTAS		= 2,
+	OSD_APAGE_STD_TIMESTAMP		= 3,
+	OSD_APAGE_STD_COLLECTIONS	= 4,
+	OSD_APAGE_STD_POLICY_SECURITY	= 5,
+	OSD_APAGE_STD_LAST		= 0x0000007F,
+
+	OSD_APAGE_RESERVED_FIRST	= 0x00000080,
+	OSD_APAGE_RESERVED_LAST		= 0x00007FFF,
+
+	OSD_APAGE_OTHER_STD_FIRST	= 0x00008000,
+	OSD_APAGE_OTHER_STD_LAST	= 0x0000EFFF,
+
+	OSD_APAGE_PUBLIC_FIRST		= 0x0000F000,
+	OSD_APAGE_PUBLIC_LAST		= 0x0000FFFF,
+
+	OSD_APAGE_APP_DEFINED_FIRST	= 0x00010000,
+	OSD_APAGE_APP_DEFINED_LAST	= 0x1FFFFFFF,
+
+	OSD_APAGE_VENDOR_SPECIFIC_FIRST	= 0x20000000,
+	OSD_APAGE_VENDOR_SPECIFIC_LAST	= 0x2FFFFFFF,
+};
+
+enum {
+	OSD_ATTR_PAGE_IDENTIFICATION = 0, /* in all pages 40 bytes */
+};
+
+struct page_identification {
+	u8 vendor_identification[8];
+	u8 page_identification[32];
+}  __packed;
+
+struct osd_attr_page_header {
+	__be32 page_number;
+	__be32 page_length;
+} __packed;
+
+/* 7.1.2.8 Root Information attributes page (OSD_APAGE_ROOT_INFORMATION) */
+enum {
+	OSD_ATTR_RI_OSD_SYSTEM_ID            = 0x3,   /* 20       */
+	OSD_ATTR_RI_VENDOR_IDENTIFICATION    = 0x4,   /* 8        */
+	OSD_ATTR_RI_PRODUCT_IDENTIFICATION   = 0x5,   /* 16       */
+	OSD_ATTR_RI_PRODUCT_MODEL            = 0x6,   /* 32       */
+	OSD_ATTR_RI_PRODUCT_REVISION_LEVEL   = 0x7,   /* 4        */
+	OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER    = 0x8,   /* variable */
+	OSD_ATTR_RI_OSD_NAME                 = 0x9,   /* variable */
+	OSD_ATTR_RI_TOTAL_CAPACITY           = 0x80,  /* 8        */
+	OSD_ATTR_RI_USED_CAPACITY            = 0x81,  /* 8        */
+	OSD_ATTR_RI_NUMBER_OF_PARTITIONS     = 0xC0,  /* 8        */
+	OSD_ATTR_RI_CLOCK                    = 0x100, /* 6        */
+};
+/* Root_Information_attributes_page does not have a get_page structure */
+
+/* 7.1.2.9 Partition Information attributes page
+ * (OSD_APAGE_PARTITION_INFORMATION)
+ */
+enum {
+	OSD_ATTR_PI_PARTITION_ID            = 0x1,     /* 8        */
+	OSD_ATTR_PI_USERNAME                = 0x9,     /* variable */
+	OSD_ATTR_PI_USED_CAPACITY           = 0x81,    /* 8        */
+	OSD_ATTR_PI_NUMBER_OF_OBJECTS       = 0xC1,    /* 8        */
+};
+/* Partition Information attributes page does not have a get_page structure */
+
+/* 7.1.2.10 Collection Information attributes page
+ * (OSD_APAGE_COLLECTION_INFORMATION)
+ */
+enum {
+	OSD_ATTR_CI_PARTITION_ID           = 0x1,       /* 8        */
+	OSD_ATTR_CI_COLLECTION_OBJECT_ID   = 0x2,       /* 8        */
+	OSD_ATTR_CI_USERNAME               = 0x9,       /* variable */
+	OSD_ATTR_CI_USED_CAPACITY          = 0x81,      /* 8        */
+};
+/* Collection Information attributes page does not have a get_page structure */
+
+/* 7.1.2.11 User Object Information attributes page
+ * (OSD_APAGE_OBJECT_INFORMATION)
+ */
+enum {
+	OSD_ATTR_OI_PARTITION_ID         = 0x1,       /* 8        */
+	OSD_ATTR_OI_OBJECT_ID            = 0x2,       /* 8        */
+	OSD_ATTR_OI_USERNAME             = 0x9,       /* variable */
+	OSD_ATTR_OI_USED_CAPACITY        = 0x81,      /* 8        */
+	OSD_ATTR_OI_LOGICAL_LENGTH       = 0x82,      /* 8        */
+};
+/* Object Information attributes page does not have a get_page structure */
+
+/* 7.1.2.12 Root Quotas attributes page (OSD_APAGE_ROOT_QUOTAS) */
+enum {
+	OSD_ATTR_RQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH     = 0x1,      /* 8  */
+	OSD_ATTR_RQ_PARTITION_CAPACITY_QUOTA               = 0x10001,  /* 8  */
+	OSD_ATTR_RQ_PARTITION_OBJECT_COUNT                 = 0x10002,  /* 8  */
+	OSD_ATTR_RQ_PARTITION_COLLECTIONS_PER_USER_OBJECT  = 0x10081,  /* 4  */
+	OSD_ATTR_RQ_PARTITION_COUNT                        = 0x20002,  /* 8  */
+};
+
+struct Root_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+2, size=0x24 */
+	__be64 default_maximum_user_object_length;
+	__be64 partition_capacity_quota;
+	__be64 partition_object_count;
+	__be64 partition_collections_per_user_object;
+	__be64 partition_count;
+}  __packed;
+
+/* 7.1.2.13 Partition Quotas attributes page (OSD_APAGE_PARTITION_QUOTAS)*/
+enum {
+	OSD_ATTR_PQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH  = 0x1,        /* 8 */
+	OSD_ATTR_PQ_CAPACITY_QUOTA                      = 0x10001,    /* 8 */
+	OSD_ATTR_PQ_OBJECT_COUNT                        = 0x10002,    /* 8 */
+	OSD_ATTR_PQ_COLLECTIONS_PER_USER_OBJECT         = 0x10081,    /* 4 */
+};
+
+struct Partition_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=P+2, size=0x1C */
+	__be64 default_maximum_user_object_length;
+	__be64 capacity_quota;
+	__be64 object_count;
+	__be64 collections_per_user_object;
+}  __packed;
+
+/* 7.1.2.14 User Object Quotas attributes page (OSD_APAGE_OBJECT_QUOTAS) */
+enum {
+	OSD_ATTR_OQ_MAXIMUM_LENGTH  = 0x1,        /* 8 */
+};
+
+struct Object_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=U+2, size=0x8 */
+	__be64 maximum_length;
+}  __packed;
+
+/* 7.1.2.15 Root Timestamps attributes page (OSD_APAGE_ROOT_TIMESTAMP) */
+enum {
+	OSD_ATTR_RT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_RT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_RT_TIMESTAMP_BYPASS          = 0xFFFFFFFE, /* 1 */
+};
+
+struct root_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+3, size=0xD */
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	u8 timestamp_bypass;
+}  __packed;
+
+/* 7.1.2.16 Partition Timestamps attributes page
+ * (OSD_APAGE_PARTITION_TIMESTAMP)
+ */
+enum {
+	OSD_ATTR_PT_CREATED_TIME              = 0x1,        /* 6 */
+	OSD_ATTR_PT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_PT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_PT_DATA_ACCESSED_TIME        = 0x4,        /* 6 */
+	OSD_ATTR_PT_DATA_MODIFIED_TIME        = 0x5,        /* 6 */
+	OSD_ATTR_PT_TIMESTAMP_BYPASS          = 0xFFFFFFFE, /* 1 */
+};
+
+struct partition_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=P+3, size=0x1F */
+	struct osd_timestamp created_time;
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	struct osd_timestamp data_accessed_time;
+	struct osd_timestamp data_modified_time;
+	u8 timestamp_bypass;
+}  __packed;
+
+/* 7.1.2.17/18 Collection/Object Timestamps attributes page
+ * (OSD_APAGE_COLLECTION_TIMESTAMP/OSD_APAGE_OBJECT_TIMESTAMP)
+ */
+enum {
+	OSD_ATTR_OT_CREATED_TIME              = 0x1,        /* 6 */
+	OSD_ATTR_OT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_OT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_OT_DATA_ACCESSED_TIME        = 0x4,        /* 6 */
+	OSD_ATTR_OT_DATA_MODIFIED_TIME        = 0x5,        /* 6 */
+};
+
+/* same for collection */
+struct object_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=C+3/3, size=0x1E */
+	struct osd_timestamp created_time;
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	struct osd_timestamp data_accessed_time;
+	struct osd_timestamp data_modified_time;
+}  __packed;
+
+/* 7.1.2.19 Collections attributes page */
+/* TBD */
+
+/* 7.1.2.20 Root Policy/Security attributes page (OSD_APAGE_ROOT_SECURITY) */
+enum {
+	OSD_ATTR_RS_DEFAULT_SECURITY_METHOD           = 0x1,       /* 1      */
+	OSD_ATTR_RS_OLDEST_VALID_NONCE_LIMIT          = 0x2,       /* 6      */
+	OSD_ATTR_RS_NEWEST_VALID_NONCE_LIMIT          = 0x3,       /* 6      */
+	OSD_ATTR_RS_PARTITION_DEFAULT_SECURITY_METHOD = 0x6,       /* 1      */
+	OSD_ATTR_RS_SUPPORTED_SECURITY_METHODS        = 0x7,       /* 2      */
+	OSD_ATTR_RS_ADJUSTABLE_CLOCK                  = 0x9,       /* 6      */
+	OSD_ATTR_RS_MASTER_KEY_IDENTIFIER             = 0x7FFD,    /* 0 or 7 */
+	OSD_ATTR_RS_ROOT_KEY_IDENTIFIER               = 0x7FFE,    /* 0 or 7 */
+	OSD_ATTR_RS_SUPPORTED_INTEGRITY_ALGORITHM_0   = 0x80000000,/* 1,(x16)*/
+	OSD_ATTR_RS_SUPPORTED_DH_GROUP_0              = 0x80000010,/* 1,(x16)*/
+};
+
+struct root_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+5, size=0x3F */
+	u8 default_security_method;
+	u8 partition_default_security_method;
+	__be16 supported_security_methods;
+	u8 mki_valid_rki_valid;
+	struct osd_timestamp oldest_valid_nonce_limit;
+	struct osd_timestamp newest_valid_nonce_limit;
+	struct osd_timestamp adjustable_clock;
+	u8 master_key_identifier[32-25];
+	u8 root_key_identifier[39-32];
+	u8 supported_integrity_algorithm[16];
+	u8 supported_dh_group[16];
+}  __packed;
+
+/* 7.1.2.21 Partition Policy/Security attributes page
+ * (OSD_APAGE_PARTITION_SECURITY)
+ */
+enum {
+	OSD_ATTR_PS_DEFAULT_SECURITY_METHOD        = 0x1,        /* 1      */
+	OSD_ATTR_PS_OLDEST_VALID_NONCE             = 0x2,        /* 6      */
+	OSD_ATTR_PS_NEWEST_VALID_NONCE             = 0x3,        /* 6      */
+	OSD_ATTR_PS_REQUEST_NONCE_LIST_DEPTH       = 0x4,        /* 2      */
+	OSD_ATTR_PS_FROZEN_WORKING_KEY_BIT_MASK    = 0x5,        /* 2      */
+	OSD_ATTR_PS_PARTITION_KEY_IDENTIFIER       = 0x7FFF,     /* 0 or 7 */
+	OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_FIRST   = 0x8000,     /* 0 or 7 */
+	OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_LAST    = 0x800F,     /* 0 or 7 */
+	OSD_ATTR_PS_POLICY_ACCESS_TAG              = 0x40000001, /* 4      */
+	OSD_ATTR_PS_USER_OBJECT_POLICY_ACCESS_TAG  = 0x40000002, /* 4      */
+};
+
+struct partition_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=p+5, size=0x8f */
+	u8 reserved[3];
+	u8 default_security_method;
+	struct osd_timestamp oldest_valid_nonce;
+	struct osd_timestamp newest_valid_nonce;
+	__be16 request_nonce_list_depth;
+	__be16 frozen_working_key_bit_mask;
+	__be32 policy_access_tag;
+	__be32 user_object_policy_access_tag;
+	u8 pki_valid;
+	__be16 wki_00_0f_vld;
+	struct osd_key_identifier partition_key_identifier;
+	struct osd_key_identifier working_key_identifiers[16];
+}  __packed;
+
+/* 7.1.2.22/23 Collection/Object Policy-Security attributes page
+ * (OSD_APAGE_COLLECTION_SECURITY/OSD_APAGE_OBJECT_SECURITY)
+ */
+enum {
+	OSD_ATTR_OS_POLICY_ACCESS_TAG              = 0x40000001, /* 4      */
+};
+
+struct object_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=C+5/5, size=4 */
+	__be32 policy_access_tag;
+}  __packed;
+
+#endif /*ndef __OSD_ATTRIBUTES_H__*/
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 08/18] libosd: attributes Support
@ 2008-12-22 12:55     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:55 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Support for both List-Mode and Page-Mode osd attributes. One of
these operations may be added to most other operations.

Define the OSD standard's attribute pages constants and structures
(osd_attributes.h)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  574 ++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_attributes.h    |  327 ++++++++++++++++++++++
 2 files changed, 901 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_attributes.h

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 0e6d906..c760d7a 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -63,6 +63,50 @@ static unsigned _osd_req_cdb_len(struct osd_request *or)
 	return OSDv1_TOTAL_CDB_LEN;
 }
 
+static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
+{
+	return osdv1_attr_list_elem_size(len);
+}
+
+static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
+{
+	return osdv1_list_size(list_head);
+}
+
+static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
+{
+	return sizeof(struct osdv1_attributes_list_header);
+}
+
+static void _osd_req_set_alist_type(struct osd_request *or,
+	void *list, int list_type)
+{
+	struct osdv1_attributes_list_header *attr_list = list;
+
+	memset(attr_list, 0, sizeof(*attr_list));
+	attr_list->type = list_type;
+}
+
+static bool _osd_req_is_alist_type(struct osd_request *or,
+	void *list, int list_type)
+{
+	if (!list)
+		return false;
+
+	if (1) {
+		struct osdv1_attributes_list_header *attr_list = list;
+
+		return attr_list->type == list_type;
+	}
+}
+
+static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
+	u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
 {
 	memset(osdd, 0, sizeof(*osdd));
@@ -125,10 +169,25 @@ static void _abort_unexecuted_bios(struct request *rq)
 	}
 }
 
+static void _osd_free_seg(struct osd_request *or,
+	struct _osd_req_data_segment *seg)
+{
+	if (!seg->buff || !seg->alloc_size)
+		return;
+
+	kfree(seg->buff);
+	seg->buff = NULL;
+	seg->alloc_size = 0;
+}
+
 void osd_end_request(struct osd_request *or)
 {
 	struct request *rq = or->request;
 
+	_osd_free_seg(or, &or->set_attr);
+	_osd_free_seg(or, &or->enc_get_attr);
+	_osd_free_seg(or, &or->get_attr);
+
 	if (rq) {
 		if (rq->next_rq) {
 			_abort_unexecuted_bios(rq->next_rq);
@@ -176,6 +235,54 @@ int osd_execute_request_async(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_execute_request_async);
 
+u8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+u8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+
+static int _osd_realloc_seg(struct osd_request *or,
+	struct _osd_req_data_segment *seg, unsigned max_bytes)
+{
+	void *buff;
+
+	if (seg->alloc_size >= max_bytes)
+		return 0;
+
+	buff = krealloc(seg->buff, max_bytes, or->alloc_flags);
+	if (!buff) {
+		OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes,
+			seg->alloc_size);
+		return -ENOMEM;
+	}
+
+	memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size);
+	seg->buff = buff;
+	seg->alloc_size = max_bytes;
+	return 0;
+}
+
+static int _alloc_set_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem, unsigned add_bytes)
+{
+	unsigned total_bytes = add_bytes;
+
+	for (; nelem; --nelem, ++oa)
+		total_bytes += _osd_req_alist_elem_size(or, oa->len);
+
+	OSD_DEBUG("total_bytes=%d\n", total_bytes);
+	return _osd_realloc_seg(or, &or->set_attr, total_bytes);
+}
+
+static int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes)
+{
+	OSD_DEBUG("total_bytes=%d\n", max_bytes);
+	return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes);
+}
+
+static int _alloc_get_attr_list(struct osd_request *or)
+{
+	OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes);
+	return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes);
+}
+
 /*
  * Common to all OSD commands
  */
@@ -284,6 +391,409 @@ void osd_req_read(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_read);
 
+void osd_req_get_attributes(struct osd_request *or,
+	const struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_get_attributes);
+
+void osd_req_set_attributes(struct osd_request *or,
+	const struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_set_attributes);
+
+/*
+ * Attributes List-mode
+ */
+
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem)
+{
+	unsigned total_bytes = or->set_attr.total_bytes;
+	void *attr_last;
+	int ret;
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+	if (!total_bytes) { /* first-time: allocate and put list header */
+		total_bytes = _osd_req_sizeof_alist_header(or);
+		ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+		if (ret)
+			return ret;
+		_osd_req_set_alist_type(or, or->set_attr.buff,
+					OSD_ATTR_LIST_SET_RETRIEVE);
+	}
+	attr_last = or->set_attr.buff + total_bytes;
+
+	for (; nelem; --nelem) {
+		struct osd_attributes_list_element *attr;
+		unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
+
+		total_bytes += elem_size;
+		if (unlikely(or->set_attr.alloc_size < total_bytes)) {
+			or->set_attr.total_bytes = total_bytes - elem_size;
+			ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+			if (ret)
+				return ret;
+			attr_last =
+				or->set_attr.buff + or->set_attr.total_bytes;
+		}
+
+		attr = attr_last;
+		attr->page = cpu_to_be32(oa->page);
+		attr->attr_id = cpu_to_be32(oa->attr_id);
+		attr->attr_bytes = cpu_to_be16(oa->len);
+		memcpy(attr->attr_val, oa->val_ptr, oa->len);
+
+		attr_last += elem_size;
+		++oa;
+	}
+
+	or->set_attr.total_bytes = total_bytes;
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_set_attr_list);
+
+static int _append_map_kern(struct request *req,
+	void *buff, unsigned len, gfp_t flags)
+{
+	struct bio *bio;
+	int ret;
+
+	bio = bio_map_kern(req->q, buff, len, flags);
+	if (IS_ERR(bio)) {
+		OSD_ERR("Failed bio_map_kern(%p, %d) => %ld\n", buff, len,
+			PTR_ERR(bio));
+		return PTR_ERR(bio);
+	}
+	ret = blk_rq_append_bio(req->q, req, bio);
+	if (ret) {
+		OSD_ERR("Failed blk_rq_append_bio(%p) => %d\n", bio, ret);
+		bio_put(bio);
+	}
+	return ret;
+}
+
+static int _req_append_segment(struct osd_request *or,
+	int padding, struct _osd_req_data_segment *seg,
+	struct _osd_req_data_segment *last_seg, struct _osd_io_info *io)
+{
+	void *pad_buff;
+	int ret;
+
+	if (padding) {
+		/* check if we can just add it to last buffer */
+		if (last_seg &&
+		    (padding <= last_seg->alloc_size - last_seg->total_bytes))
+			pad_buff = last_seg->buff + last_seg->total_bytes;
+		else
+			pad_buff = io->pad_buff;
+
+		ret = _append_map_kern(io->req, pad_buff, padding,
+				       or->alloc_flags);
+		if (ret)
+			return ret;
+		io->total_bytes += padding;
+	}
+
+	ret = _append_map_kern(io->req, seg->buff, seg->total_bytes,
+			       or->alloc_flags);
+	if (ret)
+		return ret;
+
+	io->total_bytes += seg->total_bytes;
+	OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff,
+		  seg->total_bytes);
+	return 0;
+}
+
+static int _osd_req_finalize_set_attr_list(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	int padding;
+	int ret;
+
+	if (!or->set_attr.total_bytes) {
+		cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED;
+		return 0;
+	}
+
+	cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes);
+	cdbh->attrs_list.set_attr_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &padding);
+
+	ret = _req_append_segment(or, padding, &or->set_attr,
+				  or->out.last_seg, &or->out);
+	if (ret)
+		return ret;
+
+	or->out.last_seg = &or->set_attr;
+	return 0;
+}
+
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem)
+{
+	unsigned total_bytes = or->enc_get_attr.total_bytes;
+	void *attr_last;
+	int ret;
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+	/* first time calc data-in list header size */
+	if (!or->get_attr.total_bytes)
+		or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or);
+
+	/* calc data-out info */
+	if (!total_bytes) { /* first-time: allocate and put list header */
+		unsigned max_bytes;
+
+		total_bytes = _osd_req_sizeof_alist_header(or);
+		max_bytes = total_bytes +
+			nelem * sizeof(struct osd_attributes_list_attrid);
+		ret = _alloc_get_attr_desc(or, max_bytes);
+		if (ret)
+			return ret;
+
+		_osd_req_set_alist_type(or, or->enc_get_attr.buff,
+					OSD_ATTR_LIST_GET);
+	}
+	attr_last = or->enc_get_attr.buff + total_bytes;
+
+	for (; nelem; --nelem) {
+		struct osd_attributes_list_attrid *attrid;
+		const unsigned cur_size = sizeof(*attrid);
+
+		total_bytes += cur_size;
+		if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) {
+			or->enc_get_attr.total_bytes = total_bytes - cur_size;
+			ret = _alloc_get_attr_desc(or,
+					total_bytes + nelem * sizeof(*attrid));
+			if (ret)
+				return ret;
+			attr_last = or->enc_get_attr.buff +
+				or->enc_get_attr.total_bytes;
+		}
+
+		attrid = attr_last;
+		attrid->page = cpu_to_be32(oa->page);
+		attrid->attr_id = cpu_to_be32(oa->attr_id);
+
+		attr_last += cur_size;
+
+		/* calc data-in size */
+		or->get_attr.total_bytes +=
+			_osd_req_alist_elem_size(or, oa->len);
+		++oa;
+	}
+
+	or->enc_get_attr.total_bytes = total_bytes;
+
+	OSD_DEBUG(
+	       "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n",
+	       or->get_attr.total_bytes,
+	       or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or),
+	       or->enc_get_attr.total_bytes,
+	       (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or))
+			/ sizeof(struct osd_attributes_list_attrid));
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_list);
+
+static int _osd_req_finalize_get_attr_list(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	unsigned out_padding;
+	unsigned in_padding;
+	int ret;
+
+	if (!or->enc_get_attr.total_bytes) {
+		cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED;
+		cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED;
+		return 0;
+	}
+
+	ret = _alloc_get_attr_list(or);
+	if (ret)
+		return ret;
+
+	/* The out-going buffer info update */
+	OSD_DEBUG("out-going\n");
+	cdbh->attrs_list.get_attr_desc_bytes =
+		cpu_to_be32(or->enc_get_attr.total_bytes);
+
+	cdbh->attrs_list.get_attr_desc_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+	ret = _req_append_segment(or, out_padding, &or->enc_get_attr,
+				  or->out.last_seg, &or->out);
+	if (ret)
+		return ret;
+	or->out.last_seg = &or->enc_get_attr;
+
+	/* The incoming buffer info update */
+	OSD_DEBUG("in-coming\n");
+	cdbh->attrs_list.get_attr_alloc_length =
+		cpu_to_be32(or->get_attr.total_bytes);
+
+	cdbh->attrs_list.get_attr_offset =
+		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+				  &or->in);
+	if (ret)
+		return ret;
+	or->in.last_seg = &or->get_attr;
+
+	return 0;
+}
+
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *oa, int *nelem, void **iterator)
+{
+	unsigned cur_bytes, returned_bytes, n;
+	const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or);
+	void *cur_p;
+
+	if (!_osd_req_is_alist_type(or, or->get_attr.buff,
+				    OSD_ATTR_LIST_SET_RETRIEVE)) {
+		oa->page = 0;
+		oa->attr_id = 0;
+		oa->val_ptr = NULL;
+		oa->len = 0;
+		*iterator = NULL;
+		return 0;
+	}
+
+	if (*iterator) {
+		BUG_ON((*iterator < or->get_attr.buff) ||
+		     (or->get_attr.buff + or->get_attr.alloc_size < *iterator));
+		cur_p = *iterator;
+		cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list;
+		returned_bytes = or->get_attr.total_bytes;
+	} else { /* first time decode the list header */
+		cur_bytes = sizeof_attr_list;
+		returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) +
+					sizeof_attr_list;
+
+		cur_p = or->get_attr.buff + sizeof_attr_list;
+
+		if (returned_bytes > or->get_attr.alloc_size) {
+			OSD_DEBUG("target report: space was not big enough! "
+				  "Allocate=%u Needed=%u\n",
+				  or->get_attr.alloc_size,
+				  returned_bytes + sizeof_attr_list);
+
+			returned_bytes =
+				or->get_attr.alloc_size - sizeof_attr_list;
+		}
+		or->get_attr.total_bytes = returned_bytes;
+	}
+
+	for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
+		struct osd_attributes_list_element *attr = cur_p;
+		unsigned inc;
+
+		oa->len = be16_to_cpu(attr->attr_bytes);
+		inc = _osd_req_alist_elem_size(or, oa->len);
+		OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n",
+			  oa->len, inc, cur_bytes);
+		cur_bytes += inc;
+		if (cur_bytes > returned_bytes) {
+			OSD_ERR("BAD FOOD from target. list not valid!"
+				"c=%d r=%d n=%d\n",
+				cur_bytes, returned_bytes, n);
+			oa->val_ptr = NULL;
+			break;
+		}
+
+		oa->page = be32_to_cpu(attr->page);
+		oa->attr_id = be32_to_cpu(attr->attr_id);
+		oa->val_ptr = attr->attr_val;
+
+		cur_p += inc;
+		++oa;
+	}
+
+	*iterator = (returned_bytes - cur_bytes) ? cur_p : NULL;
+	*nelem = n;
+	return returned_bytes - cur_bytes;
+}
+EXPORT_SYMBOL(osd_req_decode_get_attr_list);
+
+/*
+ * Attributes Page-mode
+ */
+
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attar_page, unsigned max_page_len,
+	const struct osd_attr *set_one_attr)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE;
+
+	or->get_attr.buff = attar_page;
+	or->get_attr.total_bytes = max_page_len;
+
+	or->set_attr.buff = set_one_attr->val_ptr;
+	or->set_attr.total_bytes = set_one_attr->len;
+
+	cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id);
+	cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len);
+	/* ocdb->attrs_page.get_attr_offset; */
+
+	cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->page);
+	cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id);
+	cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len);
+	/* ocdb->attrs_page.set_attr_offset; */
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_page);
+
+static int _osd_req_finalize_attr_page(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	int in_padding, out_padding;
+	int ret;
+
+	/* returned page */
+	cdbh->attrs_page.get_attr_offset =
+		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+				  &or->in);
+	if (ret)
+		return ret;
+
+	/* set one value */
+	cdbh->attrs_page.set_attr_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+	ret = _req_append_segment(or, out_padding, &or->enc_get_attr, NULL,
+				  &or->out);
+	return ret;
+}
+
 /*
  * osd_finalize_request and helpers
  */
@@ -378,9 +888,31 @@ int osd_finalize_request(struct osd_request *or,
 			_LLU(or->in.total_bytes), or->in.req->data_len);
 	}
 
+	or->out.pad_buff = sg_out_pad_buffer;
+	or->in.pad_buff = sg_in_pad_buffer;
+
 	if (!or->attributes_mode)
 		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
 	cdbh->command_specific_options |= or->attributes_mode;
+	if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+		ret = _osd_req_finalize_attr_page(or);
+	} else {
+		/* TODO: I think that for the GET_ATTR command these 2 should
+		 * be reversed to keep them in execution order (for embeded
+		 * targets with low memory footprint)
+		 */
+		ret = _osd_req_finalize_set_attr_list(or);
+		if (ret) {
+			OSD_DEBUG("_osd_req_finalize_set_attr_list failed\n");
+			return ret;
+		}
+
+		ret = _osd_req_finalize_get_attr_list(or);
+		if (ret) {
+			OSD_DEBUG("_osd_req_finalize_get_attr_list failed\n");
+			return ret;
+		}
+	}
 
 	or->request->cmd = or->cdb.buff;
 	or->request->cmd_len = _osd_req_cdb_len(or);
@@ -446,3 +978,45 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 {
 	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
 }
+
+/*
+ * Declared in osd_protocol.h
+ * 4.12.5 Data-In and Data-Out buffer offsets
+ * byte offset = mantissa * (2^(exponent+8))
+ * Returns the smallest allowed encoded offset that contains given @offset
+ * The actual encoded offset returned is @offset + *@padding.
+ */
+osd_cdb_offset __osd_encode_offset(
+	u64 offset, unsigned *padding, int min_shift, int max_shift)
+{
+	u64 try_offset = -1, mod, align;
+	osd_cdb_offset be32_offset;
+	int shift;
+
+	*padding = 0;
+	if (!offset)
+		return 0;
+
+	for (shift = min_shift; shift < max_shift; ++shift) {
+		try_offset = offset >> shift;
+		if (try_offset < (1 << OSD_OFFSET_MAX_BITS))
+			break;
+	}
+
+	BUG_ON(shift == max_shift);
+
+	align = 1 << shift;
+	mod = offset & (align - 1);
+	if (mod) {
+		*padding = align - mod;
+		try_offset += 1;
+	}
+
+	try_offset |= ((shift - 8) & 0xf) << 28;
+	be32_offset = cpu_to_be32((u32)try_offset);
+
+	OSD_DEBUG("offset=%llu mantissa=%llu exp=%d encoded=%x pad=%d\n",
+		 _LLU(offset), _LLU(try_offset & 0x0FFFFFFF), shift,
+		 be32_offset, *padding);
+	return be32_offset;
+}
diff --git a/include/scsi/osd_attributes.h b/include/scsi/osd_attributes.h
new file mode 100644
index 0000000..c53f49b
--- /dev/null
+++ b/include/scsi/osd_attributes.h
@@ -0,0 +1,327 @@
+#ifndef __OSD_ATTRIBUTES_H__
+#define __OSD_ATTRIBUTES_H__
+
+#include "osd_protocol.h"
+
+/*
+ * Contains types and constants that define attribute pages and attribute
+ * numbers and their data types.
+ */
+
+#define ATTR_SET(pg, id, l, ptr) \
+	{ .page = pg, .attr_id = id, .len = l, .val_ptr = ptr }
+
+#define ATTR_DEF(pg, id, l) ATTR_SET(pg, id, l, NULL)
+
+/* osd-r10 4.7.3 Attributes pages */
+enum {
+	OSD_APAGE_OBJECT_FIRST		= 0x0,
+	OSD_APAGE_OBJECT_DIRECTORY	= 0,
+	OSD_APAGE_OBJECT_INFORMATION	= 1,
+	OSD_APAGE_OBJECT_QUOTAS		= 2,
+	OSD_APAGE_OBJECT_TIMESTAMP	= 3,
+	OSD_APAGE_OBJECT_COLLECTIONS	= 4,
+	OSD_APAGE_OBJECT_SECURITY	= 5,
+	OSD_APAGE_OBJECT_LAST		= 0x2fffffff,
+
+	OSD_APAGE_PARTITION_FIRST	= 0x30000000,
+	OSD_APAGE_PARTITION_DIRECTORY	= OSD_APAGE_PARTITION_FIRST + 0,
+	OSD_APAGE_PARTITION_INFORMATION = OSD_APAGE_PARTITION_FIRST + 1,
+	OSD_APAGE_PARTITION_QUOTAS	= OSD_APAGE_PARTITION_FIRST + 2,
+	OSD_APAGE_PARTITION_TIMESTAMP	= OSD_APAGE_PARTITION_FIRST + 3,
+	OSD_APAGE_PARTITION_SECURITY	= OSD_APAGE_PARTITION_FIRST + 5,
+	OSD_APAGE_PARTITION_LAST	= 0x5FFFFFFF,
+
+	OSD_APAGE_COLLECTION_FIRST	= 0x60000000,
+	OSD_APAGE_COLLECTION_DIRECTORY	= OSD_APAGE_COLLECTION_FIRST + 0,
+	OSD_APAGE_COLLECTION_INFORMATION = OSD_APAGE_COLLECTION_FIRST + 1,
+	OSD_APAGE_COLLECTION_TIMESTAMP	= OSD_APAGE_COLLECTION_FIRST + 3,
+	OSD_APAGE_COLLECTION_SECURITY	= OSD_APAGE_COLLECTION_FIRST + 5,
+	OSD_APAGE_COLLECTION_LAST	= 0x8FFFFFFF,
+
+	OSD_APAGE_ROOT_FIRST		= 0x90000000,
+	OSD_APAGE_ROOT_DIRECTORY	= OSD_APAGE_ROOT_FIRST + 0,
+	OSD_APAGE_ROOT_INFORMATION	= OSD_APAGE_ROOT_FIRST + 1,
+	OSD_APAGE_ROOT_QUOTAS		= OSD_APAGE_ROOT_FIRST + 2,
+	OSD_APAGE_ROOT_TIMESTAMP	= OSD_APAGE_ROOT_FIRST + 3,
+	OSD_APAGE_ROOT_SECURITY		= OSD_APAGE_ROOT_FIRST + 5,
+	OSD_APAGE_ROOT_LAST		= 0xBFFFFFFF,
+
+	OSD_APAGE_RESERVED_TYPE_FIRST	= 0xC0000000,
+	OSD_APAGE_RESERVED_TYPE_LAST	= 0xEFFFFFFF,
+
+	OSD_APAGE_COMMON_FIRST		= 0xF0000000,
+	OSD_APAGE_COMMON_LAST		= 0xFFFFFFFE,
+
+	OSD_APAGE_REQUEST_ALL		= 0xFFFFFFFF,
+};
+
+/* subcategories of attr pages within each range above */
+enum {
+	OSD_APAGE_STD_FIRST		= 0x0,
+	OSD_APAGE_STD_DIRECTORY		= 0,
+	OSD_APAGE_STD_INFORMATION	= 1,
+	OSD_APAGE_STD_QUOTAS		= 2,
+	OSD_APAGE_STD_TIMESTAMP		= 3,
+	OSD_APAGE_STD_COLLECTIONS	= 4,
+	OSD_APAGE_STD_POLICY_SECURITY	= 5,
+	OSD_APAGE_STD_LAST		= 0x0000007F,
+
+	OSD_APAGE_RESERVED_FIRST	= 0x00000080,
+	OSD_APAGE_RESERVED_LAST		= 0x00007FFF,
+
+	OSD_APAGE_OTHER_STD_FIRST	= 0x00008000,
+	OSD_APAGE_OTHER_STD_LAST	= 0x0000EFFF,
+
+	OSD_APAGE_PUBLIC_FIRST		= 0x0000F000,
+	OSD_APAGE_PUBLIC_LAST		= 0x0000FFFF,
+
+	OSD_APAGE_APP_DEFINED_FIRST	= 0x00010000,
+	OSD_APAGE_APP_DEFINED_LAST	= 0x1FFFFFFF,
+
+	OSD_APAGE_VENDOR_SPECIFIC_FIRST	= 0x20000000,
+	OSD_APAGE_VENDOR_SPECIFIC_LAST	= 0x2FFFFFFF,
+};
+
+enum {
+	OSD_ATTR_PAGE_IDENTIFICATION = 0, /* in all pages 40 bytes */
+};
+
+struct page_identification {
+	u8 vendor_identification[8];
+	u8 page_identification[32];
+}  __packed;
+
+struct osd_attr_page_header {
+	__be32 page_number;
+	__be32 page_length;
+} __packed;
+
+/* 7.1.2.8 Root Information attributes page (OSD_APAGE_ROOT_INFORMATION) */
+enum {
+	OSD_ATTR_RI_OSD_SYSTEM_ID            = 0x3,   /* 20       */
+	OSD_ATTR_RI_VENDOR_IDENTIFICATION    = 0x4,   /* 8        */
+	OSD_ATTR_RI_PRODUCT_IDENTIFICATION   = 0x5,   /* 16       */
+	OSD_ATTR_RI_PRODUCT_MODEL            = 0x6,   /* 32       */
+	OSD_ATTR_RI_PRODUCT_REVISION_LEVEL   = 0x7,   /* 4        */
+	OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER    = 0x8,   /* variable */
+	OSD_ATTR_RI_OSD_NAME                 = 0x9,   /* variable */
+	OSD_ATTR_RI_TOTAL_CAPACITY           = 0x80,  /* 8        */
+	OSD_ATTR_RI_USED_CAPACITY            = 0x81,  /* 8        */
+	OSD_ATTR_RI_NUMBER_OF_PARTITIONS     = 0xC0,  /* 8        */
+	OSD_ATTR_RI_CLOCK                    = 0x100, /* 6        */
+};
+/* Root_Information_attributes_page does not have a get_page structure */
+
+/* 7.1.2.9 Partition Information attributes page
+ * (OSD_APAGE_PARTITION_INFORMATION)
+ */
+enum {
+	OSD_ATTR_PI_PARTITION_ID            = 0x1,     /* 8        */
+	OSD_ATTR_PI_USERNAME                = 0x9,     /* variable */
+	OSD_ATTR_PI_USED_CAPACITY           = 0x81,    /* 8        */
+	OSD_ATTR_PI_NUMBER_OF_OBJECTS       = 0xC1,    /* 8        */
+};
+/* Partition Information attributes page does not have a get_page structure */
+
+/* 7.1.2.10 Collection Information attributes page
+ * (OSD_APAGE_COLLECTION_INFORMATION)
+ */
+enum {
+	OSD_ATTR_CI_PARTITION_ID           = 0x1,       /* 8        */
+	OSD_ATTR_CI_COLLECTION_OBJECT_ID   = 0x2,       /* 8        */
+	OSD_ATTR_CI_USERNAME               = 0x9,       /* variable */
+	OSD_ATTR_CI_USED_CAPACITY          = 0x81,      /* 8        */
+};
+/* Collection Information attributes page does not have a get_page structure */
+
+/* 7.1.2.11 User Object Information attributes page
+ * (OSD_APAGE_OBJECT_INFORMATION)
+ */
+enum {
+	OSD_ATTR_OI_PARTITION_ID         = 0x1,       /* 8        */
+	OSD_ATTR_OI_OBJECT_ID            = 0x2,       /* 8        */
+	OSD_ATTR_OI_USERNAME             = 0x9,       /* variable */
+	OSD_ATTR_OI_USED_CAPACITY        = 0x81,      /* 8        */
+	OSD_ATTR_OI_LOGICAL_LENGTH       = 0x82,      /* 8        */
+};
+/* Object Information attributes page does not have a get_page structure */
+
+/* 7.1.2.12 Root Quotas attributes page (OSD_APAGE_ROOT_QUOTAS) */
+enum {
+	OSD_ATTR_RQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH     = 0x1,      /* 8  */
+	OSD_ATTR_RQ_PARTITION_CAPACITY_QUOTA               = 0x10001,  /* 8  */
+	OSD_ATTR_RQ_PARTITION_OBJECT_COUNT                 = 0x10002,  /* 8  */
+	OSD_ATTR_RQ_PARTITION_COLLECTIONS_PER_USER_OBJECT  = 0x10081,  /* 4  */
+	OSD_ATTR_RQ_PARTITION_COUNT                        = 0x20002,  /* 8  */
+};
+
+struct Root_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+2, size=0x24 */
+	__be64 default_maximum_user_object_length;
+	__be64 partition_capacity_quota;
+	__be64 partition_object_count;
+	__be64 partition_collections_per_user_object;
+	__be64 partition_count;
+}  __packed;
+
+/* 7.1.2.13 Partition Quotas attributes page (OSD_APAGE_PARTITION_QUOTAS)*/
+enum {
+	OSD_ATTR_PQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH  = 0x1,        /* 8 */
+	OSD_ATTR_PQ_CAPACITY_QUOTA                      = 0x10001,    /* 8 */
+	OSD_ATTR_PQ_OBJECT_COUNT                        = 0x10002,    /* 8 */
+	OSD_ATTR_PQ_COLLECTIONS_PER_USER_OBJECT         = 0x10081,    /* 4 */
+};
+
+struct Partition_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=P+2, size=0x1C */
+	__be64 default_maximum_user_object_length;
+	__be64 capacity_quota;
+	__be64 object_count;
+	__be64 collections_per_user_object;
+}  __packed;
+
+/* 7.1.2.14 User Object Quotas attributes page (OSD_APAGE_OBJECT_QUOTAS) */
+enum {
+	OSD_ATTR_OQ_MAXIMUM_LENGTH  = 0x1,        /* 8 */
+};
+
+struct Object_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=U+2, size=0x8 */
+	__be64 maximum_length;
+}  __packed;
+
+/* 7.1.2.15 Root Timestamps attributes page (OSD_APAGE_ROOT_TIMESTAMP) */
+enum {
+	OSD_ATTR_RT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_RT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_RT_TIMESTAMP_BYPASS          = 0xFFFFFFFE, /* 1 */
+};
+
+struct root_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+3, size=0xD */
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	u8 timestamp_bypass;
+}  __packed;
+
+/* 7.1.2.16 Partition Timestamps attributes page
+ * (OSD_APAGE_PARTITION_TIMESTAMP)
+ */
+enum {
+	OSD_ATTR_PT_CREATED_TIME              = 0x1,        /* 6 */
+	OSD_ATTR_PT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_PT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_PT_DATA_ACCESSED_TIME        = 0x4,        /* 6 */
+	OSD_ATTR_PT_DATA_MODIFIED_TIME        = 0x5,        /* 6 */
+	OSD_ATTR_PT_TIMESTAMP_BYPASS          = 0xFFFFFFFE, /* 1 */
+};
+
+struct partition_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=P+3, size=0x1F */
+	struct osd_timestamp created_time;
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	struct osd_timestamp data_accessed_time;
+	struct osd_timestamp data_modified_time;
+	u8 timestamp_bypass;
+}  __packed;
+
+/* 7.1.2.17/18 Collection/Object Timestamps attributes page
+ * (OSD_APAGE_COLLECTION_TIMESTAMP/OSD_APAGE_OBJECT_TIMESTAMP)
+ */
+enum {
+	OSD_ATTR_OT_CREATED_TIME              = 0x1,        /* 6 */
+	OSD_ATTR_OT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_OT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_OT_DATA_ACCESSED_TIME        = 0x4,        /* 6 */
+	OSD_ATTR_OT_DATA_MODIFIED_TIME        = 0x5,        /* 6 */
+};
+
+/* same for collection */
+struct object_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=C+3/3, size=0x1E */
+	struct osd_timestamp created_time;
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	struct osd_timestamp data_accessed_time;
+	struct osd_timestamp data_modified_time;
+}  __packed;
+
+/* 7.1.2.19 Collections attributes page */
+/* TBD */
+
+/* 7.1.2.20 Root Policy/Security attributes page (OSD_APAGE_ROOT_SECURITY) */
+enum {
+	OSD_ATTR_RS_DEFAULT_SECURITY_METHOD           = 0x1,       /* 1      */
+	OSD_ATTR_RS_OLDEST_VALID_NONCE_LIMIT          = 0x2,       /* 6      */
+	OSD_ATTR_RS_NEWEST_VALID_NONCE_LIMIT          = 0x3,       /* 6      */
+	OSD_ATTR_RS_PARTITION_DEFAULT_SECURITY_METHOD = 0x6,       /* 1      */
+	OSD_ATTR_RS_SUPPORTED_SECURITY_METHODS        = 0x7,       /* 2      */
+	OSD_ATTR_RS_ADJUSTABLE_CLOCK                  = 0x9,       /* 6      */
+	OSD_ATTR_RS_MASTER_KEY_IDENTIFIER             = 0x7FFD,    /* 0 or 7 */
+	OSD_ATTR_RS_ROOT_KEY_IDENTIFIER               = 0x7FFE,    /* 0 or 7 */
+	OSD_ATTR_RS_SUPPORTED_INTEGRITY_ALGORITHM_0   = 0x80000000,/* 1,(x16)*/
+	OSD_ATTR_RS_SUPPORTED_DH_GROUP_0              = 0x80000010,/* 1,(x16)*/
+};
+
+struct root_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+5, size=0x3F */
+	u8 default_security_method;
+	u8 partition_default_security_method;
+	__be16 supported_security_methods;
+	u8 mki_valid_rki_valid;
+	struct osd_timestamp oldest_valid_nonce_limit;
+	struct osd_timestamp newest_valid_nonce_limit;
+	struct osd_timestamp adjustable_clock;
+	u8 master_key_identifier[32-25];
+	u8 root_key_identifier[39-32];
+	u8 supported_integrity_algorithm[16];
+	u8 supported_dh_group[16];
+}  __packed;
+
+/* 7.1.2.21 Partition Policy/Security attributes page
+ * (OSD_APAGE_PARTITION_SECURITY)
+ */
+enum {
+	OSD_ATTR_PS_DEFAULT_SECURITY_METHOD        = 0x1,        /* 1      */
+	OSD_ATTR_PS_OLDEST_VALID_NONCE             = 0x2,        /* 6      */
+	OSD_ATTR_PS_NEWEST_VALID_NONCE             = 0x3,        /* 6      */
+	OSD_ATTR_PS_REQUEST_NONCE_LIST_DEPTH       = 0x4,        /* 2      */
+	OSD_ATTR_PS_FROZEN_WORKING_KEY_BIT_MASK    = 0x5,        /* 2      */
+	OSD_ATTR_PS_PARTITION_KEY_IDENTIFIER       = 0x7FFF,     /* 0 or 7 */
+	OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_FIRST   = 0x8000,     /* 0 or 7 */
+	OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_LAST    = 0x800F,     /* 0 or 7 */
+	OSD_ATTR_PS_POLICY_ACCESS_TAG              = 0x40000001, /* 4      */
+	OSD_ATTR_PS_USER_OBJECT_POLICY_ACCESS_TAG  = 0x40000002, /* 4      */
+};
+
+struct partition_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=p+5, size=0x8f */
+	u8 reserved[3];
+	u8 default_security_method;
+	struct osd_timestamp oldest_valid_nonce;
+	struct osd_timestamp newest_valid_nonce;
+	__be16 request_nonce_list_depth;
+	__be16 frozen_working_key_bit_mask;
+	__be32 policy_access_tag;
+	__be32 user_object_policy_access_tag;
+	u8 pki_valid;
+	__be16 wki_00_0f_vld;
+	struct osd_key_identifier partition_key_identifier;
+	struct osd_key_identifier working_key_identifiers[16];
+}  __packed;
+
+/* 7.1.2.22/23 Collection/Object Policy-Security attributes page
+ * (OSD_APAGE_COLLECTION_SECURITY/OSD_APAGE_OBJECT_SECURITY)
+ */
+enum {
+	OSD_ATTR_OS_POLICY_ACCESS_TAG              = 0x40000001, /* 4      */
+};
+
+struct object_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=C+5/5, size=4 */
+	__be32 policy_access_tag;
+}  __packed;
+
+#endif /*ndef __OSD_ATTRIBUTES_H__*/
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 09/18] osd_ktests: Test Attribute lists
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 12:57     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:57 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Add tests for setting/getting Attribute lists. All combinations
of read/write with set/get attributes are tested.
(6 possibilities), So all but data integrity request structure
layouts are attempted.

This test passes against the IBM-OSD-SIM OSDv1 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_ktests.c |  110 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
index fba4934..d098323 100644
--- a/drivers/scsi/osd/osd_ktests.c
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -43,6 +43,7 @@
 
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
+#include <scsi/osd_attributes.h>
 
 #include "osd_ktests.h"
 #include "osd_debug.h"
@@ -260,6 +261,91 @@ int ktest_remove_par(struct osd_dev *osd_dev)
 	return 0;
 }
 
+int ktest_write_read_attr(struct osd_dev *osd_dev, void *buff,
+	bool doread, bool doset, bool doget)
+{
+	struct request_queue *req_q = osd_dev->scsi_device->request_queue;
+	struct osd_request *or;
+	char g_caps[OSD_CAP_LEN];
+	int ret;
+	struct bio *bio;
+	char *domsg;
+	/* set attrs */
+	static char name[] = "ktest_write_read_attr";
+	__be64 max_len = cpu_to_be64(0x80000000L);
+	struct osd_obj_id obj = {
+		.partition = first_par_id,
+		.id = first_obj_id,
+	};
+	struct osd_attr set_attrs[] = {
+		ATTR_SET(OSD_APAGE_OBJECT_QUOTAS, OSD_ATTR_OQ_MAXIMUM_LENGTH,
+			sizeof(max_len), &max_len),
+		ATTR_SET(OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_USERNAME,
+			sizeof(name), name),
+	};
+	struct osd_attr get_attrs[] = {
+		ATTR_DEF(OSD_APAGE_OBJECT_INFORMATION,
+			OSD_ATTR_OI_USED_CAPACITY, sizeof(__be64)),
+		ATTR_DEF(OSD_APAGE_OBJECT_INFORMATION,
+			OSD_ATTR_OI_LOGICAL_LENGTH, sizeof(__be64)),
+	};
+
+	KTEST_START_REQ(osd_dev, or);
+	bio = bio_map_kern(req_q, buff, BUFF_SIZE, GFP_KERNEL);
+	if (!bio) {
+		OSD_ERR("!!! Failed to allocate BIO\n");
+		return -ENOMEM;
+	}
+
+	if (doread) {
+		osd_req_read(or, &obj, bio, 0);
+		domsg = "Read-with-attr";
+	} else {
+		osd_req_write(or, &obj, bio, 0);
+		domsg = "Write-with-attr";
+	}
+
+	if (doset)
+		osd_req_add_set_attr_list(or, set_attrs, 2);
+	if (doget)
+		osd_req_add_get_attr_list(or, get_attrs, 2);
+
+/*	KTEST_EXEC_END(or, &obj, "");*/
+	ret = test_exec(or, g_caps, &obj);
+	if (!ret && doget) {
+		void *iter = NULL, *pFirst, *pSec;
+		int nelem = 2;
+		u64 capacity_len = ~0;
+		u64 logical_len = ~0;
+
+		osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+		/*FIXME: Std does not guaranty order of return attrs */
+		pFirst = get_attrs[0].val_ptr;
+		if (pFirst)
+			capacity_len = get_unaligned_be64(pFirst);
+		else
+			OSD_ERR("failed to read capacity_used\n");
+		pSec = get_attrs[1].val_ptr;
+		if (pSec)
+			logical_len = get_unaligned_be64(pSec);
+		else
+			OSD_ERR("failed to read logical_length\n");
+		OSD_INFO("%s capacity=%llu len=%llu\n",
+			domsg, _LLU(capacity_len), _LLU(logical_len));
+	}
+
+	osd_end_request(or);
+	if (ret) {
+		OSD_ERR("!!! Error executing %s => %d doset=%d doget=%d\n",
+			domsg, ret, doset, doget);
+		return ret;
+	}
+	OSD_DEBUG("%s\n", domsg);
+
+	return 0;
+}
+
 int do_test_17(struct osd_dev *od)
 {
 	void *write_buff = NULL;
@@ -304,11 +390,35 @@ int do_test_17(struct osd_dev *od)
 /* List all objects */
 
 /* Write with get_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, false, true);
+	if (ret)
+		goto dev_fini;
+
 /* Write with set_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, true, false);
+	if (ret)
+		goto dev_fini;
+
 /* Write with set_attr + get_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, true, true);
+	if (ret)
+		goto dev_fini;
+
 /* Read with set_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, true, false);
+	if (ret)
+		goto dev_fini;
+
 /* Read with get_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, false, true);
+	if (ret)
+		goto dev_fini;
+
 /* Read with get_attr + set_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, true, true);
+	if (ret)
+		goto dev_fini;
+
 /* remove objects */
 	ret = ktest_remove_obj(od);
 	if (ret)
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 09/18] osd_ktests: Test Attribute lists
@ 2008-12-22 12:57     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 12:57 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Add tests for setting/getting Attribute lists. All combinations
of read/write with set/get attributes are tested.
(6 possibilities), So all but data integrity request structure
layouts are attempted.

This test passes against the IBM-OSD-SIM OSDv1 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_ktests.c |  110 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
index fba4934..d098323 100644
--- a/drivers/scsi/osd/osd_ktests.c
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -43,6 +43,7 @@
 
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
+#include <scsi/osd_attributes.h>
 
 #include "osd_ktests.h"
 #include "osd_debug.h"
@@ -260,6 +261,91 @@ int ktest_remove_par(struct osd_dev *osd_dev)
 	return 0;
 }
 
+int ktest_write_read_attr(struct osd_dev *osd_dev, void *buff,
+	bool doread, bool doset, bool doget)
+{
+	struct request_queue *req_q = osd_dev->scsi_device->request_queue;
+	struct osd_request *or;
+	char g_caps[OSD_CAP_LEN];
+	int ret;
+	struct bio *bio;
+	char *domsg;
+	/* set attrs */
+	static char name[] = "ktest_write_read_attr";
+	__be64 max_len = cpu_to_be64(0x80000000L);
+	struct osd_obj_id obj = {
+		.partition = first_par_id,
+		.id = first_obj_id,
+	};
+	struct osd_attr set_attrs[] = {
+		ATTR_SET(OSD_APAGE_OBJECT_QUOTAS, OSD_ATTR_OQ_MAXIMUM_LENGTH,
+			sizeof(max_len), &max_len),
+		ATTR_SET(OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_USERNAME,
+			sizeof(name), name),
+	};
+	struct osd_attr get_attrs[] = {
+		ATTR_DEF(OSD_APAGE_OBJECT_INFORMATION,
+			OSD_ATTR_OI_USED_CAPACITY, sizeof(__be64)),
+		ATTR_DEF(OSD_APAGE_OBJECT_INFORMATION,
+			OSD_ATTR_OI_LOGICAL_LENGTH, sizeof(__be64)),
+	};
+
+	KTEST_START_REQ(osd_dev, or);
+	bio = bio_map_kern(req_q, buff, BUFF_SIZE, GFP_KERNEL);
+	if (!bio) {
+		OSD_ERR("!!! Failed to allocate BIO\n");
+		return -ENOMEM;
+	}
+
+	if (doread) {
+		osd_req_read(or, &obj, bio, 0);
+		domsg = "Read-with-attr";
+	} else {
+		osd_req_write(or, &obj, bio, 0);
+		domsg = "Write-with-attr";
+	}
+
+	if (doset)
+		osd_req_add_set_attr_list(or, set_attrs, 2);
+	if (doget)
+		osd_req_add_get_attr_list(or, get_attrs, 2);
+
+/*	KTEST_EXEC_END(or, &obj, "");*/
+	ret = test_exec(or, g_caps, &obj);
+	if (!ret && doget) {
+		void *iter = NULL, *pFirst, *pSec;
+		int nelem = 2;
+		u64 capacity_len = ~0;
+		u64 logical_len = ~0;
+
+		osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+		/*FIXME: Std does not guaranty order of return attrs */
+		pFirst = get_attrs[0].val_ptr;
+		if (pFirst)
+			capacity_len = get_unaligned_be64(pFirst);
+		else
+			OSD_ERR("failed to read capacity_used\n");
+		pSec = get_attrs[1].val_ptr;
+		if (pSec)
+			logical_len = get_unaligned_be64(pSec);
+		else
+			OSD_ERR("failed to read logical_length\n");
+		OSD_INFO("%s capacity=%llu len=%llu\n",
+			domsg, _LLU(capacity_len), _LLU(logical_len));
+	}
+
+	osd_end_request(or);
+	if (ret) {
+		OSD_ERR("!!! Error executing %s => %d doset=%d doget=%d\n",
+			domsg, ret, doset, doget);
+		return ret;
+	}
+	OSD_DEBUG("%s\n", domsg);
+
+	return 0;
+}
+
 int do_test_17(struct osd_dev *od)
 {
 	void *write_buff = NULL;
@@ -304,11 +390,35 @@ int do_test_17(struct osd_dev *od)
 /* List all objects */
 
 /* Write with get_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, false, true);
+	if (ret)
+		goto dev_fini;
+
 /* Write with set_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, true, false);
+	if (ret)
+		goto dev_fini;
+
 /* Write with set_attr + get_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, true, true);
+	if (ret)
+		goto dev_fini;
+
 /* Read with set_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, true, false);
+	if (ret)
+		goto dev_fini;
+
 /* Read with get_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, false, true);
+	if (ret)
+		goto dev_fini;
+
 /* Read with get_attr + set_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, true, true);
+	if (ret)
+		goto dev_fini;
+
 /* remove objects */
 	ret = ktest_remove_obj(od);
 	if (ret)
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 10/18] libosd: OSD Security processing stubs
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 13:00     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:00 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Layout the signing of OSD's CDB and all-data security modes. The actual
code for signing the data and CDB is missing, but the code flow and the extra
buffer segments are all in place.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   85 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 85 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index c760d7a..03f71c5 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -107,6 +107,14 @@ static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
 }
 
+static struct osd_security_parameters *
+_osd_req_sec_params(struct osd_request *or)
+{
+	struct osd_cdb *ocdb = &or->cdb;
+
+	return &ocdb->v1.sec_params;
+}
+
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
 {
 	memset(osdd, 0, sizeof(*osdd));
@@ -794,6 +802,64 @@ static int _osd_req_finalize_attr_page(struct osd_request *or)
 	return ret;
 }
 
+static int _osd_req_finalize_data_integrity(struct osd_request *or,
+	bool has_in, bool has_out, const u8 *cap_key)
+{
+	struct osd_security_parameters *sec_parms = _osd_req_sec_params(or);
+	int ret;
+
+	if (!osd_is_sec_alldata(sec_parms))
+		return 0;
+
+	if (has_out) {
+		struct _osd_req_data_segment seg = {
+			.buff = &or->out_data_integ,
+			.total_bytes = sizeof(or->out_data_integ),
+		};
+		int pad;
+
+		or->out_data_integ.data_bytes = cpu_to_be64(
+			or->out.bio ? or->out.bio->bi_size : 0);
+		or->out_data_integ.set_attributes_bytes = cpu_to_be64(
+			or->set_attr.total_bytes);
+		or->out_data_integ.get_attributes_bytes = cpu_to_be64(
+			or->enc_get_attr.total_bytes);
+
+		sec_parms->data_out_integrity_check_offset =
+			osd_req_encode_offset(or, or->out.total_bytes, &pad);
+
+		ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
+					  &or->out);
+		if (ret)
+			return ret;
+		or->out.last_seg = NULL;
+
+		/* they are now all chained to request sign them all together */
+		osd_sec_sign_data(&or->out_data_integ, or->out.req->bio,
+				  cap_key);
+	}
+
+	if (has_in) {
+		struct _osd_req_data_segment seg = {
+			.buff = &or->in_data_integ,
+			.total_bytes = sizeof(or->in_data_integ),
+		};
+		int pad;
+
+		sec_parms->data_in_integrity_check_offset =
+			osd_req_encode_offset(or, or->in.total_bytes, &pad);
+
+		ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
+					  &or->in);
+		if (ret)
+			return ret;
+
+		or->in.last_seg = NULL;
+	}
+
+	return 0;
+}
+
 /*
  * osd_finalize_request and helpers
  */
@@ -914,6 +980,12 @@ int osd_finalize_request(struct osd_request *or,
 		}
 	}
 
+	ret = _osd_req_finalize_data_integrity(or, has_in, has_out, cap_key);
+	if (ret)
+		return ret;
+
+	osd_sec_sign_cdb(&or->cdb, cap_key);
+
 	or->request->cmd = or->cdb.buff;
 	or->request->cmd_len = _osd_req_cdb_len(or);
 
@@ -979,6 +1051,19 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
 }
 
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms)
+{
+	return false;
+}
+
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key)
+{
+}
+
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key)
+{
+}
+
 /*
  * Declared in osd_protocol.h
  * 4.12.5 Data-In and Data-Out buffer offsets
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 10/18] libosd: OSD Security processing stubs
@ 2008-12-22 13:00     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:00 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Layout the signing of OSD's CDB and all-data security modes. The actual
code for signing the data and CDB is missing, but the code flow and the extra
buffer segments are all in place.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   85 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 85 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index c760d7a..03f71c5 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -107,6 +107,14 @@ static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
 }
 
+static struct osd_security_parameters *
+_osd_req_sec_params(struct osd_request *or)
+{
+	struct osd_cdb *ocdb = &or->cdb;
+
+	return &ocdb->v1.sec_params;
+}
+
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
 {
 	memset(osdd, 0, sizeof(*osdd));
@@ -794,6 +802,64 @@ static int _osd_req_finalize_attr_page(struct osd_request *or)
 	return ret;
 }
 
+static int _osd_req_finalize_data_integrity(struct osd_request *or,
+	bool has_in, bool has_out, const u8 *cap_key)
+{
+	struct osd_security_parameters *sec_parms = _osd_req_sec_params(or);
+	int ret;
+
+	if (!osd_is_sec_alldata(sec_parms))
+		return 0;
+
+	if (has_out) {
+		struct _osd_req_data_segment seg = {
+			.buff = &or->out_data_integ,
+			.total_bytes = sizeof(or->out_data_integ),
+		};
+		int pad;
+
+		or->out_data_integ.data_bytes = cpu_to_be64(
+			or->out.bio ? or->out.bio->bi_size : 0);
+		or->out_data_integ.set_attributes_bytes = cpu_to_be64(
+			or->set_attr.total_bytes);
+		or->out_data_integ.get_attributes_bytes = cpu_to_be64(
+			or->enc_get_attr.total_bytes);
+
+		sec_parms->data_out_integrity_check_offset =
+			osd_req_encode_offset(or, or->out.total_bytes, &pad);
+
+		ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
+					  &or->out);
+		if (ret)
+			return ret;
+		or->out.last_seg = NULL;
+
+		/* they are now all chained to request sign them all together */
+		osd_sec_sign_data(&or->out_data_integ, or->out.req->bio,
+				  cap_key);
+	}
+
+	if (has_in) {
+		struct _osd_req_data_segment seg = {
+			.buff = &or->in_data_integ,
+			.total_bytes = sizeof(or->in_data_integ),
+		};
+		int pad;
+
+		sec_parms->data_in_integrity_check_offset =
+			osd_req_encode_offset(or, or->in.total_bytes, &pad);
+
+		ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
+					  &or->in);
+		if (ret)
+			return ret;
+
+		or->in.last_seg = NULL;
+	}
+
+	return 0;
+}
+
 /*
  * osd_finalize_request and helpers
  */
@@ -914,6 +980,12 @@ int osd_finalize_request(struct osd_request *or,
 		}
 	}
 
+	ret = _osd_req_finalize_data_integrity(or, has_in, has_out, cap_key);
+	if (ret)
+		return ret;
+
+	osd_sec_sign_cdb(&or->cdb, cap_key);
+
 	or->request->cmd = or->cdb.buff;
 	or->request->cmd_len = _osd_req_cdb_len(or);
 
@@ -979,6 +1051,19 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
 }
 
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms)
+{
+	return false;
+}
+
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key)
+{
+}
+
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key)
+{
+}
+
 /*
  * Declared in osd_protocol.h
  * 4.12.5 Data-In and Data-Out buffer offsets
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 11/18] libosd: Add Flush and List-objects support
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 13:02     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:02 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Add support for the various List-objects commands. List-partitions-in-device,
List-collections-in-partition, List-objects-in-partition,
List-objects-in-collection. All these support partial listing and continuation.

Add support for the different Flush commands and options.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  124 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 124 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 03f71c5..91f58fd 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -100,6 +100,16 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
 	}
 }
 
+/* This is for List-objects not Attributes-Lists */
+static void _osd_req_encode_olist(struct osd_request *or,
+	struct osd_obj_id_list *list)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+	cdbh->v1.list_identifier = list->list_identifier;
+	cdbh->v1.start_address = list->continuation_id;
+}
+
 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 	u64 offset, unsigned *padding)
 {
@@ -336,6 +346,29 @@ void osd_req_format(struct osd_request *or, u64 tot_capacity)
 }
 EXPORT_SYMBOL(osd_req_format);
 
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem)
+{
+	return osd_req_list_partition_objects(or, 0, initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_dev_partitions);
+
+static void _osd_req_encode_flush(struct osd_request *or,
+	enum osd_options_flush_scope_values op)
+{
+	struct osd_cdb_head *ocdb = osd_cdb_head(&or->cdb);
+
+	ocdb->command_specific_options = op;
+}
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH_OSD, &osd_root_object, 0, 0);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_obsd);
+
 /*
  * Partition commands
  */
@@ -362,6 +395,88 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition)
 }
 EXPORT_SYMBOL(osd_req_remove_partition);
 
+static int _osd_req_list_objects(struct osd_request *or,
+	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem)
+{
+	struct request_queue *q = or->osd_dev->scsi_device->request_queue;
+	u64 len = nelem * sizeof(osd_id) + sizeof(*list);
+	struct bio *bio;
+
+	_osd_req_encode_common(or, action, obj, (u64)initial_id, len);
+
+	if (list->list_identifier)
+		_osd_req_encode_olist(or, list);
+
+	WARN_ON(or->in.bio);
+	bio = bio_map_kern(q, list, len, or->alloc_flags);
+	if (!bio) {
+		OSD_ERR("!!! Failed to allocate list_objects BIO\n");
+		return -ENOMEM;
+	}
+
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+	return 0;
+}
+
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	return osd_req_list_collection_objects(or, &par, initial_id, list,
+					       nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_collections);
+
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	return _osd_req_list_objects(or, OSD_ACT_LIST, &par, initial_id, list,
+				     nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_objects);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_partition(or, OSD_ACT_FLUSH_PARTITION, partition);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_partition);
+
+/*
+ * Collection commands
+ */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *obj, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem)
+{
+	return _osd_req_list_objects(or, OSD_ACT_LIST_COLLECTION, obj,
+				     initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_collection_objects);
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH_PARTITION, obj, 0, 0);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_collection);
+
 /*
  * Object commands
  */
@@ -388,6 +503,15 @@ void osd_req_write(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_write);
 
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
+	/*V2*/ u64 offset, /*V2*/ u64 len)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_object);
+
 void osd_req_read(struct osd_request *or,
 	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
 {
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 11/18] libosd: Add Flush and List-objects support
@ 2008-12-22 13:02     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:02 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Add support for the various List-objects commands. List-partitions-in-device,
List-collections-in-partition, List-objects-in-partition,
List-objects-in-collection. All these support partial listing and continuation.

Add support for the different Flush commands and options.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  124 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 124 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 03f71c5..91f58fd 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -100,6 +100,16 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
 	}
 }
 
+/* This is for List-objects not Attributes-Lists */
+static void _osd_req_encode_olist(struct osd_request *or,
+	struct osd_obj_id_list *list)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+	cdbh->v1.list_identifier = list->list_identifier;
+	cdbh->v1.start_address = list->continuation_id;
+}
+
 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 	u64 offset, unsigned *padding)
 {
@@ -336,6 +346,29 @@ void osd_req_format(struct osd_request *or, u64 tot_capacity)
 }
 EXPORT_SYMBOL(osd_req_format);
 
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem)
+{
+	return osd_req_list_partition_objects(or, 0, initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_dev_partitions);
+
+static void _osd_req_encode_flush(struct osd_request *or,
+	enum osd_options_flush_scope_values op)
+{
+	struct osd_cdb_head *ocdb = osd_cdb_head(&or->cdb);
+
+	ocdb->command_specific_options = op;
+}
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH_OSD, &osd_root_object, 0, 0);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_obsd);
+
 /*
  * Partition commands
  */
@@ -362,6 +395,88 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition)
 }
 EXPORT_SYMBOL(osd_req_remove_partition);
 
+static int _osd_req_list_objects(struct osd_request *or,
+	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem)
+{
+	struct request_queue *q = or->osd_dev->scsi_device->request_queue;
+	u64 len = nelem * sizeof(osd_id) + sizeof(*list);
+	struct bio *bio;
+
+	_osd_req_encode_common(or, action, obj, (u64)initial_id, len);
+
+	if (list->list_identifier)
+		_osd_req_encode_olist(or, list);
+
+	WARN_ON(or->in.bio);
+	bio = bio_map_kern(q, list, len, or->alloc_flags);
+	if (!bio) {
+		OSD_ERR("!!! Failed to allocate list_objects BIO\n");
+		return -ENOMEM;
+	}
+
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+	return 0;
+}
+
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	return osd_req_list_collection_objects(or, &par, initial_id, list,
+					       nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_collections);
+
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	return _osd_req_list_objects(or, OSD_ACT_LIST, &par, initial_id, list,
+				     nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_objects);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_partition(or, OSD_ACT_FLUSH_PARTITION, partition);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_partition);
+
+/*
+ * Collection commands
+ */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *obj, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem)
+{
+	return _osd_req_list_objects(or, OSD_ACT_LIST_COLLECTION, obj,
+				     initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_collection_objects);
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH_PARTITION, obj, 0, 0);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_collection);
+
 /*
  * Object commands
  */
@@ -388,6 +503,15 @@ void osd_req_write(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_write);
 
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
+	/*V2*/ u64 offset, /*V2*/ u64 len)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_object);
+
 void osd_req_read(struct osd_request *or,
 	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
 {
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 12/18] libosd: Not implemented commands
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 13:04     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:04 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Some commands declared in header are not yet implemented. Put them
as stubs in .c file, just so they take their place in the file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   35 +++++++++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 91f58fd..d3cc7ed 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -339,6 +339,9 @@ static void _osd_req_encode_common(struct osd_request *or,
 /*
  * Device commands
  */
+/*TODO: void osd_req_set_master_seed_xchg(struct osd_request *, ...); */
+/*TODO: void osd_req_set_master_key(struct osd_request *, ...); */
+
 void osd_req_format(struct osd_request *or, u64 tot_capacity)
 {
 	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
@@ -369,6 +372,10 @@ void osd_req_flush_obsd(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_flush_obsd);
 
+/*TODO: void osd_req_perform_scsi_command(struct osd_request *,
+	const u8 *cdb, ...); */
+/*TODO: void osd_req_task_management(struct osd_request *, ...); */
+
 /*
  * Partition commands
  */
@@ -395,6 +402,10 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition)
 }
 EXPORT_SYMBOL(osd_req_remove_partition);
 
+/*TODO: void osd_req_set_partition_key(struct osd_request *,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]); */
+
 static int _osd_req_list_objects(struct osd_request *or,
 	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
 	struct osd_obj_id_list *list, unsigned nelem)
@@ -460,6 +471,11 @@ EXPORT_SYMBOL(osd_req_flush_partition);
 /*
  * Collection commands
  */
+/*TODO: void osd_req_create_collection(struct osd_request *,
+	const struct osd_obj_id *); */
+/*TODO: void osd_req_remove_collection(struct osd_request *,
+	const struct osd_obj_id *); */
+
 int osd_req_list_collection_objects(struct osd_request *or,
 	const struct osd_obj_id *obj, osd_id initial_id,
 	struct osd_obj_id_list *list, unsigned nelem)
@@ -469,6 +485,8 @@ int osd_req_list_collection_objects(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_list_collection_objects);
 
+/*TODO: void query(struct osd_request *, ...); V2 */
+
 void osd_req_flush_collection(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
 {
@@ -477,6 +495,9 @@ void osd_req_flush_collection(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_flush_collection);
 
+/*TODO: void get_member_attrs(struct osd_request *, ...); V2 */
+/*TODO: void set_member_attrs(struct osd_request *, ...); V2 */
+
 /*
  * Object commands
  */
@@ -492,6 +513,11 @@ void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
 }
 EXPORT_SYMBOL(osd_req_remove_object);
 
+
+/*TODO: void osd_req_create_multi(struct osd_request *or,
+	struct osd_obj_id *first, struct osd_obj_id_list *list, unsigned nelem);
+*/
+
 void osd_req_write(struct osd_request *or,
 	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
 {
@@ -503,6 +529,15 @@ void osd_req_write(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_write);
 
+/*TODO: void osd_req_append(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out); */
+/*TODO: void osd_req_create_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset); */
+/*TODO: void osd_req_clear(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len); */
+/*TODO: void osd_req_punch(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len); V2 */
+
 void osd_req_flush_object(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
 	/*V2*/ u64 offset, /*V2*/ u64 len)
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 12/18] libosd: Not implemented commands
@ 2008-12-22 13:04     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:04 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Some commands declared in header are not yet implemented. Put them
as stubs in .c file, just so they take their place in the file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   35 +++++++++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 91f58fd..d3cc7ed 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -339,6 +339,9 @@ static void _osd_req_encode_common(struct osd_request *or,
 /*
  * Device commands
  */
+/*TODO: void osd_req_set_master_seed_xchg(struct osd_request *, ...); */
+/*TODO: void osd_req_set_master_key(struct osd_request *, ...); */
+
 void osd_req_format(struct osd_request *or, u64 tot_capacity)
 {
 	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
@@ -369,6 +372,10 @@ void osd_req_flush_obsd(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_flush_obsd);
 
+/*TODO: void osd_req_perform_scsi_command(struct osd_request *,
+	const u8 *cdb, ...); */
+/*TODO: void osd_req_task_management(struct osd_request *, ...); */
+
 /*
  * Partition commands
  */
@@ -395,6 +402,10 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition)
 }
 EXPORT_SYMBOL(osd_req_remove_partition);
 
+/*TODO: void osd_req_set_partition_key(struct osd_request *,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]); */
+
 static int _osd_req_list_objects(struct osd_request *or,
 	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
 	struct osd_obj_id_list *list, unsigned nelem)
@@ -460,6 +471,11 @@ EXPORT_SYMBOL(osd_req_flush_partition);
 /*
  * Collection commands
  */
+/*TODO: void osd_req_create_collection(struct osd_request *,
+	const struct osd_obj_id *); */
+/*TODO: void osd_req_remove_collection(struct osd_request *,
+	const struct osd_obj_id *); */
+
 int osd_req_list_collection_objects(struct osd_request *or,
 	const struct osd_obj_id *obj, osd_id initial_id,
 	struct osd_obj_id_list *list, unsigned nelem)
@@ -469,6 +485,8 @@ int osd_req_list_collection_objects(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_list_collection_objects);
 
+/*TODO: void query(struct osd_request *, ...); V2 */
+
 void osd_req_flush_collection(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
 {
@@ -477,6 +495,9 @@ void osd_req_flush_collection(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_flush_collection);
 
+/*TODO: void get_member_attrs(struct osd_request *, ...); V2 */
+/*TODO: void set_member_attrs(struct osd_request *, ...); V2 */
+
 /*
  * Object commands
  */
@@ -492,6 +513,11 @@ void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
 }
 EXPORT_SYMBOL(osd_req_remove_object);
 
+
+/*TODO: void osd_req_create_multi(struct osd_request *or,
+	struct osd_obj_id *first, struct osd_obj_id_list *list, unsigned nelem);
+*/
+
 void osd_req_write(struct osd_request *or,
 	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
 {
@@ -503,6 +529,15 @@ void osd_req_write(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_write);
 
+/*TODO: void osd_req_append(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out); */
+/*TODO: void osd_req_create_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset); */
+/*TODO: void osd_req_clear(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len); */
+/*TODO: void osd_req_punch(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len); V2 */
+
 void osd_req_flush_object(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
 	/*V2*/ u64 offset, /*V2*/ u64 len)
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 13/18] libosd: OSD version 2 Support
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 13:07     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:07 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 14172 bytes --]

Add support for OSD2 at run time. It is now possible to run with
both OSDv1 and OSDv2 targets at the same time. The actual detection
should be preformed by the security manager, as the version is encoded
in the capability structure.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   94 ++++++++++++++++++++++++++++++++------
 include/scsi/osd_initiator.h     |   39 ++++++++++++++++
 include/scsi/osd_protocol.h      |   90 ++++++++++++++++++++++++++++++++++--
 3 files changed, 205 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index d3cc7ed..9d2ec73 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -55,36 +55,50 @@ static inline void build_test(void)
 {
 	/* structures were not packed */
 	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
 	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
 }
 
 static unsigned _osd_req_cdb_len(struct osd_request *or)
 {
-	return OSDv1_TOTAL_CDB_LEN;
+	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
 }
 
 static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
 {
-	return osdv1_attr_list_elem_size(len);
+	return osd_req_is_ver1(or) ?
+		osdv1_attr_list_elem_size(len) :
+		osdv2_attr_list_elem_size(len);
 }
 
 static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
 {
-	return osdv1_list_size(list_head);
+	return osd_req_is_ver1(or) ?
+		osdv1_list_size(list_head) :
+		osdv2_list_size(list_head);
 }
 
 static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
 {
-	return sizeof(struct osdv1_attributes_list_header);
+	return osd_req_is_ver1(or) ?
+		sizeof(struct osdv1_attributes_list_header) :
+		sizeof(struct osdv2_attributes_list_header);
 }
 
 static void _osd_req_set_alist_type(struct osd_request *or,
 	void *list, int list_type)
 {
-	struct osdv1_attributes_list_header *attr_list = list;
+	if (osd_req_is_ver1(or)) {
+		struct osdv1_attributes_list_header *attr_list = list;
+
+		memset(attr_list, 0, sizeof(*attr_list));
+		attr_list->type = list_type;
+	} else {
+		struct osdv2_attributes_list_header *attr_list = list;
 
-	memset(attr_list, 0, sizeof(*attr_list));
-	attr_list->type = list_type;
+		memset(attr_list, 0, sizeof(*attr_list));
+		attr_list->type = list_type;
+	}
 }
 
 static bool _osd_req_is_alist_type(struct osd_request *or,
@@ -93,10 +107,14 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
 	if (!list)
 		return false;
 
-	if (1) {
+	if (osd_req_is_ver1(or)) {
 		struct osdv1_attributes_list_header *attr_list = list;
 
 		return attr_list->type == list_type;
+	} else {
+		struct osdv2_attributes_list_header *attr_list = list;
+
+		return attr_list->type == list_type;
 	}
 }
 
@@ -106,15 +124,22 @@ static void _osd_req_encode_olist(struct osd_request *or,
 {
 	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
 
-	cdbh->v1.list_identifier = list->list_identifier;
-	cdbh->v1.start_address = list->continuation_id;
+	if (osd_req_is_ver1(or)) {
+		cdbh->v1.list_identifier = list->list_identifier;
+		cdbh->v1.start_address = list->continuation_id;
+	} else {
+		cdbh->v2.list_identifier = list->list_identifier;
+		cdbh->v2.start_address = list->continuation_id;
+	}
 }
 
 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 	u64 offset, unsigned *padding)
 {
 	return __osd_encode_offset(offset, padding,
-				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+			osd_req_is_ver1(or) ?
+				OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT,
+			OSD_OFFSET_MAX_SHIFT);
 }
 
 static struct osd_security_parameters *
@@ -122,7 +147,10 @@ _osd_req_sec_params(struct osd_request *or)
 {
 	struct osd_cdb *ocdb = &or->cdb;
 
-	return &ocdb->v1.sec_params;
+	if (osd_req_is_ver1(or))
+		return &ocdb->v1.sec_params;
+	else
+		return &ocdb->v2.sec_params;
 }
 
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
@@ -130,6 +158,9 @@ void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
 	memset(osdd, 0, sizeof(*osdd));
 	osdd->scsi_device = scsi_device;
 	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+#ifdef OSD_VER1_SUPPORT
+	osdd->version = OSD_VER2;
+#endif
 	/* TODO: Allocate pools for osd_request attributes ... */
 }
 EXPORT_SYMBOL(osd_dev_init);
@@ -330,10 +361,30 @@ static void _osdv1_req_encode_common(struct osd_request *or,
 	ocdb->h.v1.start_address = cpu_to_be64(offset);
 }
 
+static void _osdv2_req_encode_common(struct osd_request *or,
+	 __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv2_cdb *ocdb = &or->cdb.v2;
+
+	OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v2.length = cpu_to_be64(len);
+	ocdb->h.v2.start_address = cpu_to_be64(offset);
+}
+
 static void _osd_req_encode_common(struct osd_request *or,
 	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
 {
-	_osdv1_req_encode_common(or, act, obj, offset, len);
+	if (osd_req_is_ver1(or))
+		_osdv1_req_encode_common(or, act, obj, offset, len);
+	else
+		_osdv2_req_encode_common(or, act, obj, offset, len);
 }
 
 /*
@@ -542,6 +593,12 @@ void osd_req_flush_object(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
 	/*V2*/ u64 offset, /*V2*/ u64 len)
 {
+	if (unlikely(osd_req_is_ver1(or) && (offset || len))) {
+		OSD_DEBUG("OSD Ver1 flush on specific range ignored\n");
+		offset = 0;
+		len = 0;
+	}
+
 	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
 	_osd_req_encode_flush(or, op);
 }
@@ -1164,6 +1221,10 @@ enum { OSD_SEC_CAP_V1_ALL_CAPS =
 	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
 };
 
+enum { OSD_SEC_CAP_V2_ALL_CAPS =
+	OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT
+};
+
 void osd_sec_init_nosec_doall_caps(void *caps,
 	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
 {
@@ -1205,9 +1266,14 @@ void osd_sec_init_nosec_doall_caps(void *caps,
 }
 EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
 
+/* FIXME: Extract version from caps pointer.
+ *        Also Pete's target only supports caps from OSDv1 for now
+ */
 void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 {
-	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+	bool is_ver1 = true;
+	/* NOTE: They start at same address */
+	memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN);
 }
 
 bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms)
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 93fa86b..778a624 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -21,6 +21,23 @@
 
 /* Note: "NI" in comments below means "Not Implemented yet" */
 
+/* Configure of code:
+ * #undef if you *don't* want OSD v1 support in runtime.
+ * If #defined the initiator will dynamically configure to encode OSD v1
+ * CDB's if the target is detected to be OSD v1 only.
+ * OSD v2 only commands, options, and attributes will be ignored if target
+ * is v1 only.
+ * If #defined will result in bigger/slower code (OK Slower maybe not)
+ * Q: Should this be CONFIG_SCSI_OSD_VER1_SUPPORT and set from Kconfig?
+ */
+#define OSD_VER1_SUPPORT y
+
+enum osd_std_version {
+	OSD_VER_NONE = 0,
+	OSD_VER1 = 1,
+	OSD_VER2 = 2,
+};
+
 /*
  * Object-based Storage Device.
  * This object represents an OSD device.
@@ -31,6 +48,10 @@
 struct osd_dev {
 	struct scsi_device *scsi_device;
 	unsigned def_timeout;
+
+#ifdef OSD_VER1_SUPPORT
+	enum osd_std_version version;
+#endif
 };
 
 /* Retrieve/return osd_dev(s) for use by Kernel clients */
@@ -41,6 +62,14 @@ void osduld_put_device(struct osd_dev *od);
 void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
 void osd_dev_fini(struct osd_dev *od);
 
+/* we might want to use function vector in the future */
+static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v)
+{
+#ifdef OSD_VER1_SUPPORT
+	od->version = v;
+#endif
+}
+
 struct osd_request;
 typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
 
@@ -77,6 +106,16 @@ struct osd_request {
 	int async_error;
 };
 
+/* OSD Version control */
+static inline bool osd_req_is_ver1(struct osd_request *or)
+{
+#ifdef OSD_VER1_SUPPORT
+	return or->osd_dev->version == OSD_VER1;
+#else
+	return false;
+#endif
+}
+
 /*
  * How to use the osd library:
  *
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
index eeb899b..3875613 100644
--- a/include/scsi/osd_protocol.h
+++ b/include/scsi/osd_protocol.h
@@ -25,12 +25,16 @@ enum {
 	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
 	OSDv1_CAP_LEN = 80,
 	/* Latest supported version */
-	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
-	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
-	OSD_CAP_LEN = OSDv1_CAP_LEN,
+/* 	OSD_ADDITIONAL_CDB_LENGTH = 216,*/
+	OSD_ADDITIONAL_CDB_LENGTH =
+		OSDv1_ADDITIONAL_CDB_LENGTH, /* FIXME: Pete rev-001 sup */
+	OSD_TOTAL_CDB_LEN = OSD_ADDITIONAL_CDB_LENGTH + 8,
+/* 	OSD_CAP_LEN = 104,*/
+	OSD_CAP_LEN = OSDv1_CAP_LEN,/* FIXME: Pete rev-001 sup */
 
 	OSD_SYSTEMID_LEN = 20,
 	OSD_CRYPTO_KEYID_SIZE = 20,
+	/*FIXME: OSDv2_CRYPTO_KEYID_SIZE = 32,*/
 	OSD_CRYPTO_SEED_SIZE = 4,
 	OSD_CRYPTO_NONCE_SIZE = 12,
 	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
@@ -108,6 +112,7 @@ enum {
 	OSD_OFFSET_MAX_BITS = 28,
 
 	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MIN_SHIFT = 3,
 	OSD_OFFSET_MAX_SHIFT = 16,
 };
 
@@ -129,6 +134,16 @@ static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
 				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
 }
 
+/* Minimum 8 bytes alignment
+ * Same as v1 but since exponent can be signed than a less than
+ * 256 alignment can be reached with small offsets (<2GB)
+ */
+static inline osd_cdb_offset osd_encode_offset_v2(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				   OSD_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
 /* osd2r03: 5.2.1 Overview */
 struct osd_cdb_head {
 	struct scsi_varlen_cdb_hdr varlen_cdb;
@@ -144,6 +159,13 @@ struct osd_cdb_head {
 /*36*/			__be64		length;
 /*44*/			__be64		start_address;
 		} __packed v1;
+
+		struct __osdv2_cdb_addr_len {
+			/* called allocation_length in some commands */
+/*32*/			__be64	length;
+/*40*/			__be64	start_address;
+/*48*/			__be32 list_identifier;/* Rarely used */
+		} __packed v2;
 	};
 /*52*/	union { /* selected attributes mode Page/List/Single */
 		struct osd_attributes_page_mode {
@@ -182,6 +204,7 @@ struct osd_cdb_head {
 /*80*/
 
 /*160 v1*/
+/*184 v2*/
 struct osd_security_parameters {
 /*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
 /*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
@@ -189,6 +212,9 @@ struct osd_security_parameters {
 /*196*/osd_cdb_offset	data_out_integrity_check_offset;
 } __packed;
 /*200 v1*/
+/*224 v2*/
+
+/* FIXME: osdv2_security_parameters */
 
 struct osdv1_cdb {
 	struct osd_cdb_head h;
@@ -196,9 +222,17 @@ struct osdv1_cdb {
 	struct osd_security_parameters sec_params;
 } __packed;
 
+struct osdv2_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSD_CAP_LEN];
+	struct osd_security_parameters sec_params;
+	/* FIXME: osdv2_security_parameters */
+} __packed;
+
 struct osd_cdb {
 	union {
 		struct osdv1_cdb v1;
+		struct osdv2_cdb v2;
 		u8 buff[OSD_TOTAL_CDB_LEN];
 	};
 } __packed;
@@ -269,6 +303,7 @@ struct osd_attributes_list_attrid {
 /*
  * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
  *                  for setting attributes
+ * NOTE: v2 is 8-bytes aligned, v1 is not aligned.
  */
 struct osd_attributes_list_element {
 	__be32 page;
@@ -279,6 +314,7 @@ struct osd_attributes_list_element {
 
 enum {
 	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+	OSD_ATTRIBUTES_ELEM_ALIGN = 8,
 };
 
 enum {
@@ -292,6 +328,12 @@ static inline unsigned osdv1_attr_list_elem_size(unsigned len)
 		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
 }
 
+static inline unsigned osdv2_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSD_ATTRIBUTES_ELEM_ALIGN);
+}
+
 /*
  * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
  */
@@ -326,6 +368,21 @@ static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
 	return be16_to_cpu(h->list_bytes);
 }
 
+struct osdv2_attributes_list_header {
+	u8 type;	/* lower 4-bits only */
+	u8 pad[3];
+/*4*/	__be32 list_bytes; /* Initiator shall set to zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv2_list_size(struct osdv2_attributes_list_header *h)
+{
+	return be32_to_cpu(h->list_bytes);
+}
+
 /* (osd-r10 6.13)
  * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
  *	for root_lstchg below
@@ -469,11 +526,36 @@ struct osdv1_cap_object_descriptor {
 } __packed;
 /*80 v1*/
 
-struct osd_capability {
+/*56 v2*/
+struct osd_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 allowed_attributes_access;
+/*60*/			__be32 policy_access_tag;
+/*64*/			__be16 boot_epoch;
+/*66*/			u8 reserved[6];
+/*72*/			__be64 allowed_partition_id;
+/*80*/			__be64 allowed_object_id;
+/*88*/			__be64 allowed_range_length;
+/*96*/			__be64 allowed_range_start;
+		} __packed obj_desc;
+
+/*56*/		u8 object_descriptor[48];
+	};
+} __packed;
+/*104 v2*/
+
+struct osdv1_capability {
 	struct osd_capability_head h;
 	struct osdv1_cap_object_descriptor od;
 } __packed;
 
+struct osd_capability {
+	struct osd_capability_head h;
+/* 	struct osd_cap_object_descriptor od;*/
+	struct osdv1_cap_object_descriptor od; /* FIXME: Pete rev-001 sup */
+} __packed;
+
 /**
  * osd_sec_set_caps - set cap-bits into the capabilities header
  *
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 13/18] libosd: OSD version 2 Support
@ 2008-12-22 13:07     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:07 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Add support for OSD2 at run time. It is now possible to run with
both OSDv1 and OSDv2 targets at the same time. The actual detection
should be preformed by the security manager, as the version is encoded
in the capability structure.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   94 ++++++++++++++++++++++++++++++++------
 include/scsi/osd_initiator.h     |   39 ++++++++++++++++
 include/scsi/osd_protocol.h      |   90 ++++++++++++++++++++++++++++++++++--
 3 files changed, 205 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index d3cc7ed..9d2ec73 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -55,36 +55,50 @@ static inline void build_test(void)
 {
 	/* structures were not packed */
 	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
 	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
 }
 
 static unsigned _osd_req_cdb_len(struct osd_request *or)
 {
-	return OSDv1_TOTAL_CDB_LEN;
+	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
 }
 
 static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
 {
-	return osdv1_attr_list_elem_size(len);
+	return osd_req_is_ver1(or) ?
+		osdv1_attr_list_elem_size(len) :
+		osdv2_attr_list_elem_size(len);
 }
 
 static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
 {
-	return osdv1_list_size(list_head);
+	return osd_req_is_ver1(or) ?
+		osdv1_list_size(list_head) :
+		osdv2_list_size(list_head);
 }
 
 static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
 {
-	return sizeof(struct osdv1_attributes_list_header);
+	return osd_req_is_ver1(or) ?
+		sizeof(struct osdv1_attributes_list_header) :
+		sizeof(struct osdv2_attributes_list_header);
 }
 
 static void _osd_req_set_alist_type(struct osd_request *or,
 	void *list, int list_type)
 {
-	struct osdv1_attributes_list_header *attr_list = list;
+	if (osd_req_is_ver1(or)) {
+		struct osdv1_attributes_list_header *attr_list = list;
+
+		memset(attr_list, 0, sizeof(*attr_list));
+		attr_list->type = list_type;
+	} else {
+		struct osdv2_attributes_list_header *attr_list = list;
 
-	memset(attr_list, 0, sizeof(*attr_list));
-	attr_list->type = list_type;
+		memset(attr_list, 0, sizeof(*attr_list));
+		attr_list->type = list_type;
+	}
 }
 
 static bool _osd_req_is_alist_type(struct osd_request *or,
@@ -93,10 +107,14 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
 	if (!list)
 		return false;
 
-	if (1) {
+	if (osd_req_is_ver1(or)) {
 		struct osdv1_attributes_list_header *attr_list = list;
 
 		return attr_list->type == list_type;
+	} else {
+		struct osdv2_attributes_list_header *attr_list = list;
+
+		return attr_list->type == list_type;
 	}
 }
 
@@ -106,15 +124,22 @@ static void _osd_req_encode_olist(struct osd_request *or,
 {
 	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
 
-	cdbh->v1.list_identifier = list->list_identifier;
-	cdbh->v1.start_address = list->continuation_id;
+	if (osd_req_is_ver1(or)) {
+		cdbh->v1.list_identifier = list->list_identifier;
+		cdbh->v1.start_address = list->continuation_id;
+	} else {
+		cdbh->v2.list_identifier = list->list_identifier;
+		cdbh->v2.start_address = list->continuation_id;
+	}
 }
 
 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 	u64 offset, unsigned *padding)
 {
 	return __osd_encode_offset(offset, padding,
-				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+			osd_req_is_ver1(or) ?
+				OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT,
+			OSD_OFFSET_MAX_SHIFT);
 }
 
 static struct osd_security_parameters *
@@ -122,7 +147,10 @@ _osd_req_sec_params(struct osd_request *or)
 {
 	struct osd_cdb *ocdb = &or->cdb;
 
-	return &ocdb->v1.sec_params;
+	if (osd_req_is_ver1(or))
+		return &ocdb->v1.sec_params;
+	else
+		return &ocdb->v2.sec_params;
 }
 
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
@@ -130,6 +158,9 @@ void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
 	memset(osdd, 0, sizeof(*osdd));
 	osdd->scsi_device = scsi_device;
 	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+#ifdef OSD_VER1_SUPPORT
+	osdd->version = OSD_VER2;
+#endif
 	/* TODO: Allocate pools for osd_request attributes ... */
 }
 EXPORT_SYMBOL(osd_dev_init);
@@ -330,10 +361,30 @@ static void _osdv1_req_encode_common(struct osd_request *or,
 	ocdb->h.v1.start_address = cpu_to_be64(offset);
 }
 
+static void _osdv2_req_encode_common(struct osd_request *or,
+	 __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv2_cdb *ocdb = &or->cdb.v2;
+
+	OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v2.length = cpu_to_be64(len);
+	ocdb->h.v2.start_address = cpu_to_be64(offset);
+}
+
 static void _osd_req_encode_common(struct osd_request *or,
 	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
 {
-	_osdv1_req_encode_common(or, act, obj, offset, len);
+	if (osd_req_is_ver1(or))
+		_osdv1_req_encode_common(or, act, obj, offset, len);
+	else
+		_osdv2_req_encode_common(or, act, obj, offset, len);
 }
 
 /*
@@ -542,6 +593,12 @@ void osd_req_flush_object(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
 	/*V2*/ u64 offset, /*V2*/ u64 len)
 {
+	if (unlikely(osd_req_is_ver1(or) && (offset || len))) {
+		OSD_DEBUG("OSD Ver1 flush on specific range ignored\n");
+		offset = 0;
+		len = 0;
+	}
+
 	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
 	_osd_req_encode_flush(or, op);
 }
@@ -1164,6 +1221,10 @@ enum { OSD_SEC_CAP_V1_ALL_CAPS =
 	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
 };
 
+enum { OSD_SEC_CAP_V2_ALL_CAPS =
+	OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT
+};
+
 void osd_sec_init_nosec_doall_caps(void *caps,
 	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
 {
@@ -1205,9 +1266,14 @@ void osd_sec_init_nosec_doall_caps(void *caps,
 }
 EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
 
+/* FIXME: Extract version from caps pointer.
+ *        Also Pete's target only supports caps from OSDv1 for now
+ */
 void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 {
-	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+	bool is_ver1 = true;
+	/* NOTE: They start at same address */
+	memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN);
 }
 
 bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms)
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 93fa86b..778a624 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -21,6 +21,23 @@
 
 /* Note: "NI" in comments below means "Not Implemented yet" */
 
+/* Configure of code:
+ * #undef if you *don't* want OSD v1 support in runtime.
+ * If #defined the initiator will dynamically configure to encode OSD v1
+ * CDB's if the target is detected to be OSD v1 only.
+ * OSD v2 only commands, options, and attributes will be ignored if target
+ * is v1 only.
+ * If #defined will result in bigger/slower code (OK Slower maybe not)
+ * Q: Should this be CONFIG_SCSI_OSD_VER1_SUPPORT and set from Kconfig?
+ */
+#define OSD_VER1_SUPPORT y
+
+enum osd_std_version {
+	OSD_VER_NONE = 0,
+	OSD_VER1 = 1,
+	OSD_VER2 = 2,
+};
+
 /*
  * Object-based Storage Device.
  * This object represents an OSD device.
@@ -31,6 +48,10 @@
 struct osd_dev {
 	struct scsi_device *scsi_device;
 	unsigned def_timeout;
+
+#ifdef OSD_VER1_SUPPORT
+	enum osd_std_version version;
+#endif
 };
 
 /* Retrieve/return osd_dev(s) for use by Kernel clients */
@@ -41,6 +62,14 @@ void osduld_put_device(struct osd_dev *od);
 void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
 void osd_dev_fini(struct osd_dev *od);
 
+/* we might want to use function vector in the future */
+static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v)
+{
+#ifdef OSD_VER1_SUPPORT
+	od->version = v;
+#endif
+}
+
 struct osd_request;
 typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
 
@@ -77,6 +106,16 @@ struct osd_request {
 	int async_error;
 };
 
+/* OSD Version control */
+static inline bool osd_req_is_ver1(struct osd_request *or)
+{
+#ifdef OSD_VER1_SUPPORT
+	return or->osd_dev->version == OSD_VER1;
+#else
+	return false;
+#endif
+}
+
 /*
  * How to use the osd library:
  *
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
index eeb899b..3875613 100644
--- a/include/scsi/osd_protocol.h
+++ b/include/scsi/osd_protocol.h
@@ -25,12 +25,16 @@ enum {
 	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
 	OSDv1_CAP_LEN = 80,
 	/* Latest supported version */
-	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
-	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
-	OSD_CAP_LEN = OSDv1_CAP_LEN,
+/* 	OSD_ADDITIONAL_CDB_LENGTH = 216,*/
+	OSD_ADDITIONAL_CDB_LENGTH =
+		OSDv1_ADDITIONAL_CDB_LENGTH, /* FIXME: Pete rev-001 sup */
+	OSD_TOTAL_CDB_LEN = OSD_ADDITIONAL_CDB_LENGTH + 8,
+/* 	OSD_CAP_LEN = 104,*/
+	OSD_CAP_LEN = OSDv1_CAP_LEN,/* FIXME: Pete rev-001 sup */
 
 	OSD_SYSTEMID_LEN = 20,
 	OSD_CRYPTO_KEYID_SIZE = 20,
+	/*FIXME: OSDv2_CRYPTO_KEYID_SIZE = 32,*/
 	OSD_CRYPTO_SEED_SIZE = 4,
 	OSD_CRYPTO_NONCE_SIZE = 12,
 	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
@@ -108,6 +112,7 @@ enum {
 	OSD_OFFSET_MAX_BITS = 28,
 
 	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MIN_SHIFT = 3,
 	OSD_OFFSET_MAX_SHIFT = 16,
 };
 
@@ -129,6 +134,16 @@ static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
 				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
 }
 
+/* Minimum 8 bytes alignment
+ * Same as v1 but since exponent can be signed than a less than
+ * 256 alignment can be reached with small offsets (<2GB)
+ */
+static inline osd_cdb_offset osd_encode_offset_v2(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				   OSD_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
 /* osd2r03: 5.2.1 Overview */
 struct osd_cdb_head {
 	struct scsi_varlen_cdb_hdr varlen_cdb;
@@ -144,6 +159,13 @@ struct osd_cdb_head {
 /*36*/			__be64		length;
 /*44*/			__be64		start_address;
 		} __packed v1;
+
+		struct __osdv2_cdb_addr_len {
+			/* called allocation_length in some commands */
+/*32*/			__be64	length;
+/*40*/			__be64	start_address;
+/*48*/			__be32 list_identifier;/* Rarely used */
+		} __packed v2;
 	};
 /*52*/	union { /* selected attributes mode Page/List/Single */
 		struct osd_attributes_page_mode {
@@ -182,6 +204,7 @@ struct osd_cdb_head {
 /*80*/
 
 /*160 v1*/
+/*184 v2*/
 struct osd_security_parameters {
 /*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
 /*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
@@ -189,6 +212,9 @@ struct osd_security_parameters {
 /*196*/osd_cdb_offset	data_out_integrity_check_offset;
 } __packed;
 /*200 v1*/
+/*224 v2*/
+
+/* FIXME: osdv2_security_parameters */
 
 struct osdv1_cdb {
 	struct osd_cdb_head h;
@@ -196,9 +222,17 @@ struct osdv1_cdb {
 	struct osd_security_parameters sec_params;
 } __packed;
 
+struct osdv2_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSD_CAP_LEN];
+	struct osd_security_parameters sec_params;
+	/* FIXME: osdv2_security_parameters */
+} __packed;
+
 struct osd_cdb {
 	union {
 		struct osdv1_cdb v1;
+		struct osdv2_cdb v2;
 		u8 buff[OSD_TOTAL_CDB_LEN];
 	};
 } __packed;
@@ -269,6 +303,7 @@ struct osd_attributes_list_attrid {
 /*
  * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
  *                  for setting attributes
+ * NOTE: v2 is 8-bytes aligned, v1 is not aligned.
  */
 struct osd_attributes_list_element {
 	__be32 page;
@@ -279,6 +314,7 @@ struct osd_attributes_list_element {
 
 enum {
 	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+	OSD_ATTRIBUTES_ELEM_ALIGN = 8,
 };
 
 enum {
@@ -292,6 +328,12 @@ static inline unsigned osdv1_attr_list_elem_size(unsigned len)
 		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
 }
 
+static inline unsigned osdv2_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSD_ATTRIBUTES_ELEM_ALIGN);
+}
+
 /*
  * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
  */
@@ -326,6 +368,21 @@ static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
 	return be16_to_cpu(h->list_bytes);
 }
 
+struct osdv2_attributes_list_header {
+	u8 type;	/* lower 4-bits only */
+	u8 pad[3];
+/*4*/	__be32 list_bytes; /* Initiator shall set to zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv2_list_size(struct osdv2_attributes_list_header *h)
+{
+	return be32_to_cpu(h->list_bytes);
+}
+
 /* (osd-r10 6.13)
  * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
  *	for root_lstchg below
@@ -469,11 +526,36 @@ struct osdv1_cap_object_descriptor {
 } __packed;
 /*80 v1*/
 
-struct osd_capability {
+/*56 v2*/
+struct osd_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 allowed_attributes_access;
+/*60*/			__be32 policy_access_tag;
+/*64*/			__be16 boot_epoch;
+/*66*/			u8 reserved[6];
+/*72*/			__be64 allowed_partition_id;
+/*80*/			__be64 allowed_object_id;
+/*88*/			__be64 allowed_range_length;
+/*96*/			__be64 allowed_range_start;
+		} __packed obj_desc;
+
+/*56*/		u8 object_descriptor[48];
+	};
+} __packed;
+/*104 v2*/
+
+struct osdv1_capability {
 	struct osd_capability_head h;
 	struct osdv1_cap_object_descriptor od;
 } __packed;
 
+struct osd_capability {
+	struct osd_capability_head h;
+/* 	struct osd_cap_object_descriptor od;*/
+	struct osdv1_cap_object_descriptor od; /* FIXME: Pete rev-001 sup */
+} __packed;
+
 /**
  * osd_sec_set_caps - set cap-bits into the capabilities header
  *
-- 
1.6.0.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 14/18] libosd: OSDv2 auto detection
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 13:09     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:09 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Auto detect an OSDv2 or OSDv1 target at run time. Note how none
of the OSD API calls change. The tests do not know what device
version it is.

This test now passes against both the IBM-OSD-SIM OSD1 target
as well as OSC's OSD2 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  125 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/osd/osd_uld.c       |    5 ++
 include/scsi/osd_initiator.h     |    3 +
 3 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 9d2ec73..977d595 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -41,6 +41,7 @@
 
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
+#include <scsi/osd_attributes.h>
 #include <scsi/scsi_device.h>
 
 #include "osd_debug.h"
@@ -59,6 +60,130 @@ static inline void build_test(void)
 	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
 }
 
+static char *_osd_ver_desc(struct osd_request *or)
+{
+	return osd_req_is_ver1(or) ? "OSD1" : "OSD2";
+}
+
+#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
+
+static int _osd_print_system_info(struct osd_dev *od, void *caps)
+{
+	struct osd_request *or;
+	struct osd_attr get_attrs[] = {
+		ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/),
+		ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/),
+		ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6),
+		/* IBM-OSD-SIM Has a bug with this one put it last */
+		ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20),
+	};
+	void *iter = NULL, *pFirst;
+	int nelem = ARRAY_SIZE(get_attrs), a = 0;
+	int ret;
+
+	or = osd_start_request(od, GFP_KERNEL);
+	if (!or)
+		return -ENOMEM;
+
+	/* get attrs */
+	osd_req_get_attributes(or, &osd_root_object);
+	osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs));
+
+	ret = osd_finalize_request(or, 0, caps, NULL);
+	if (ret)
+		goto out;
+
+	ret = osd_execute_request(or);
+	if (ret) {
+		OSD_ERR("Failed to detect %s => %d\n", _osd_ver_desc(or), ret);
+		goto out;
+	}
+
+	osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+	OSD_INFO("Detected %s device\n",
+		_osd_ver_desc(or));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_VENDOR_IDENTIFICATION [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_IDENTIFICATION [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_MODEL [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_REVISION_LEVEL [%u]\n",
+		get_unaligned_be32(pFirst));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_OSD_NAME [%s]\n", (char *)pFirst);
+	a++;
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_TOTAL_CAPACITY [0x%llx]\n",
+		_LLU(get_unaligned_be64(pFirst)));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_USED_CAPACITY [0x%llx]\n",
+		_LLU(get_unaligned_be64(pFirst)));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_NUMBER_OF_PARTITIONS [%llu]\n",
+		_LLU(get_unaligned_be64(pFirst)));
+
+	/* FIXME: Where are the time utilities */
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_CLOCK [0x%02x%02x%02x%02x%02x%02x]\n",
+		((char *)pFirst)[0], ((char *)pFirst)[1],
+		((char *)pFirst)[2], ((char *)pFirst)[3],
+		((char *)pFirst)[4], ((char *)pFirst)[5]);
+
+	if (a < nelem) { /* IBM-OSD-SIM bug, Might not have it */
+		int len = get_attrs[a].len;
+		u8 sid_dump[32*4 + 2]; /* 2nibbles+space+ASCII */
+
+		hex_dump_to_buffer(get_attrs[a].val_ptr, len, 32, 1,
+				   sid_dump, sizeof(sid_dump), true);
+		OSD_INFO("OSD_ATTR_RI_OSD_SYSTEM_ID(%d) [%s]\n", len, sid_dump);
+		a++;
+	}
+out:
+	osd_end_request(or);
+	return ret;
+}
+
+int osd_auto_detect_ver(struct osd_dev *od, void *caps)
+{
+	int ret;
+
+	/* Auto-detect the osd version */
+	ret = _osd_print_system_info(od, caps);
+	if (ret) {
+		osd_dev_set_ver(od, OSD_VER1);
+		OSD_DEBUG("converting to OSD1\n");
+		ret = _osd_print_system_info(od, caps);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(osd_auto_detect_ver);
+
 static unsigned _osd_req_cdb_len(struct osd_request *or)
 {
 	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 5ba7654..fa69e09 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -213,6 +213,7 @@ EXPORT_SYMBOL(osduld_put_device);
 static int __detect_osd(struct osd_uld_device *oud)
 {
 	struct scsi_device *scsi_device = oud->od.scsi_device;
+	char caps[OSD_CAP_LEN];
 	int error;
 
 	/* sending a test_unit_ready as first command seems to be needed
@@ -224,6 +225,10 @@ static int __detect_osd(struct osd_uld_device *oud)
 	if (error)
 		OSD_ERR("warning: scsi_test_unit_ready failed\n");
 
+	osd_sec_init_nosec_doall_caps(caps, &osd_root_object, false, true);
+	if (osd_auto_detect_ver(&oud->od, caps))
+		return -ENODEV;
+
 	return 0;
 }
 
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 778a624..8a0fd35 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -62,6 +62,9 @@ void osduld_put_device(struct osd_dev *od);
 void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
 void osd_dev_fini(struct osd_dev *od);
 
+/* some hi level device operations */
+int osd_auto_detect_ver(struct osd_dev *od, void *caps);    /* GFP_KERNEL */
+
 /* we might want to use function vector in the future */
 static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v)
 {
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 14/18] libosd: OSDv2 auto detection
@ 2008-12-22 13:09     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:09 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Auto detect an OSDv2 or OSDv1 target at run time. Note how none
of the OSD API calls change. The tests do not know what device
version it is.

This test now passes against both the IBM-OSD-SIM OSD1 target
as well as OSC's OSD2 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  125 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/osd/osd_uld.c       |    5 ++
 include/scsi/osd_initiator.h     |    3 +
 3 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 9d2ec73..977d595 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -41,6 +41,7 @@
 
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
+#include <scsi/osd_attributes.h>
 #include <scsi/scsi_device.h>
 
 #include "osd_debug.h"
@@ -59,6 +60,130 @@ static inline void build_test(void)
 	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
 }
 
+static char *_osd_ver_desc(struct osd_request *or)
+{
+	return osd_req_is_ver1(or) ? "OSD1" : "OSD2";
+}
+
+#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
+
+static int _osd_print_system_info(struct osd_dev *od, void *caps)
+{
+	struct osd_request *or;
+	struct osd_attr get_attrs[] = {
+		ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/),
+		ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/),
+		ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6),
+		/* IBM-OSD-SIM Has a bug with this one put it last */
+		ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20),
+	};
+	void *iter = NULL, *pFirst;
+	int nelem = ARRAY_SIZE(get_attrs), a = 0;
+	int ret;
+
+	or = osd_start_request(od, GFP_KERNEL);
+	if (!or)
+		return -ENOMEM;
+
+	/* get attrs */
+	osd_req_get_attributes(or, &osd_root_object);
+	osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs));
+
+	ret = osd_finalize_request(or, 0, caps, NULL);
+	if (ret)
+		goto out;
+
+	ret = osd_execute_request(or);
+	if (ret) {
+		OSD_ERR("Failed to detect %s => %d\n", _osd_ver_desc(or), ret);
+		goto out;
+	}
+
+	osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+	OSD_INFO("Detected %s device\n",
+		_osd_ver_desc(or));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_VENDOR_IDENTIFICATION [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_IDENTIFICATION [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_MODEL [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_REVISION_LEVEL [%u]\n",
+		get_unaligned_be32(pFirst));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_OSD_NAME [%s]\n", (char *)pFirst);
+	a++;
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_TOTAL_CAPACITY [0x%llx]\n",
+		_LLU(get_unaligned_be64(pFirst)));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_USED_CAPACITY [0x%llx]\n",
+		_LLU(get_unaligned_be64(pFirst)));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_NUMBER_OF_PARTITIONS [%llu]\n",
+		_LLU(get_unaligned_be64(pFirst)));
+
+	/* FIXME: Where are the time utilities */
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_CLOCK [0x%02x%02x%02x%02x%02x%02x]\n",
+		((char *)pFirst)[0], ((char *)pFirst)[1],
+		((char *)pFirst)[2], ((char *)pFirst)[3],
+		((char *)pFirst)[4], ((char *)pFirst)[5]);
+
+	if (a < nelem) { /* IBM-OSD-SIM bug, Might not have it */
+		int len = get_attrs[a].len;
+		u8 sid_dump[32*4 + 2]; /* 2nibbles+space+ASCII */
+
+		hex_dump_to_buffer(get_attrs[a].val_ptr, len, 32, 1,
+				   sid_dump, sizeof(sid_dump), true);
+		OSD_INFO("OSD_ATTR_RI_OSD_SYSTEM_ID(%d) [%s]\n", len, sid_dump);
+		a++;
+	}
+out:
+	osd_end_request(or);
+	return ret;
+}
+
+int osd_auto_detect_ver(struct osd_dev *od, void *caps)
+{
+	int ret;
+
+	/* Auto-detect the osd version */
+	ret = _osd_print_system_info(od, caps);
+	if (ret) {
+		osd_dev_set_ver(od, OSD_VER1);
+		OSD_DEBUG("converting to OSD1\n");
+		ret = _osd_print_system_info(od, caps);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(osd_auto_detect_ver);
+
 static unsigned _osd_req_cdb_len(struct osd_request *or)
 {
 	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 5ba7654..fa69e09 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -213,6 +213,7 @@ EXPORT_SYMBOL(osduld_put_device);
 static int __detect_osd(struct osd_uld_device *oud)
 {
 	struct scsi_device *scsi_device = oud->od.scsi_device;
+	char caps[OSD_CAP_LEN];
 	int error;
 
 	/* sending a test_unit_ready as first command seems to be needed
@@ -224,6 +225,10 @@ static int __detect_osd(struct osd_uld_device *oud)
 	if (error)
 		OSD_ERR("warning: scsi_test_unit_ready failed\n");
 
+	osd_sec_init_nosec_doall_caps(caps, &osd_root_object, false, true);
+	if (osd_auto_detect_ver(&oud->od, caps))
+		return -ENODEV;
+
 	return 0;
 }
 
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 778a624..8a0fd35 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -62,6 +62,9 @@ void osduld_put_device(struct osd_dev *od);
 void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
 void osd_dev_fini(struct osd_dev *od);
 
+/* some hi level device operations */
+int osd_auto_detect_ver(struct osd_dev *od, void *caps);    /* GFP_KERNEL */
+
 /* we might want to use function vector in the future */
 static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v)
 {
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 15/18] libosd: SCSI/OSD Sense decoding support
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 13:13     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:13 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Implementation of the osd_req_decode_sense() API. Can be called by
library users to decode what failed in command executions.

Add SCSI_OSD_DPRINT_SENSE Kconfig variable. Possible values are:
0 - Do not print any errors to messages file <KERN_ERR>
1 - (Default) Print only decoded errors that are not recoverable.
    Recoverable errors are those that the target has complied with
    the request but with a warning. For example read passed end of
    object will return zeros after the last valid byte.
2- Print all errors.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/osd/Kbuild          |    6 +
 drivers/scsi/osd/osd_initiator.c |  188 +++++++++++++++++++++++++++
 include/scsi/osd_initiator.h     |   49 +++++++
 include/scsi/osd_sense.h         |  260 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 503 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_sense.h

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index 6fb823f..29f7ddd 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -20,6 +20,12 @@ ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
 CONFIG_SCSI_OSD_ULD=m
 ccflags-y += -DCONFIG_SCSI_OSD_ULD -DCONFIG_SCSI_OSD_ULD_MODULE
 
+# CONFIG_SCSI_OSD_DPRINT_SENSE =
+#	0 - no print of errors
+#	1 - print errors
+#	2 - errors + warrnings
+ccflags-y += -DCONFIG_SCSI_OSD_DPRINT_SENSE=1
+
 # Uncomment to turn debug on
 # ccflags-y += -DCONFIG_SCSI_OSD_DEBUG
 
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 977d595..4c663d7 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -42,6 +42,8 @@
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
 #include <scsi/osd_attributes.h>
+#include <scsi/osd_sense.h>
+
 #include <scsi/scsi_device.h>
 
 #include "osd_debug.h"
@@ -1334,6 +1336,192 @@ int osd_finalize_request(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_finalize_request);
 
+#define OSD_SENSE_PRINT1(fmt, a...) \
+	do { \
+		if (__cur_sense_need_output) \
+			OSD_ERR(fmt, ##a); \
+	} while (0)
+
+#define OSD_SENSE_PRINT2(fmt, a...) OSD_SENSE_PRINT1("    " fmt, ##a)
+
+int osd_req_decode_sense_full(struct osd_request *or,
+	struct osd_sense_info *osi, bool silent,
+	struct osd_obj_id *bad_obj_list, int max_obj,
+	struct osd_attr *bad_attr_list, int max_attr)
+{
+	int sense_len, original_sense_len;
+	struct osd_sense_info local_osi;
+	struct scsi_sense_descriptor_based *ssdb;
+	void *cur_descriptor;
+#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 0)
+	const bool __cur_sense_need_output = false;
+#else
+	bool __cur_sense_need_output = !silent;
+#endif
+
+	if (!or->request->errors)
+		return 0;
+
+	ssdb = or->request->sense;
+	sense_len = or->request->sense_len;
+	if ((sense_len < sizeof(*ssdb) || !ssdb->sense_key)) {
+		OSD_ERR("Block-layer returned error(%x) but sense is empty\n",
+			or->request->errors);
+		return 0;
+	}
+
+	if ((ssdb->response_code != 0x72) && (ssdb->response_code != 0x73)) {
+		OSD_ERR("Unrecognized scsi sense: rcode=%x length=%d\n",
+			ssdb->response_code, sense_len);
+		return -EIO;
+	}
+
+	osi = osi ? : &local_osi;
+	memset(osi, 0, sizeof(*osi));
+	osi->key = ssdb->sense_key;
+	osi->additional_code = be16_to_cpu(ssdb->additional_sense_code);
+	original_sense_len = ssdb->additional_sense_length + 8;
+
+#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 1)
+	if (__cur_sense_need_output)
+		__cur_sense_need_output = (osi->key > scsi_sk_recovered_error);
+#endif
+	OSD_SENSE_PRINT1("Main Sense information key=0x%x length(%d, %d) "
+			"additional_code=0x%x\n",
+			osi->key, original_sense_len, sense_len,
+			osi->additional_code);
+
+	if (original_sense_len < sense_len)
+		sense_len = original_sense_len;
+
+	cur_descriptor = ssdb->ssd;
+	sense_len -= sizeof(*ssdb);
+	while (sense_len > 0) {
+		struct scsi_sense_descriptor *ssd = cur_descriptor;
+		int cur_len = ssd->additional_length + 2;
+
+		sense_len -= cur_len;
+
+		if (sense_len < 0)
+			break; /* sense was truncated */
+
+		switch (ssd->descriptor_type) {
+		case scsi_sense_information:
+		case scsi_sense_command_specific_information:
+		{
+			struct scsi_sense_command_specific_data_descriptor
+				*sscd = cur_descriptor;
+
+			osi->command_info =
+				get_unaligned_be64(&sscd->information) ;
+			OSD_SENSE_PRINT2(
+				"command_specific_information 0x%llx \n",
+				_LLU(osi->command_info));
+			break;
+		}
+		case scsi_sense_key_specific:
+		{
+			struct scsi_sense_key_specific_data_descriptor
+				*ssks = cur_descriptor;
+
+			osi->sense_info = get_unaligned_be16(&ssks->value);
+			OSD_SENSE_PRINT2(
+				"sense_key_specific_information %u"
+				"sksv_cd_bpv_bp (0x%x)\n",
+				osi->sense_info, ssks->sksv_cd_bpv_bp);
+			break;
+		}
+		case osd_sense_object_identification:
+		{ /*FIXME: Keep first not last, Store in array*/
+			struct osd_sense_identification_data_descriptor
+				*osidd = cur_descriptor;
+
+			osi->not_initiated_command_functions =
+				le32_to_cpu(osidd->not_initiated_functions);
+			osi->completed_command_functions =
+				le32_to_cpu(osidd->completed_functions);
+			osi->obj.partition = be64_to_cpu(osidd->partition_id);
+			osi->obj.id = be64_to_cpu(osidd->object_id);
+			OSD_SENSE_PRINT2(
+				"object_identification pid=0x%llx oid=0x%llx\n",
+				_LLU(osi->obj.partition), _LLU(osi->obj.id));
+			OSD_SENSE_PRINT2(
+				"not_initiated_bits(%x) "
+				"completed_command_bits(%x)\n",
+				osi->not_initiated_command_functions,
+				osi->completed_command_functions);
+			break;
+		}
+		case osd_sense_response_integrity_check:
+		{
+			struct osd_sense_response_integrity_check_descriptor
+				*osricd = cur_descriptor;
+			const int len = sizeof(osricd->integrity_check_value);
+			u8 key_dump[len*4 + 2]; /* 2nibbles+space+ASCII */
+
+			hex_dump_to_buffer(osricd->integrity_check_value, len,
+				       32, 1, key_dump, sizeof(key_dump), true);
+			OSD_SENSE_PRINT2("response_integrity [%s]\n", key_dump);
+		}
+		case osd_sense_attribute_identification:
+		{
+			struct osd_sense_attributes_data_descriptor
+				*osadd = cur_descriptor;
+			int len = min(cur_len, sense_len);
+			int i = 0;
+			struct osd_sense_attr *pattr = osadd->sense_attrs;
+
+			while (len < 0) {
+				u32 page = be32_to_cpu(pattr->page);
+				u32 attr = be32_to_cpu(pattr->attr);
+
+				if (i++ == 0) {
+					osi->attr.page = page;
+					osi->attr.attr_id = attr;
+				}
+
+				if (bad_attr_list && max_attr) {
+					bad_attr_list->page = page;
+					bad_attr_list->attr_id = attr;
+					bad_attr_list++;
+					max_attr--;
+				}
+				OSD_SENSE_PRINT2(
+					"osd_sense_attribute_identification"
+					"page=0x%x attr=0x%x\n", page, attr);
+			}
+		}
+		/*These are not legal for OSD*/
+		case scsi_sense_field_replaceable_unit:
+			OSD_SENSE_PRINT2("scsi_sense_field_replaceable_unit\n");
+			break;
+		case scsi_sense_stream_commands:
+			OSD_SENSE_PRINT2("scsi_sense_stream_commands\n");
+			break;
+		case scsi_sense_block_commands:
+			OSD_SENSE_PRINT2("scsi_sense_block_commands\n");
+			break;
+		case scsi_sense_ata_return:
+			OSD_SENSE_PRINT2("scsi_sense_ata_return\n");
+			break;
+		default:
+			if (ssd->descriptor_type <= scsi_sense_Reserved_last)
+				OSD_SENSE_PRINT2(
+					"scsi_sense Reserved descriptor (0x%x)",
+					ssd->descriptor_type);
+			else
+				OSD_SENSE_PRINT2(
+					"scsi_sense Vendor descriptor (0x%x)",
+					ssd->descriptor_type);
+		}
+
+		cur_descriptor += cur_len;
+	}
+
+	return (osi->key > scsi_sk_recovered_error) ? -EIO : 0;
+}
+EXPORT_SYMBOL(osd_req_decode_sense_full);
+
 /*
  * Implementation of osd_sec.h API
  * TODO: Move to a separate osd_sec.c file at a later stage.
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 8a0fd35..83b6976 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -212,6 +212,55 @@ int osd_execute_request_async(struct osd_request *or,
 	osd_req_done_fn *done, void *private);
 
 /**
+ * osd_req_decode_sense_full - Decode sense information after execution.
+ *
+ * @or:           - osd_request to examine
+ * @osi           - Recievs a more detailed error report information (optional).
+ * @silent        - Do not print to dmsg (Even if enabled)
+ * @bad_obj_list  - Some commands act on multiple objects. Failed objects will
+ *                  be recieved here (optional)
+ * @max_obj       - Size of @bad_obj_list.
+ * @bad_attr_list - List of failing attributes (optional)
+ * @max_attr      - Size of @bad_attr_list.
+ *
+ * After execution, sense + return code can be analyzed using this function. The
+ * return code is the final disposition on the error. So it is possible that a
+ * CHECK_CONDITION was returned from target but this will return NO_ERROR, for
+ * example on recovered errors. All parameters are optional if caller does
+ * not need any returned information.
+ * Note: This function will also dump the error to dmsg according to settings
+ * of the SCSI_OSD_DPRINT_SENSE Kconfig value. Set @silent if you know the
+ * command would routinely fail, to not spam the dmsg file.
+ */
+struct osd_sense_info {
+	int key;		/* one of enum scsi_sense_keys */
+	int additional_code ;	/* enum osd_additional_sense_codes */
+	union { /* Sense specific information */
+		u16 sense_info;
+		u16 cdb_field_offset; 	/* scsi_invalid_field_in_cdb */
+	};
+	union { /* Command specific information */
+		u64 command_info;
+	};
+
+	u32 not_initiated_command_functions; /* osd_command_functions_bits */
+	u32 completed_command_functions; /* osd_command_functions_bits */
+	struct osd_obj_id obj;
+	struct osd_attr attr;
+};
+
+int osd_req_decode_sense_full(struct osd_request *or,
+	struct osd_sense_info *osi, bool silent,
+	struct osd_obj_id *bad_obj_list, int max_obj,
+	struct osd_attr *bad_attr_list, int max_attr);
+
+static inline int osd_req_decode_sense(struct osd_request *or,
+	struct osd_sense_info *osi)
+{
+	return osd_req_decode_sense_full(or, osi, false, NULL, 0, NULL, 0);
+}
+
+/**
  * osd_end_request - return osd_request to free store
  *
  * @or:		osd_request to free
diff --git a/include/scsi/osd_sense.h b/include/scsi/osd_sense.h
new file mode 100644
index 0000000..026d07e
--- /dev/null
+++ b/include/scsi/osd_sense.h
@@ -0,0 +1,260 @@
+/*
+ * osd_sense.h - OSD Related sense handling definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_SENSE_H__
+#define __OSD_SENSE_H__
+
+#include <scsi/osd_protocol.h>
+
+/* SPC3r23 4.5.6 Sense key and sense code definitions table 27 */
+enum scsi_sense_keys {
+	scsi_sk_no_sense        = 0x0,
+	scsi_sk_recovered_error = 0x1,
+	scsi_sk_not_ready       = 0x2,
+	scsi_sk_medium_error    = 0x3,
+	scsi_sk_hardware_error  = 0x4,
+	scsi_sk_illegal_request = 0x5,
+	scsi_sk_unit_attention  = 0x6,
+	scsi_sk_data_protect    = 0x7,
+	scsi_sk_blank_check     = 0x8,
+	scsi_sk_vendor_specific = 0x9,
+	scsi_sk_copy_aborted    = 0xa,
+	scsi_sk_aborted_command = 0xb,
+	scsi_sk_volume_overflow = 0xd,
+	scsi_sk_miscompare      = 0xe,
+	scsi_sk_reserved        = 0xf,
+};
+
+/* SPC3r23 4.5.6 Sense key and sense code definitions table 28 */
+/* Note: only those which can be returned by an OSD target. Most of
+ *       these errors are taken care of by the generic scsi layer.
+ */
+enum osd_additional_sense_codes {
+	scsi_no_additional_sense_information			= 0x0000,
+	scsi_operation_in_progress				= 0x0016,
+	scsi_cleaning_requested					= 0x0017,
+	scsi_lunr_cause_not_reportable				= 0x0400,
+	scsi_logical_unit_is_in_process_of_becoming_ready	= 0x0401,
+	scsi_lunr_initializing_command_required			= 0x0402,
+	scsi_lunr_manual_intervention_required			= 0x0403,
+	scsi_lunr_operation_in_progress				= 0x0407,
+	scsi_lunr_selftest_in_progress				= 0x0409,
+	scsi_luna_asymmetric_access_state_transition		= 0x040a,
+	scsi_luna_target_port_in_standby_state			= 0x040b,
+	scsi_luna_target_port_in_unavailable_state		= 0x040c,
+	scsi_lunr_notify_enable_spinup_required			= 0x0411,
+	scsi_logical_unit_does_not_respond_to_selection		= 0x0500,
+	scsi_logical_unit_communication_failure			= 0x0800,
+	scsi_logical_unit_communication_timeout			= 0x0801,
+	scsi_logical_unit_communication_parity_error		= 0x0802,
+	scsi_error_log_overflow					= 0x0a00,
+	scsi_warning						= 0x0b00,
+	scsi_warning_specified_temperature_exceeded		= 0x0b01,
+	scsi_warning_enclosure_degraded				= 0x0b02,
+	scsi_write_error_unexpected_unsolicited_data		= 0x0c0c,
+	scsi_write_error_not_enough_unsolicited_data		= 0x0c0d,
+	scsi_invalid_information_unit				= 0x0e00,
+	scsi_invalid_field_in_command_information_unit		= 0x0e03,
+	scsi_read_error_failed_retransmission_request		= 0x1113,
+	scsi_parameter_list_length_error			= 0x1a00,
+	scsi_invalid_command_operation_code			= 0x2000,
+	scsi_invalid_field_in_cdb				= 0x2400,
+	osd_security_audit_value_frozen				= 0x2404,
+	osd_security_working_key_frozen				= 0x2405,
+	osd_nonce_not_unique					= 0x2406,
+	osd_nonce_timestamp_out_of_range			= 0x2407,
+	scsi_logical_unit_not_supported				= 0x2500,
+	scsi_invalid_field_in_parameter_list			= 0x2600,
+	scsi_parameter_not_supported				= 0x2601,
+	scsi_parameter_value_invalid				= 0x2602,
+	scsi_invalid_release_of_persistent_reservation		= 0x2604,
+	osd_invalid_dataout_buffer_integrity_check_value	= 0x260f,
+	scsi_not_ready_to_ready_change_medium_may_have_changed	= 0x2800,
+	scsi_power_on_reset_or_bus_device_reset_occurred	= 0x2900,
+	scsi_power_on_occurred					= 0x2901,
+	scsi_scsi_bus_reset_occurred				= 0x2902,
+	scsi_bus_device_reset_function_occurred			= 0x2903,
+	scsi_device_internal_reset				= 0x2904,
+	scsi_transceiver_mode_changed_to_single_ended		= 0x2905,
+	scsi_transceiver_mode_changed_to_lvd			= 0x2906,
+	scsi_i_t_nexus_loss_occurred				= 0x2907,
+	scsi_parameters_changed					= 0x2a00,
+	scsi_mode_parameters_changed				= 0x2a01,
+	scsi_asymmetric_access_state_changed			= 0x2a06,
+	scsi_priority_changed					= 0x2a08,
+	scsi_command_sequence_error				= 0x2c00,
+	scsi_previous_busy_status				= 0x2c07,
+	scsi_previous_task_set_full_status			= 0x2c08,
+	scsi_previous_reservation_conflict_status		= 0x2c09,
+	osd_partition_or_collection_contains_user_objects	= 0x2c0a,
+	scsi_commands_cleared_by_another_initiator		= 0x2f00,
+	scsi_cleaning_failure					= 0x3007,
+	scsi_enclosure_failure					= 0x3400,
+	scsi_enclosure_services_failure				= 0x3500,
+	scsi_unsupported_enclosure_function			= 0x3501,
+	scsi_enclosure_services_unavailable			= 0x3502,
+	scsi_enclosure_services_transfer_failure		= 0x3503,
+	scsi_enclosure_services_transfer_refused		= 0x3504,
+	scsi_enclosure_services_checksum_error			= 0x3505,
+	scsi_rounded_parameter					= 0x3700,
+	osd_read_past_end_of_user_object			= 0x3b17,
+	scsi_logical_unit_has_not_self_configured_yet		= 0x3e00,
+	scsi_logical_unit_failure				= 0x3e01,
+	scsi_timeout_on_logical_unit				= 0x3e02,
+	scsi_logical_unit_failed_selftest			= 0x3e03,
+	scsi_logical_unit_unable_to_update_selftest_log		= 0x3e04,
+	scsi_target_operating_conditions_have_changed		= 0x3f00,
+	scsi_microcode_has_been_changed				= 0x3f01,
+	scsi_inquiry_data_has_changed				= 0x3f03,
+	scsi_echo_buffer_overwritten				= 0x3f0f,
+	scsi_diagnostic_failure_on_component_nn_first		= 0x4080,
+	scsi_diagnostic_failure_on_component_nn_last		= 0x40ff,
+	scsi_message_error					= 0x4300,
+	scsi_internal_target_failure				= 0x4400,
+	scsi_select_or_reselect_failure				= 0x4500,
+	scsi_scsi_parity_error					= 0x4700,
+	scsi_data_phase_crc_error_detected			= 0x4701,
+	scsi_scsi_parity_error_detected_during_st_data_phase	= 0x4702,
+	scsi_asynchronous_information_protection_error_detected	= 0x4704,
+	scsi_protocol_service_crc_error				= 0x4705,
+	scsi_phy_test_function_in_progress			= 0x4706,
+	scsi_invalid_message_error				= 0x4900,
+	scsi_command_phase_error				= 0x4a00,
+	scsi_data_phase_error					= 0x4b00,
+	scsi_logical_unit_failed_self_configuration		= 0x4c00,
+	scsi_overlapped_commands_attempted			= 0x4e00,
+	osd_quota_error						= 0x5507,
+	scsi_failure_prediction_threshold_exceeded		= 0x5d00,
+	scsi_failure_prediction_threshold_exceeded_false	= 0x5dff,
+	scsi_voltage_fault					= 0x6500,
+};
+
+enum scsi_descriptor_types {
+	scsi_sense_information			= 0x0,
+	scsi_sense_command_specific_information	= 0x1,
+	scsi_sense_key_specific			= 0x2,
+	scsi_sense_field_replaceable_unit	= 0x3,
+	scsi_sense_stream_commands		= 0x4,
+	scsi_sense_block_commands		= 0x5,
+	osd_sense_object_identification		= 0x6,
+	osd_sense_response_integrity_check	= 0x7,
+	osd_sense_attribute_identification	= 0x8,
+	scsi_sense_ata_return			= 0x9,
+
+	scsi_sense_Reserved_first		= 0x0A,
+	scsi_sense_Reserved_last		= 0x7F,
+	scsi_sense_Vendor_specific_first	= 0x80,
+	scsi_sense_Vendor_specific_last		= 0xFF,
+};
+
+struct scsi_sense_descriptor { /* for picking into desc type */
+	u8	descriptor_type; /* one of enum scsi_descriptor_types */
+	u8	additional_length; /* n - 1 */
+	u8	data[];
+} __packed;
+
+/* OSD deploys only scsi descriptor_based sense buffers */
+struct scsi_sense_descriptor_based {
+/*0*/	u8 	response_code; /* 0x72 or 0x73 */
+/*1*/	u8 	sense_key; /* one of enum scsi_sense_keys (4 lower bits) */
+/*2*/	__be16	additional_sense_code; /* enum osd_additional_sense_codes */
+/*4*/	u8	Reserved[3];
+/*7*/	u8	additional_sense_length; /* n - 7 */
+/*8*/	struct	scsi_sense_descriptor ssd[0]; /* variable length, 1 or more */
+} __packed;
+
+/* some descriptors deployed by OSD */
+
+/* SPC3r23 4.5.2.3 Command-specific information sense data descriptor */
+/* Note: this is the same for descriptor_type=00 but with type=00 the
+ *        Reserved[0] == 0x80 (ie. bit-7 set)
+ */
+struct scsi_sense_command_specific_data_descriptor {
+/*0*/	u8	descriptor_type; /* (00h/01h) */
+/*1*/	u8	additional_length; /* (0Ah) */
+/*2*/	u8	Reserved[2];
+/*4*/	__be64  information;
+} __packed;
+/*12*/
+
+struct scsi_sense_key_specific_data_descriptor {
+/*0*/	u8	descriptor_type; /* (02h) */
+/*1*/	u8	additional_length; /* (06h) */
+/*2*/	u8	Reserved[2];
+/* SKSV, C/D, Reserved (2), BPV, BIT POINTER (3) */
+/*4*/	u8	sksv_cd_bpv_bp;
+/*5*/	__be16	value; /* field-pointer/progress-value/retry-count/... */
+/*7*/	u8	Reserved2;
+} __packed;
+/*8*/
+
+/* 4.16.2.1 OSD error identification sense data descriptor - table 52 */
+/* Note: these bits are defined LE order for easy definition, this way the BIT()
+ * number is the same as in the documentation. Below members at
+ * osd_sense_identification_data_descriptor are therefore defined __le32.
+ */
+enum osd_command_functions_bits {
+	OSD_CFB_COMMAND		 = BIT(4),
+	OSD_CFB_CMD_CAP_VERIFIED = BIT(5),
+	OSD_CFB_VALIDATION	 = BIT(7),
+	OSD_CFB_IMP_ST_ATT	 = BIT(12),
+	OSD_CFB_SET_ATT		 = BIT(20),
+	OSD_CFB_SA_CAP_VERIFIED	 = BIT(21),
+	OSD_CFB_GET_ATT		 = BIT(28),
+	OSD_CFB_GA_CAP_VERIFIED	 = BIT(29),
+};
+
+struct osd_sense_identification_data_descriptor {
+/*0*/	u8	descriptor_type; /* (06h) */
+/*1*/	u8	additional_length; /* (1Eh) */
+/*2*/	u8	Reserved[6];
+/*8*/	__le32	not_initiated_functions; /*osd_command_functions_bits*/
+/*12*/	__le32	completed_functions; /*osd_command_functions_bits*/
+/*16*/ 	__be64	partition_id;
+/*24*/	__be64	object_id;
+} __packed;
+/*32*/
+
+struct osd_sense_response_integrity_check_descriptor {
+/*0*/	u8	descriptor_type; /* (07h) */
+/*1*/	u8	additional_length; /* (20h) */
+/*2*/	u8	integrity_check_value[32]; /*FIXME: OSDv2_CRYPTO_KEYID_SIZE*/
+} __packed;
+/*34*/
+
+struct osd_sense_attributes_data_descriptor {
+/*0*/	u8	descriptor_type; /* (08h) */
+/*1*/	u8	additional_length; /* (n-2) */
+/*2*/	u8	Reserved[6];
+	struct osd_sense_attr {
+/*8*/		__be32	page;
+/*12*/		__be32	attr;
+/*16*/	} sense_attrs[0]; /* 1 or more */
+} __packed;
+/*variable*/
+
+/* Dig into scsi_sk_illegal_request/scsi_invalid_field_in_cdb errors */
+
+/*FIXME: Support also field in CAPS*/
+#define OSD_CDB_OFFSET(F) offsetof(struct osd_cdb_head, F)
+
+enum osdv2_cdb_field_offset {
+	OSDv1_CFO_STARTING_BYTE	= OSD_CDB_OFFSET(v1.start_address),
+	OSD_CFO_STARTING_BYTE	= OSD_CDB_OFFSET(v2.start_address),
+	OSD_CFO_PARTITION_ID	= OSD_CDB_OFFSET(partition),
+	OSD_CFO_OBJECT_ID	= OSD_CDB_OFFSET(object),
+};
+
+#endif /* ndef __OSD_SENSE_H__ */
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 15/18] libosd: SCSI/OSD Sense decoding support
@ 2008-12-22 13:13     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:13 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Implementation of the osd_req_decode_sense() API. Can be called by
library users to decode what failed in command executions.

Add SCSI_OSD_DPRINT_SENSE Kconfig variable. Possible values are:
0 - Do not print any errors to messages file <KERN_ERR>
1 - (Default) Print only decoded errors that are not recoverable.
    Recoverable errors are those that the target has complied with
    the request but with a warning. For example read passed end of
    object will return zeros after the last valid byte.
2- Print all errors.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/osd/Kbuild          |    6 +
 drivers/scsi/osd/osd_initiator.c |  188 +++++++++++++++++++++++++++
 include/scsi/osd_initiator.h     |   49 +++++++
 include/scsi/osd_sense.h         |  260 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 503 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_sense.h

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index 6fb823f..29f7ddd 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -20,6 +20,12 @@ ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
 CONFIG_SCSI_OSD_ULD=m
 ccflags-y += -DCONFIG_SCSI_OSD_ULD -DCONFIG_SCSI_OSD_ULD_MODULE
 
+# CONFIG_SCSI_OSD_DPRINT_SENSE =
+#	0 - no print of errors
+#	1 - print errors
+#	2 - errors + warrnings
+ccflags-y += -DCONFIG_SCSI_OSD_DPRINT_SENSE=1
+
 # Uncomment to turn debug on
 # ccflags-y += -DCONFIG_SCSI_OSD_DEBUG
 
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 977d595..4c663d7 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -42,6 +42,8 @@
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
 #include <scsi/osd_attributes.h>
+#include <scsi/osd_sense.h>
+
 #include <scsi/scsi_device.h>
 
 #include "osd_debug.h"
@@ -1334,6 +1336,192 @@ int osd_finalize_request(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_finalize_request);
 
+#define OSD_SENSE_PRINT1(fmt, a...) \
+	do { \
+		if (__cur_sense_need_output) \
+			OSD_ERR(fmt, ##a); \
+	} while (0)
+
+#define OSD_SENSE_PRINT2(fmt, a...) OSD_SENSE_PRINT1("    " fmt, ##a)
+
+int osd_req_decode_sense_full(struct osd_request *or,
+	struct osd_sense_info *osi, bool silent,
+	struct osd_obj_id *bad_obj_list, int max_obj,
+	struct osd_attr *bad_attr_list, int max_attr)
+{
+	int sense_len, original_sense_len;
+	struct osd_sense_info local_osi;
+	struct scsi_sense_descriptor_based *ssdb;
+	void *cur_descriptor;
+#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 0)
+	const bool __cur_sense_need_output = false;
+#else
+	bool __cur_sense_need_output = !silent;
+#endif
+
+	if (!or->request->errors)
+		return 0;
+
+	ssdb = or->request->sense;
+	sense_len = or->request->sense_len;
+	if ((sense_len < sizeof(*ssdb) || !ssdb->sense_key)) {
+		OSD_ERR("Block-layer returned error(%x) but sense is empty\n",
+			or->request->errors);
+		return 0;
+	}
+
+	if ((ssdb->response_code != 0x72) && (ssdb->response_code != 0x73)) {
+		OSD_ERR("Unrecognized scsi sense: rcode=%x length=%d\n",
+			ssdb->response_code, sense_len);
+		return -EIO;
+	}
+
+	osi = osi ? : &local_osi;
+	memset(osi, 0, sizeof(*osi));
+	osi->key = ssdb->sense_key;
+	osi->additional_code = be16_to_cpu(ssdb->additional_sense_code);
+	original_sense_len = ssdb->additional_sense_length + 8;
+
+#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 1)
+	if (__cur_sense_need_output)
+		__cur_sense_need_output = (osi->key > scsi_sk_recovered_error);
+#endif
+	OSD_SENSE_PRINT1("Main Sense information key=0x%x length(%d, %d) "
+			"additional_code=0x%x\n",
+			osi->key, original_sense_len, sense_len,
+			osi->additional_code);
+
+	if (original_sense_len < sense_len)
+		sense_len = original_sense_len;
+
+	cur_descriptor = ssdb->ssd;
+	sense_len -= sizeof(*ssdb);
+	while (sense_len > 0) {
+		struct scsi_sense_descriptor *ssd = cur_descriptor;
+		int cur_len = ssd->additional_length + 2;
+
+		sense_len -= cur_len;
+
+		if (sense_len < 0)
+			break; /* sense was truncated */
+
+		switch (ssd->descriptor_type) {
+		case scsi_sense_information:
+		case scsi_sense_command_specific_information:
+		{
+			struct scsi_sense_command_specific_data_descriptor
+				*sscd = cur_descriptor;
+
+			osi->command_info =
+				get_unaligned_be64(&sscd->information) ;
+			OSD_SENSE_PRINT2(
+				"command_specific_information 0x%llx \n",
+				_LLU(osi->command_info));
+			break;
+		}
+		case scsi_sense_key_specific:
+		{
+			struct scsi_sense_key_specific_data_descriptor
+				*ssks = cur_descriptor;
+
+			osi->sense_info = get_unaligned_be16(&ssks->value);
+			OSD_SENSE_PRINT2(
+				"sense_key_specific_information %u"
+				"sksv_cd_bpv_bp (0x%x)\n",
+				osi->sense_info, ssks->sksv_cd_bpv_bp);
+			break;
+		}
+		case osd_sense_object_identification:
+		{ /*FIXME: Keep first not last, Store in array*/
+			struct osd_sense_identification_data_descriptor
+				*osidd = cur_descriptor;
+
+			osi->not_initiated_command_functions =
+				le32_to_cpu(osidd->not_initiated_functions);
+			osi->completed_command_functions =
+				le32_to_cpu(osidd->completed_functions);
+			osi->obj.partition = be64_to_cpu(osidd->partition_id);
+			osi->obj.id = be64_to_cpu(osidd->object_id);
+			OSD_SENSE_PRINT2(
+				"object_identification pid=0x%llx oid=0x%llx\n",
+				_LLU(osi->obj.partition), _LLU(osi->obj.id));
+			OSD_SENSE_PRINT2(
+				"not_initiated_bits(%x) "
+				"completed_command_bits(%x)\n",
+				osi->not_initiated_command_functions,
+				osi->completed_command_functions);
+			break;
+		}
+		case osd_sense_response_integrity_check:
+		{
+			struct osd_sense_response_integrity_check_descriptor
+				*osricd = cur_descriptor;
+			const int len = sizeof(osricd->integrity_check_value);
+			u8 key_dump[len*4 + 2]; /* 2nibbles+space+ASCII */
+
+			hex_dump_to_buffer(osricd->integrity_check_value, len,
+				       32, 1, key_dump, sizeof(key_dump), true);
+			OSD_SENSE_PRINT2("response_integrity [%s]\n", key_dump);
+		}
+		case osd_sense_attribute_identification:
+		{
+			struct osd_sense_attributes_data_descriptor
+				*osadd = cur_descriptor;
+			int len = min(cur_len, sense_len);
+			int i = 0;
+			struct osd_sense_attr *pattr = osadd->sense_attrs;
+
+			while (len < 0) {
+				u32 page = be32_to_cpu(pattr->page);
+				u32 attr = be32_to_cpu(pattr->attr);
+
+				if (i++ == 0) {
+					osi->attr.page = page;
+					osi->attr.attr_id = attr;
+				}
+
+				if (bad_attr_list && max_attr) {
+					bad_attr_list->page = page;
+					bad_attr_list->attr_id = attr;
+					bad_attr_list++;
+					max_attr--;
+				}
+				OSD_SENSE_PRINT2(
+					"osd_sense_attribute_identification"
+					"page=0x%x attr=0x%x\n", page, attr);
+			}
+		}
+		/*These are not legal for OSD*/
+		case scsi_sense_field_replaceable_unit:
+			OSD_SENSE_PRINT2("scsi_sense_field_replaceable_unit\n");
+			break;
+		case scsi_sense_stream_commands:
+			OSD_SENSE_PRINT2("scsi_sense_stream_commands\n");
+			break;
+		case scsi_sense_block_commands:
+			OSD_SENSE_PRINT2("scsi_sense_block_commands\n");
+			break;
+		case scsi_sense_ata_return:
+			OSD_SENSE_PRINT2("scsi_sense_ata_return\n");
+			break;
+		default:
+			if (ssd->descriptor_type <= scsi_sense_Reserved_last)
+				OSD_SENSE_PRINT2(
+					"scsi_sense Reserved descriptor (0x%x)",
+					ssd->descriptor_type);
+			else
+				OSD_SENSE_PRINT2(
+					"scsi_sense Vendor descriptor (0x%x)",
+					ssd->descriptor_type);
+		}
+
+		cur_descriptor += cur_len;
+	}
+
+	return (osi->key > scsi_sk_recovered_error) ? -EIO : 0;
+}
+EXPORT_SYMBOL(osd_req_decode_sense_full);
+
 /*
  * Implementation of osd_sec.h API
  * TODO: Move to a separate osd_sec.c file at a later stage.
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 8a0fd35..83b6976 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -212,6 +212,55 @@ int osd_execute_request_async(struct osd_request *or,
 	osd_req_done_fn *done, void *private);
 
 /**
+ * osd_req_decode_sense_full - Decode sense information after execution.
+ *
+ * @or:           - osd_request to examine
+ * @osi           - Recievs a more detailed error report information (optional).
+ * @silent        - Do not print to dmsg (Even if enabled)
+ * @bad_obj_list  - Some commands act on multiple objects. Failed objects will
+ *                  be recieved here (optional)
+ * @max_obj       - Size of @bad_obj_list.
+ * @bad_attr_list - List of failing attributes (optional)
+ * @max_attr      - Size of @bad_attr_list.
+ *
+ * After execution, sense + return code can be analyzed using this function. The
+ * return code is the final disposition on the error. So it is possible that a
+ * CHECK_CONDITION was returned from target but this will return NO_ERROR, for
+ * example on recovered errors. All parameters are optional if caller does
+ * not need any returned information.
+ * Note: This function will also dump the error to dmsg according to settings
+ * of the SCSI_OSD_DPRINT_SENSE Kconfig value. Set @silent if you know the
+ * command would routinely fail, to not spam the dmsg file.
+ */
+struct osd_sense_info {
+	int key;		/* one of enum scsi_sense_keys */
+	int additional_code ;	/* enum osd_additional_sense_codes */
+	union { /* Sense specific information */
+		u16 sense_info;
+		u16 cdb_field_offset; 	/* scsi_invalid_field_in_cdb */
+	};
+	union { /* Command specific information */
+		u64 command_info;
+	};
+
+	u32 not_initiated_command_functions; /* osd_command_functions_bits */
+	u32 completed_command_functions; /* osd_command_functions_bits */
+	struct osd_obj_id obj;
+	struct osd_attr attr;
+};
+
+int osd_req_decode_sense_full(struct osd_request *or,
+	struct osd_sense_info *osi, bool silent,
+	struct osd_obj_id *bad_obj_list, int max_obj,
+	struct osd_attr *bad_attr_list, int max_attr);
+
+static inline int osd_req_decode_sense(struct osd_request *or,
+	struct osd_sense_info *osi)
+{
+	return osd_req_decode_sense_full(or, osi, false, NULL, 0, NULL, 0);
+}
+
+/**
  * osd_end_request - return osd_request to free store
  *
  * @or:		osd_request to free
diff --git a/include/scsi/osd_sense.h b/include/scsi/osd_sense.h
new file mode 100644
index 0000000..026d07e
--- /dev/null
+++ b/include/scsi/osd_sense.h
@@ -0,0 +1,260 @@
+/*
+ * osd_sense.h - OSD Related sense handling definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_SENSE_H__
+#define __OSD_SENSE_H__
+
+#include <scsi/osd_protocol.h>
+
+/* SPC3r23 4.5.6 Sense key and sense code definitions table 27 */
+enum scsi_sense_keys {
+	scsi_sk_no_sense        = 0x0,
+	scsi_sk_recovered_error = 0x1,
+	scsi_sk_not_ready       = 0x2,
+	scsi_sk_medium_error    = 0x3,
+	scsi_sk_hardware_error  = 0x4,
+	scsi_sk_illegal_request = 0x5,
+	scsi_sk_unit_attention  = 0x6,
+	scsi_sk_data_protect    = 0x7,
+	scsi_sk_blank_check     = 0x8,
+	scsi_sk_vendor_specific = 0x9,
+	scsi_sk_copy_aborted    = 0xa,
+	scsi_sk_aborted_command = 0xb,
+	scsi_sk_volume_overflow = 0xd,
+	scsi_sk_miscompare      = 0xe,
+	scsi_sk_reserved        = 0xf,
+};
+
+/* SPC3r23 4.5.6 Sense key and sense code definitions table 28 */
+/* Note: only those which can be returned by an OSD target. Most of
+ *       these errors are taken care of by the generic scsi layer.
+ */
+enum osd_additional_sense_codes {
+	scsi_no_additional_sense_information			= 0x0000,
+	scsi_operation_in_progress				= 0x0016,
+	scsi_cleaning_requested					= 0x0017,
+	scsi_lunr_cause_not_reportable				= 0x0400,
+	scsi_logical_unit_is_in_process_of_becoming_ready	= 0x0401,
+	scsi_lunr_initializing_command_required			= 0x0402,
+	scsi_lunr_manual_intervention_required			= 0x0403,
+	scsi_lunr_operation_in_progress				= 0x0407,
+	scsi_lunr_selftest_in_progress				= 0x0409,
+	scsi_luna_asymmetric_access_state_transition		= 0x040a,
+	scsi_luna_target_port_in_standby_state			= 0x040b,
+	scsi_luna_target_port_in_unavailable_state		= 0x040c,
+	scsi_lunr_notify_enable_spinup_required			= 0x0411,
+	scsi_logical_unit_does_not_respond_to_selection		= 0x0500,
+	scsi_logical_unit_communication_failure			= 0x0800,
+	scsi_logical_unit_communication_timeout			= 0x0801,
+	scsi_logical_unit_communication_parity_error		= 0x0802,
+	scsi_error_log_overflow					= 0x0a00,
+	scsi_warning						= 0x0b00,
+	scsi_warning_specified_temperature_exceeded		= 0x0b01,
+	scsi_warning_enclosure_degraded				= 0x0b02,
+	scsi_write_error_unexpected_unsolicited_data		= 0x0c0c,
+	scsi_write_error_not_enough_unsolicited_data		= 0x0c0d,
+	scsi_invalid_information_unit				= 0x0e00,
+	scsi_invalid_field_in_command_information_unit		= 0x0e03,
+	scsi_read_error_failed_retransmission_request		= 0x1113,
+	scsi_parameter_list_length_error			= 0x1a00,
+	scsi_invalid_command_operation_code			= 0x2000,
+	scsi_invalid_field_in_cdb				= 0x2400,
+	osd_security_audit_value_frozen				= 0x2404,
+	osd_security_working_key_frozen				= 0x2405,
+	osd_nonce_not_unique					= 0x2406,
+	osd_nonce_timestamp_out_of_range			= 0x2407,
+	scsi_logical_unit_not_supported				= 0x2500,
+	scsi_invalid_field_in_parameter_list			= 0x2600,
+	scsi_parameter_not_supported				= 0x2601,
+	scsi_parameter_value_invalid				= 0x2602,
+	scsi_invalid_release_of_persistent_reservation		= 0x2604,
+	osd_invalid_dataout_buffer_integrity_check_value	= 0x260f,
+	scsi_not_ready_to_ready_change_medium_may_have_changed	= 0x2800,
+	scsi_power_on_reset_or_bus_device_reset_occurred	= 0x2900,
+	scsi_power_on_occurred					= 0x2901,
+	scsi_scsi_bus_reset_occurred				= 0x2902,
+	scsi_bus_device_reset_function_occurred			= 0x2903,
+	scsi_device_internal_reset				= 0x2904,
+	scsi_transceiver_mode_changed_to_single_ended		= 0x2905,
+	scsi_transceiver_mode_changed_to_lvd			= 0x2906,
+	scsi_i_t_nexus_loss_occurred				= 0x2907,
+	scsi_parameters_changed					= 0x2a00,
+	scsi_mode_parameters_changed				= 0x2a01,
+	scsi_asymmetric_access_state_changed			= 0x2a06,
+	scsi_priority_changed					= 0x2a08,
+	scsi_command_sequence_error				= 0x2c00,
+	scsi_previous_busy_status				= 0x2c07,
+	scsi_previous_task_set_full_status			= 0x2c08,
+	scsi_previous_reservation_conflict_status		= 0x2c09,
+	osd_partition_or_collection_contains_user_objects	= 0x2c0a,
+	scsi_commands_cleared_by_another_initiator		= 0x2f00,
+	scsi_cleaning_failure					= 0x3007,
+	scsi_enclosure_failure					= 0x3400,
+	scsi_enclosure_services_failure				= 0x3500,
+	scsi_unsupported_enclosure_function			= 0x3501,
+	scsi_enclosure_services_unavailable			= 0x3502,
+	scsi_enclosure_services_transfer_failure		= 0x3503,
+	scsi_enclosure_services_transfer_refused		= 0x3504,
+	scsi_enclosure_services_checksum_error			= 0x3505,
+	scsi_rounded_parameter					= 0x3700,
+	osd_read_past_end_of_user_object			= 0x3b17,
+	scsi_logical_unit_has_not_self_configured_yet		= 0x3e00,
+	scsi_logical_unit_failure				= 0x3e01,
+	scsi_timeout_on_logical_unit				= 0x3e02,
+	scsi_logical_unit_failed_selftest			= 0x3e03,
+	scsi_logical_unit_unable_to_update_selftest_log		= 0x3e04,
+	scsi_target_operating_conditions_have_changed		= 0x3f00,
+	scsi_microcode_has_been_changed				= 0x3f01,
+	scsi_inquiry_data_has_changed				= 0x3f03,
+	scsi_echo_buffer_overwritten				= 0x3f0f,
+	scsi_diagnostic_failure_on_component_nn_first		= 0x4080,
+	scsi_diagnostic_failure_on_component_nn_last		= 0x40ff,
+	scsi_message_error					= 0x4300,
+	scsi_internal_target_failure				= 0x4400,
+	scsi_select_or_reselect_failure				= 0x4500,
+	scsi_scsi_parity_error					= 0x4700,
+	scsi_data_phase_crc_error_detected			= 0x4701,
+	scsi_scsi_parity_error_detected_during_st_data_phase	= 0x4702,
+	scsi_asynchronous_information_protection_error_detected	= 0x4704,
+	scsi_protocol_service_crc_error				= 0x4705,
+	scsi_phy_test_function_in_progress			= 0x4706,
+	scsi_invalid_message_error				= 0x4900,
+	scsi_command_phase_error				= 0x4a00,
+	scsi_data_phase_error					= 0x4b00,
+	scsi_logical_unit_failed_self_configuration		= 0x4c00,
+	scsi_overlapped_commands_attempted			= 0x4e00,
+	osd_quota_error						= 0x5507,
+	scsi_failure_prediction_threshold_exceeded		= 0x5d00,
+	scsi_failure_prediction_threshold_exceeded_false	= 0x5dff,
+	scsi_voltage_fault					= 0x6500,
+};
+
+enum scsi_descriptor_types {
+	scsi_sense_information			= 0x0,
+	scsi_sense_command_specific_information	= 0x1,
+	scsi_sense_key_specific			= 0x2,
+	scsi_sense_field_replaceable_unit	= 0x3,
+	scsi_sense_stream_commands		= 0x4,
+	scsi_sense_block_commands		= 0x5,
+	osd_sense_object_identification		= 0x6,
+	osd_sense_response_integrity_check	= 0x7,
+	osd_sense_attribute_identification	= 0x8,
+	scsi_sense_ata_return			= 0x9,
+
+	scsi_sense_Reserved_first		= 0x0A,
+	scsi_sense_Reserved_last		= 0x7F,
+	scsi_sense_Vendor_specific_first	= 0x80,
+	scsi_sense_Vendor_specific_last		= 0xFF,
+};
+
+struct scsi_sense_descriptor { /* for picking into desc type */
+	u8	descriptor_type; /* one of enum scsi_descriptor_types */
+	u8	additional_length; /* n - 1 */
+	u8	data[];
+} __packed;
+
+/* OSD deploys only scsi descriptor_based sense buffers */
+struct scsi_sense_descriptor_based {
+/*0*/	u8 	response_code; /* 0x72 or 0x73 */
+/*1*/	u8 	sense_key; /* one of enum scsi_sense_keys (4 lower bits) */
+/*2*/	__be16	additional_sense_code; /* enum osd_additional_sense_codes */
+/*4*/	u8	Reserved[3];
+/*7*/	u8	additional_sense_length; /* n - 7 */
+/*8*/	struct	scsi_sense_descriptor ssd[0]; /* variable length, 1 or more */
+} __packed;
+
+/* some descriptors deployed by OSD */
+
+/* SPC3r23 4.5.2.3 Command-specific information sense data descriptor */
+/* Note: this is the same for descriptor_type=00 but with type=00 the
+ *        Reserved[0] == 0x80 (ie. bit-7 set)
+ */
+struct scsi_sense_command_specific_data_descriptor {
+/*0*/	u8	descriptor_type; /* (00h/01h) */
+/*1*/	u8	additional_length; /* (0Ah) */
+/*2*/	u8	Reserved[2];
+/*4*/	__be64  information;
+} __packed;
+/*12*/
+
+struct scsi_sense_key_specific_data_descriptor {
+/*0*/	u8	descriptor_type; /* (02h) */
+/*1*/	u8	additional_length; /* (06h) */
+/*2*/	u8	Reserved[2];
+/* SKSV, C/D, Reserved (2), BPV, BIT POINTER (3) */
+/*4*/	u8	sksv_cd_bpv_bp;
+/*5*/	__be16	value; /* field-pointer/progress-value/retry-count/... */
+/*7*/	u8	Reserved2;
+} __packed;
+/*8*/
+
+/* 4.16.2.1 OSD error identification sense data descriptor - table 52 */
+/* Note: these bits are defined LE order for easy definition, this way the BIT()
+ * number is the same as in the documentation. Below members at
+ * osd_sense_identification_data_descriptor are therefore defined __le32.
+ */
+enum osd_command_functions_bits {
+	OSD_CFB_COMMAND		 = BIT(4),
+	OSD_CFB_CMD_CAP_VERIFIED = BIT(5),
+	OSD_CFB_VALIDATION	 = BIT(7),
+	OSD_CFB_IMP_ST_ATT	 = BIT(12),
+	OSD_CFB_SET_ATT		 = BIT(20),
+	OSD_CFB_SA_CAP_VERIFIED	 = BIT(21),
+	OSD_CFB_GET_ATT		 = BIT(28),
+	OSD_CFB_GA_CAP_VERIFIED	 = BIT(29),
+};
+
+struct osd_sense_identification_data_descriptor {
+/*0*/	u8	descriptor_type; /* (06h) */
+/*1*/	u8	additional_length; /* (1Eh) */
+/*2*/	u8	Reserved[6];
+/*8*/	__le32	not_initiated_functions; /*osd_command_functions_bits*/
+/*12*/	__le32	completed_functions; /*osd_command_functions_bits*/
+/*16*/ 	__be64	partition_id;
+/*24*/	__be64	object_id;
+} __packed;
+/*32*/
+
+struct osd_sense_response_integrity_check_descriptor {
+/*0*/	u8	descriptor_type; /* (07h) */
+/*1*/	u8	additional_length; /* (20h) */
+/*2*/	u8	integrity_check_value[32]; /*FIXME: OSDv2_CRYPTO_KEYID_SIZE*/
+} __packed;
+/*34*/
+
+struct osd_sense_attributes_data_descriptor {
+/*0*/	u8	descriptor_type; /* (08h) */
+/*1*/	u8	additional_length; /* (n-2) */
+/*2*/	u8	Reserved[6];
+	struct osd_sense_attr {
+/*8*/		__be32	page;
+/*12*/		__be32	attr;
+/*16*/	} sense_attrs[0]; /* 1 or more */
+} __packed;
+/*variable*/
+
+/* Dig into scsi_sk_illegal_request/scsi_invalid_field_in_cdb errors */
+
+/*FIXME: Support also field in CAPS*/
+#define OSD_CDB_OFFSET(F) offsetof(struct osd_cdb_head, F)
+
+enum osdv2_cdb_field_offset {
+	OSDv1_CFO_STARTING_BYTE	= OSD_CDB_OFFSET(v1.start_address),
+	OSD_CFO_STARTING_BYTE	= OSD_CDB_OFFSET(v2.start_address),
+	OSD_CFO_PARTITION_ID	= OSD_CDB_OFFSET(partition),
+	OSD_CFO_OBJECT_ID	= OSD_CDB_OFFSET(object),
+};
+
+#endif /* ndef __OSD_SENSE_H__ */
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 16/18] osd: Documentation for OSD library
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 13:16     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:16 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Add osd.txt to Documentation/scsi/

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 Documentation/scsi/osd.txt |  198 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 198 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/scsi/osd.txt

diff --git a/Documentation/scsi/osd.txt b/Documentation/scsi/osd.txt
new file mode 100644
index 0000000..da162f7
--- /dev/null
+++ b/Documentation/scsi/osd.txt
@@ -0,0 +1,198 @@
+The OSD Standard
+================
+OSD (Object-Based Storage Device) is a T10 SCSI command set that is designed
+to provide efficient operation of input/output logical units that manage the
+allocation, placement, and accessing of variable-size data-storage containers,
+called objects. Objects are intended to contain operating system and application
+constructs. Each object has associated attributes attached to it, which are
+integral part of the object and provide metadata about the object. The standard
+defines some common obligatory attributes, but user attributes can be added as
+needed.
+
+See: http://www.t10.org/ftp/t10/drafts/osd2/ for the latest draft for OSD 2
+or search the web for "OSD SCSI"
+
+OSD in the Linux Kernel
+=======================
+osd-initiator:
+  The main component of OSD in Kernel is the osd-initiator library. Its main
+user is intended to be the pNFS-over-objects layout driver, which uses objects
+as its back-end data storage. Other clients are the other osd parts listed below.
+
+osd-uld:
+  This is a SCSI ULD that registers for OSD type devices and provides a testing
+platform, both for the in-kernel initiator as well as connected targets. It
+currently has no useful user-mode API, though it could have if need be.
+
+exofs:
+  Is an OSD based Linux file system. It uses the osd-initiator and osd-uld,
+to export a usable file system for users.
+See Documentation/filesystems/exofs.txt for more details
+
+osd target:
+  There are no current plans for an OSD target implementation in kernel. For all
+needs, a user-mode target that is based on the scsi tgt target framework is
+available from Ohio Supercomputer Center (OSC) at:
+http://www.open-osd.org/bin/view/Main/OscOsdProject
+There are several other target implementations. See http://open-osd.org for more
+links.
+
+Files and Folders
+=================
+This is the complete list of files included in this work:
+include/scsi/
+	osd_initiator.h   Main API for the initiator library
+	osd_types.h	  Common OSD types
+	osd_sec.h	  Security Manager API
+	osd_protocol.h	  Wire definitions of the OSD standard protocol
+	osd_attributes.h  Wire definitions of OSD attributes
+
+drivers/scsi/osd/
+	osd_initiator.c   OSD-Initiator library implementation
+	osd_uld.c	  The OSD scsi ULD
+	osd_ktest.{h,c}	  In-kernel test suite (called by osd_uld)
+	osd_debug.h	  Some printk macros
+	Makefile	  For both in-tree and out-of-tree compilation
+	Kconfig		  Enables inclusion of the different pieces
+	osd_test.c	  User-mode application to call the kernel tests
+
+The OSD-Initiator Library
+=========================
+osd_initiator is a low level implementation of an osd initiator encoder.
+But even though, it should be intuitive and easy to use. Perhaps over time an
+higher lever will form that automates some of the more common recipes.
+
+init/fini:
+- osd_dev_init() associates a scsi_device with an osd_dev structure
+  and initializes some global pools. This should be done once per scsi_device
+  (OSD LUN). The osd_dev structure is needed for calling osd_start_request().
+
+- osd_dev_fini() cleans up before a osd_dev/scsi_device destruction.
+
+OSD commands encoding, execution, and decoding of results:
+
+struct osd_request's is used to iteratively encode an OSD command and carry
+its state throughout execution. Each request goes through these stages:
+
+a. osd_start_request() allocates the request.
+
+b. Any of the osd_req_* methods is used to encode a request of the specified
+   type.
+
+c. osd_req_add_{get,set}_attr_* may be called to add get/set attributes to the
+   CDB. "List" or "Page" mode can be used exclusively. The attribute-list API
+   can be called multiple times on the same request. However, only one
+   attribute-page can be read, as mandated by the OSD standard.
+
+d. osd_finalize_request() computes offsets into the data-in and data-out buffers
+   and signs the request using the provided capability key and integrity-
+   check parameters.
+
+e. osd_execute_request() may be called to execute the request via the block
+   layer and wait for its completion.  The request can be executed
+   asynchronously by calling the block layer API directly.
+
+f. After execution, osd_req_decode_sense() can be called to decode the request's
+   sense information.
+
+g. osd_req_decode_get_attr() may be called to retrieve osd_add_get_attr_list()
+   values.
+
+h. osd_end_request() must be called to deallocate the request and any resource
+   associated with it. Note that osd_end_request cleans up the request at any
+   stage and it must always be called after a successful osd_start_request().
+
+osd_request's structure:
+
+The OSD standard defines a complex structure of IO segments pointed to by
+members in the CDB. Up to 3 segments can be deployed in the IN-Buffer and up to
+4 in the OUT-Buffer. The ASCII illustration below depicts a secure-read with
+associated get+set of attributes-lists. Other combinations very on the same
+basic theme. From no-segments-used up to all-segments-used.
+
+|________OSD-CDB__________|
+|                         |
+|read_len (offset=0)     -|---------\
+|                         |         |
+|get_attrs_list_length    |         |
+|get_attrs_list_offset   -|----\    |
+|                         |    |    |
+|retrieved_attrs_alloc_len|    |    |
+|retrieved_attrs_offset  -|----|----|-\
+|                         |    |    | |
+|set_attrs_list_length    |    |    | |
+|set_attrs_list_offset   -|-\  |    | |
+|                         | |  |    | |
+|in_data_integ_offset    -|-|--|----|-|-\
+|out_data_integ_offset   -|-|--|--\ | | |
+\_________________________/ |  |  | | | |
+                            |  |  | | | |
+|_______OUT-BUFFER________| |  |  | | | |
+|      Set attr list      |</  |  | | | |
+|                         |    |  | | | |
+|-------------------------|    |  | | | |
+|   Get attr descriptors  |<---/  | | | |
+|                         |       | | | |
+|-------------------------|       | | | |
+|    Out-data integrity   |<------/ | | |
+|                         |         | | |
+\_________________________/         | | |
+                                    | | |
+|________IN-BUFFER________|         | | |
+|      In-Data read       |<--------/ | |
+|                         |           | |
+|-------------------------|           | |
+|      Get attr list      |<----------/ |
+|                         |             |
+|-------------------------|             |
+|    In-data integrity    |<------------/
+|                         |
+\_________________________/
+
+A block device request can carry bidirectional payload by means of associating
+a bidi_read request with a main write-request. Each in/out request is described
+by a chain of BIOs associated with each request.
+The CDB is of a SCSI VARLEN CDB format, as described by OSD standard.
+The OSD standard also mandates alignment restrictions at start of each segment.
+
+In the code, in struct osd_request, there are two _osd_io_info structures to
+describe the IN/OUT buffers above, two BIOs for the data payload and up to five
+_osd_req_data_segment structures to hold the different segments allocation and
+information.
+
+Important: We have chosen to disregard the assumption that a BIO-chain (and
+the resulting sg-list) describes a linear memory buffer. Meaning only first and
+last scatter chain can be incomplete and all the middle chains are of PAGE_SIZE.
+For us, a scatter-gather-list, as its name implies and as used by the Networking
+layer, is to describe a vector of buffers that will be transferred to/from the
+wire. It works very well with current iSCSI transport. iSCSI is currently the
+only deployed OSD transport. In the future we anticipate SAS and FC attached OSD
+devices as well.
+
+The OSD Testing ULD
+===================
+TODO: More user-mode control on tests.
+
+Authors, Mailing list
+=====================
+Please communicate with us on any deployment of osd, whether using this code
+or not.
+
+Any problems, questions, bug reports, lonely OSD nights, please email:
+   OSD Dev List <osd-dev@open-osd.org>
+
+More up-to-date information can be found on:
+http://open-osd.org
+
+Boaz Harrosh <bharrosh@panasas.com>
+Benny Halevy <bhalevy@panasas.com>
+
+References
+==========
+Weber, R., "SCSI Object-Based Storage Device Commands",
+T10/1355-D ANSI/INCITS 400-2004,
+http://www.t10.org/ftp/t10/drafts/osd/osd-r10.pdf
+
+Weber, R., "SCSI Object-Based Storage Device Commands -2 (OSD-2)"
+T10/1729-D, Working Draft, rev. 3
+http://www.t10.org/ftp/t10/drafts/osd2/osd2r03.pdf
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 16/18] osd: Documentation for OSD library
@ 2008-12-22 13:16     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:16 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Add osd.txt to Documentation/scsi/

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 Documentation/scsi/osd.txt |  198 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 198 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/scsi/osd.txt

diff --git a/Documentation/scsi/osd.txt b/Documentation/scsi/osd.txt
new file mode 100644
index 0000000..da162f7
--- /dev/null
+++ b/Documentation/scsi/osd.txt
@@ -0,0 +1,198 @@
+The OSD Standard
+================
+OSD (Object-Based Storage Device) is a T10 SCSI command set that is designed
+to provide efficient operation of input/output logical units that manage the
+allocation, placement, and accessing of variable-size data-storage containers,
+called objects. Objects are intended to contain operating system and application
+constructs. Each object has associated attributes attached to it, which are
+integral part of the object and provide metadata about the object. The standard
+defines some common obligatory attributes, but user attributes can be added as
+needed.
+
+See: http://www.t10.org/ftp/t10/drafts/osd2/ for the latest draft for OSD 2
+or search the web for "OSD SCSI"
+
+OSD in the Linux Kernel
+=======================
+osd-initiator:
+  The main component of OSD in Kernel is the osd-initiator library. Its main
+user is intended to be the pNFS-over-objects layout driver, which uses objects
+as its back-end data storage. Other clients are the other osd parts listed below.
+
+osd-uld:
+  This is a SCSI ULD that registers for OSD type devices and provides a testing
+platform, both for the in-kernel initiator as well as connected targets. It
+currently has no useful user-mode API, though it could have if need be.
+
+exofs:
+  Is an OSD based Linux file system. It uses the osd-initiator and osd-uld,
+to export a usable file system for users.
+See Documentation/filesystems/exofs.txt for more details
+
+osd target:
+  There are no current plans for an OSD target implementation in kernel. For all
+needs, a user-mode target that is based on the scsi tgt target framework is
+available from Ohio Supercomputer Center (OSC) at:
+http://www.open-osd.org/bin/view/Main/OscOsdProject
+There are several other target implementations. See http://open-osd.org for more
+links.
+
+Files and Folders
+=================
+This is the complete list of files included in this work:
+include/scsi/
+	osd_initiator.h   Main API for the initiator library
+	osd_types.h	  Common OSD types
+	osd_sec.h	  Security Manager API
+	osd_protocol.h	  Wire definitions of the OSD standard protocol
+	osd_attributes.h  Wire definitions of OSD attributes
+
+drivers/scsi/osd/
+	osd_initiator.c   OSD-Initiator library implementation
+	osd_uld.c	  The OSD scsi ULD
+	osd_ktest.{h,c}	  In-kernel test suite (called by osd_uld)
+	osd_debug.h	  Some printk macros
+	Makefile	  For both in-tree and out-of-tree compilation
+	Kconfig		  Enables inclusion of the different pieces
+	osd_test.c	  User-mode application to call the kernel tests
+
+The OSD-Initiator Library
+=========================
+osd_initiator is a low level implementation of an osd initiator encoder.
+But even though, it should be intuitive and easy to use. Perhaps over time an
+higher lever will form that automates some of the more common recipes.
+
+init/fini:
+- osd_dev_init() associates a scsi_device with an osd_dev structure
+  and initializes some global pools. This should be done once per scsi_device
+  (OSD LUN). The osd_dev structure is needed for calling osd_start_request().
+
+- osd_dev_fini() cleans up before a osd_dev/scsi_device destruction.
+
+OSD commands encoding, execution, and decoding of results:
+
+struct osd_request's is used to iteratively encode an OSD command and carry
+its state throughout execution. Each request goes through these stages:
+
+a. osd_start_request() allocates the request.
+
+b. Any of the osd_req_* methods is used to encode a request of the specified
+   type.
+
+c. osd_req_add_{get,set}_attr_* may be called to add get/set attributes to the
+   CDB. "List" or "Page" mode can be used exclusively. The attribute-list API
+   can be called multiple times on the same request. However, only one
+   attribute-page can be read, as mandated by the OSD standard.
+
+d. osd_finalize_request() computes offsets into the data-in and data-out buffers
+   and signs the request using the provided capability key and integrity-
+   check parameters.
+
+e. osd_execute_request() may be called to execute the request via the block
+   layer and wait for its completion.  The request can be executed
+   asynchronously by calling the block layer API directly.
+
+f. After execution, osd_req_decode_sense() can be called to decode the request's
+   sense information.
+
+g. osd_req_decode_get_attr() may be called to retrieve osd_add_get_attr_list()
+   values.
+
+h. osd_end_request() must be called to deallocate the request and any resource
+   associated with it. Note that osd_end_request cleans up the request at any
+   stage and it must always be called after a successful osd_start_request().
+
+osd_request's structure:
+
+The OSD standard defines a complex structure of IO segments pointed to by
+members in the CDB. Up to 3 segments can be deployed in the IN-Buffer and up to
+4 in the OUT-Buffer. The ASCII illustration below depicts a secure-read with
+associated get+set of attributes-lists. Other combinations very on the same
+basic theme. From no-segments-used up to all-segments-used.
+
+|________OSD-CDB__________|
+|                         |
+|read_len (offset=0)     -|---------\
+|                         |         |
+|get_attrs_list_length    |         |
+|get_attrs_list_offset   -|----\    |
+|                         |    |    |
+|retrieved_attrs_alloc_len|    |    |
+|retrieved_attrs_offset  -|----|----|-\
+|                         |    |    | |
+|set_attrs_list_length    |    |    | |
+|set_attrs_list_offset   -|-\  |    | |
+|                         | |  |    | |
+|in_data_integ_offset    -|-|--|----|-|-\
+|out_data_integ_offset   -|-|--|--\ | | |
+\_________________________/ |  |  | | | |
+                            |  |  | | | |
+|_______OUT-BUFFER________| |  |  | | | |
+|      Set attr list      |</  |  | | | |
+|                         |    |  | | | |
+|-------------------------|    |  | | | |
+|   Get attr descriptors  |<---/  | | | |
+|                         |       | | | |
+|-------------------------|       | | | |
+|    Out-data integrity   |<------/ | | |
+|                         |         | | |
+\_________________________/         | | |
+                                    | | |
+|________IN-BUFFER________|         | | |
+|      In-Data read       |<--------/ | |
+|                         |           | |
+|-------------------------|           | |
+|      Get attr list      |<----------/ |
+|                         |             |
+|-------------------------|             |
+|    In-data integrity    |<------------/
+|                         |
+\_________________________/
+
+A block device request can carry bidirectional payload by means of associating
+a bidi_read request with a main write-request. Each in/out request is described
+by a chain of BIOs associated with each request.
+The CDB is of a SCSI VARLEN CDB format, as described by OSD standard.
+The OSD standard also mandates alignment restrictions at start of each segment.
+
+In the code, in struct osd_request, there are two _osd_io_info structures to
+describe the IN/OUT buffers above, two BIOs for the data payload and up to five
+_osd_req_data_segment structures to hold the different segments allocation and
+information.
+
+Important: We have chosen to disregard the assumption that a BIO-chain (and
+the resulting sg-list) describes a linear memory buffer. Meaning only first and
+last scatter chain can be incomplete and all the middle chains are of PAGE_SIZE.
+For us, a scatter-gather-list, as its name implies and as used by the Networking
+layer, is to describe a vector of buffers that will be transferred to/from the
+wire. It works very well with current iSCSI transport. iSCSI is currently the
+only deployed OSD transport. In the future we anticipate SAS and FC attached OSD
+devices as well.
+
+The OSD Testing ULD
+===================
+TODO: More user-mode control on tests.
+
+Authors, Mailing list
+=====================
+Please communicate with us on any deployment of osd, whether using this code
+or not.
+
+Any problems, questions, bug reports, lonely OSD nights, please email:
+   OSD Dev List <osd-dev@open-osd.org>
+
+More up-to-date information can be found on:
+http://open-osd.org
+
+Boaz Harrosh <bharrosh@panasas.com>
+Benny Halevy <bhalevy@panasas.com>
+
+References
+==========
+Weber, R., "SCSI Object-Based Storage Device Commands",
+T10/1355-D ANSI/INCITS 400-2004,
+http://www.t10.org/ftp/t10/drafts/osd/osd-r10.pdf
+
+Weber, R., "SCSI Object-Based Storage Device Commands -2 (OSD-2)"
+T10/1729-D, Working Draft, rev. 3
+http://www.t10.org/ftp/t10/drafts/osd2/osd2r03.pdf
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 17/18] osd: Kconfig file for in-tree builds
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 13:18     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:18 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

Kconfig file for the drivers/scsi/osd subdirectory.
Adds the following config items:
	config SCSI_OSD_INITIATOR
	config SCSI_OSD_ULD
	config SCSI_OSD_DPRINT_SENSE
	config SCSI_OSD_DEBUG

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kconfig |   53 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 53 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kconfig

diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
new file mode 100644
index 0000000..861b5ce
--- /dev/null
+++ b/drivers/scsi/osd/Kconfig
@@ -0,0 +1,53 @@
+#
+# Kernel configuration file for the OSD scsi protocol
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public version 2 License as
+# published by the Free Software Foundation
+#
+# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
+#        How is it done properly?
+#
+
+config SCSI_OSD_INITIATOR
+	tristate "OSD-Initiator library"
+	depends on SCSI
+	help
+		Enable the OSD-Initiator library (libosd.ko).
+		NOTE: You must also select CRYPTO_SHA1 + CRYPTO_HMAC and their
+		dependencies
+
+config SCSI_OSD_ULD
+	tristate "OSD Upper Level driver"
+	depends on SCSI_OSD_INITIATOR
+	help
+		Build a SCSI upper layer driver that exports /dev/osdX devices
+		to user-mode for testing and controlling OSD devices. It is also
+		needed by exofs, for mounting an OSD based file system.
+
+config SCSI_OSD_DPRINT_SENSE
+    int "(0-2) When sense is returned, DEBUG print all sense descriptors"
+    default 1
+    depends on SCSI_OSD_INITIATOR
+    help
+        When a CHECK_CONDITION status is returned from a target, and a
+        sense-buffer is retrieved, turning this on will dump a full
+        sense-decoding message. Setting to 2 will also print recoverable
+        errors that might be regularly returned for some filesystem
+        operations.
+
+config SCSI_OSD_DEBUG
+	bool "Compile All OSD modules with lots of DEBUG prints"
+	default n
+	depends on SCSI_OSD_INITIATOR
+	help
+		OSD Code is populated with lots of OSD_DEBUG(..) printouts to
+		dmesg. Enable this if you found a bug and you want to help us
+		track the problem (see also MAINTAINERS). Setting this will also
+		force SCSI_OSD_DPRINT_SENSE=2.
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 17/18] osd: Kconfig file for in-tree builds
@ 2008-12-22 13:18     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:18 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

Kconfig file for the drivers/scsi/osd subdirectory.
Adds the following config items:
	config SCSI_OSD_INITIATOR
	config SCSI_OSD_ULD
	config SCSI_OSD_DPRINT_SENSE
	config SCSI_OSD_DEBUG

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kconfig |   53 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 53 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kconfig

diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
new file mode 100644
index 0000000..861b5ce
--- /dev/null
+++ b/drivers/scsi/osd/Kconfig
@@ -0,0 +1,53 @@
+#
+# Kernel configuration file for the OSD scsi protocol
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public version 2 License as
+# published by the Free Software Foundation
+#
+# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
+#        How is it done properly?
+#
+
+config SCSI_OSD_INITIATOR
+	tristate "OSD-Initiator library"
+	depends on SCSI
+	help
+		Enable the OSD-Initiator library (libosd.ko).
+		NOTE: You must also select CRYPTO_SHA1 + CRYPTO_HMAC and their
+		dependencies
+
+config SCSI_OSD_ULD
+	tristate "OSD Upper Level driver"
+	depends on SCSI_OSD_INITIATOR
+	help
+		Build a SCSI upper layer driver that exports /dev/osdX devices
+		to user-mode for testing and controlling OSD devices. It is also
+		needed by exofs, for mounting an OSD based file system.
+
+config SCSI_OSD_DPRINT_SENSE
+    int "(0-2) When sense is returned, DEBUG print all sense descriptors"
+    default 1
+    depends on SCSI_OSD_INITIATOR
+    help
+        When a CHECK_CONDITION status is returned from a target, and a
+        sense-buffer is retrieved, turning this on will dump a full
+        sense-decoding message. Setting to 2 will also print recoverable
+        errors that might be regularly returned for some filesystem
+        operations.
+
+config SCSI_OSD_DEBUG
+	bool "Compile All OSD modules with lots of DEBUG prints"
+	default n
+	depends on SCSI_OSD_INITIATOR
+	help
+		OSD Code is populated with lots of OSD_DEBUG(..) printouts to
+		dmesg. Enable this if you found a bug and you want to help us
+		track the problem (see also MAINTAINERS). Setting this will also
+		force SCSI_OSD_DPRINT_SENSE=2.
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 18/18] scsi: Add osd library to build system
  2008-12-22 12:32   ` Boaz Harrosh
@ 2008-12-22 13:20     ` Boaz Harrosh
  -1 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:20 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik,
	linux-scsi, open-osd ml
  Cc: linux-kernel

OSD in kernel source code is assumed to be at:
drivers/scsi/osd/ with its own Makefile and Kconfig

Add includes to them from drivers/scsi Makefile and Kconfig
Add OSD to MAINTAINERS file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 MAINTAINERS           |   10 ++++++++++
 drivers/scsi/Kconfig  |    2 ++
 drivers/scsi/Makefile |    2 ++
 3 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8f2b67e..79df335 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3234,6 +3234,16 @@ L:	orinoco-devel@lists.sourceforge.net
 W:	http://www.nongnu.org/orinoco/
 S:	Maintained
 
+OSD LIBRARY
+P:	Boaz Harrosh
+M:	bharrosh@panasas.com
+P:	Benny Halevy
+M:	bhalevy@panasas.com
+L:	osd-dev@open-osd.org
+W:	http://open-osd.org
+T:	git://git.open-osd.org/open-osd.git
+S:	Maintained
+
 P54 WIRELESS DRIVER
 P:	Michael Wu
 M:	flamingice@sourmilk.net
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 673463e..1170c01 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1800,4 +1800,6 @@ source "drivers/scsi/pcmcia/Kconfig"
 
 source "drivers/scsi/device_handler/Kconfig"
 
+source "drivers/scsi/osd/Kconfig"
+
 endmenu
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 07d0f58..e68864b 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -137,6 +137,8 @@ obj-$(CONFIG_CHR_DEV_SG)	+= sg.o
 obj-$(CONFIG_CHR_DEV_SCH)	+= ch.o
 obj-$(CONFIG_SCSI_ENCLOSURE)	+= ses.o
 
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += osd/
+
 # This goes last, so that "real" scsi devices probe earlier
 obj-$(CONFIG_SCSI_DEBUG)	+= scsi_debug.o
 
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 18/18] scsi: Add osd library to build system
@ 2008-12-22 13:20     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2008-12-22 13:20 UTC (permalink / raw)
  To: James Bottomley, Mike Christie, FUJITA Tomonori, Jeff Garzik, linux-s
  Cc: linux-kernel

OSD in kernel source code is assumed to be at:
drivers/scsi/osd/ with its own Makefile and Kconfig

Add includes to them from drivers/scsi Makefile and Kconfig
Add OSD to MAINTAINERS file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 MAINTAINERS           |   10 ++++++++++
 drivers/scsi/Kconfig  |    2 ++
 drivers/scsi/Makefile |    2 ++
 3 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8f2b67e..79df335 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3234,6 +3234,16 @@ L:	orinoco-devel@lists.sourceforge.net
 W:	http://www.nongnu.org/orinoco/
 S:	Maintained
 
+OSD LIBRARY
+P:	Boaz Harrosh
+M:	bharrosh@panasas.com
+P:	Benny Halevy
+M:	bhalevy@panasas.com
+L:	osd-dev@open-osd.org
+W:	http://open-osd.org
+T:	git://git.open-osd.org/open-osd.git
+S:	Maintained
+
 P54 WIRELESS DRIVER
 P:	Michael Wu
 M:	flamingice@sourmilk.net
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 673463e..1170c01 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1800,4 +1800,6 @@ source "drivers/scsi/pcmcia/Kconfig"
 
 source "drivers/scsi/device_handler/Kconfig"
 
+source "drivers/scsi/osd/Kconfig"
+
 endmenu
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 07d0f58..e68864b 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -137,6 +137,8 @@ obj-$(CONFIG_CHR_DEV_SG)	+= sg.o
 obj-$(CONFIG_CHR_DEV_SCH)	+= ch.o
 obj-$(CONFIG_SCSI_ENCLOSURE)	+= ses.o
 
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += osd/
+
 # This goes last, so that "real" scsi devices probe earlier
 obj-$(CONFIG_SCSI_DEBUG)	+= scsi_debug.o
 
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29
       [not found] <48876009.8010701@panasas.com>
                   ` (2 preceding siblings ...)
  2008-12-22 12:32   ` Boaz Harrosh
@ 2009-01-06 14:04 ` Boaz Harrosh
  2009-01-06 14:07   ` [PATCH 01/18] major.h: char-major number for OSD device driver Boaz Harrosh
                     ` (17 more replies)
  3 siblings, 18 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:04 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

OSD (Object-Based Storage Device) is a T10 SCSI command set that is designed
to provide efficient operation of input/output logical units that manage the
allocation, placement, and accessing of variable-size data-storage containers,
called objects. Objects are intended to contain operating system and application
constructs. Each object has associated attributes attached to it, which are
integral part of the object and provide metadata about the object. The standard
defines some common obligatory attributes, but user attributes can be added as
needed.

Whats new from last time:
- rename attribute's "page" member to "attr_page" so not to confuse with
  struct page. As suggested by Andrew Morton.

The patches are cut over scsi-misc-2.6-5db524b but apply cleanly over
linus-238c6d5 and are intended for the 2.6.29 merge window.

To try out and run the library please visit
http://open-osd.org and follow the instructions there.

The submitted patchset is also available via git at:
   git://git.open-osd.org/linux-open-osd.git osd
   http://git.open-osd.org/gitweb.cgi?p=linux-open-osd.git;a=shortlog;h=osd

here is the list of patches:

[PATCH 01/18] major.h: char-major number for OSD device driver
  Request for a new char-device major number

[PATCH 02/18] scsi: OSD_TYPE
  The OSD scsi type constant definition.

[PATCH 03/18] libosd: OSDv1 Headers
[PATCH 04/18] libosd: OSDv1 preliminary implementation
  Most basic, but usable library module (libosd.ko) including
  Kbuild file.

[PATCH 05/18] osd_uld: OSD scsi ULD
[PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel
[PATCH 07/18] osd_ktests: Add basic OSD tests
  These patches add a scsi ULD for OSD type devices. Please see
  commit logs for details.

[PATCH 08/18] libosd: attributes Support
[PATCH 09/18] osd_ktests: Test Attribute lists
[PATCH 10/18] libosd: OSD Security processing stubs
[PATCH 12/18] libosd: Add Flush and List-objects support
[PATCH 12/18] libosd: Not implemented commands
[PATCH 13/18] libosd: OSD version 2 Support
[PATCH 14/18] libosd: OSDv2 auto detection
[PATCH 15/18] libosd: SCSI/OSD Sense decoding support
  Up to here this is a fairly complete body of work, to support
  both OSD1 and OSD2 targets. Main pieces that are still missing
  from the library at this point are: The OSD2 capabilities structure,
  do to lack of an OSD target that supports it, so it was never tested.
  And the absence of any OSD-security methods other then NO_SECURITY.
  These will come in future versions.

[PATCH 16/18] osd: Documentation for OSD library
  Some reading about OSD in general and further usability instructions.
  Please comment on anything missing from this document.

[PATCH 17/18] osd: Kconfig file for in-tree builds
[PATCH 18/18] scsi: Add osd library to build system
  The in-tree compilation is only enabled at the end of the patchset.
  Run your favorite configure-tool to enable the library and osd_uld
  compilation. Default is off.
  The patchset is however fully bisectable, and compilable from the beginning,
  (by applying these 2 patches first).

The open-osd team
Boaz Harrosh

^ permalink raw reply	[flat|nested] 183+ messages in thread

* [PATCH 01/18] major.h: char-major number for OSD device driver
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
@ 2009-01-06 14:07   ` Boaz Harrosh
  2009-01-06 14:10   ` [PATCH 02/18] scsi: OSD_TYPE Boaz Harrosh
                     ` (16 subsequent siblings)
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:07 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

We need a major for a char device for our OSD device driver.
Attached is a proposed patch for the Documentation/devices.txt
and include/linux/major.h files.

I have allocated the *260* char device as it looked like the next
available on the lanana.org web-site
(http://lanana.org/docs/device-list/devices-2.6+.txt)

Any number will do. Please allocate a number for us

(See http:/open-osd.org for further information)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
CC: Torben Mathiasen <device@lanana.org>
---
 Documentation/devices.txt |    6 ++++++
 include/linux/major.h     |    1 +
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 2be0824..62254d4 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -3145,6 +3145,12 @@ Your cooperation is appreciated.
 		  1 = /dev/blockrom1	Second ROM card's translation layer interface
 		  ...
 
+260 char	OSD (Object-based-device) SCSI Device
+		  0 = /dev/osd0		First OSD Device
+		  1 = /dev/osd1		Second OSD Device
+		  ...
+		  255 = /dev/osd255	256th OSD Device
+
  ****	ADDITIONAL /dev DIRECTORY ENTRIES
 
 This section details additional entries that should or may exist in
diff --git a/include/linux/major.h b/include/linux/major.h
index 8824945..058ec15 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -171,5 +171,6 @@
 #define VIOTAPE_MAJOR		230
 
 #define BLOCK_EXT_MAJOR		259
+#define SCSI_OSD_MAJOR		260	/* open-osd's OSD scsi device */
 
 #endif
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 02/18] scsi: OSD_TYPE
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
  2009-01-06 14:07   ` [PATCH 01/18] major.h: char-major number for OSD device driver Boaz Harrosh
@ 2009-01-06 14:10   ` Boaz Harrosh
  2009-01-06 14:11   ` [PATCH 03/18] libosd: OSDv1 Headers Boaz Harrosh
                     ` (15 subsequent siblings)
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:10 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

- Define the OSD_TYPE scsi device and let it show up in scans

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/scsi_scan.c |    1 +
 include/scsi/scsi.h      |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index f8493f2..001c1da 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -793,6 +793,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
 	case TYPE_ENCLOSURE:
 	case TYPE_COMM:
 	case TYPE_RAID:
+	case TYPE_OSD:
 		sdev->writeable = 1;
 		break;
 	case TYPE_ROM:
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index a109165..de1cef2 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -263,6 +263,7 @@ static inline int scsi_status_is_good(int status)
 #define TYPE_RAID           0x0c
 #define TYPE_ENCLOSURE      0x0d    /* Enclosure Services Device */
 #define TYPE_RBC	    0x0e
+#define TYPE_OSD            0x11
 #define TYPE_NO_LUN         0x7f
 
 /* SCSI protocols; these are taken from SPC-3 section 7.5 */
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 03/18] libosd: OSDv1 Headers
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
  2009-01-06 14:07   ` [PATCH 01/18] major.h: char-major number for OSD device driver Boaz Harrosh
  2009-01-06 14:10   ` [PATCH 02/18] scsi: OSD_TYPE Boaz Harrosh
@ 2009-01-06 14:11   ` Boaz Harrosh
  2009-01-06 14:13   ` [PATCH 04/18] libosd: OSDv1 preliminary implementation Boaz Harrosh
                     ` (14 subsequent siblings)
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:11 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Headers only patch.

osd_protocol.h
	Contains a C-fied definition of the T10 OSD standard
osd_types.h
	Contains CPU order common used types
osd_initiator.h
	API definition of the osd_initiator library
osd_sec.h
	Contains High level API for the security manager.

[Note that checkpatch spews errors on things that are valid in this context
and will not be fixed]

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 include/scsi/osd_initiator.h |  332 ++++++++++++++++++++++++++++
 include/scsi/osd_protocol.h  |  497 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_sec.h       |   45 ++++
 include/scsi/osd_types.h     |   40 ++++
 4 files changed, 914 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_initiator.h
 create mode 100644 include/scsi/osd_protocol.h
 create mode 100644 include/scsi/osd_sec.h
 create mode 100644 include/scsi/osd_types.h

diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
new file mode 100644
index 0000000..1d92247
--- /dev/null
+++ b/include/scsi/osd_initiator.h
@@ -0,0 +1,332 @@
+/*
+ * osd_initiator.h - OSD initiator API definition
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_INITIATOR_H__
+#define __OSD_INITIATOR_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+#include <linux/blkdev.h>
+
+/* Note: "NI" in comments below means "Not Implemented yet" */
+
+/*
+ * Object-based Storage Device.
+ * This object represents an OSD device.
+ * It is not a full linux device in any way. It is only
+ * a place to hang resources associated with a Linux
+ * request Q and some default properties.
+ */
+struct osd_dev {
+	struct scsi_device *scsi_device;
+	unsigned def_timeout;
+};
+
+void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
+void osd_dev_fini(struct osd_dev *od);
+
+struct osd_request;
+typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
+
+struct osd_request {
+	struct osd_cdb cdb;
+	struct osd_data_out_integrity_info out_data_integ;
+	struct osd_data_in_integrity_info in_data_integ;
+
+	struct osd_dev *osd_dev;
+	struct request *request;
+
+	struct _osd_req_data_segment {
+		void *buff;
+		unsigned alloc_size; /* 0 here means: don't call kfree */
+		unsigned total_bytes;
+	} set_attr, enc_get_attr, get_attr;
+
+	struct _osd_io_info {
+		struct bio *bio;
+		u64 total_bytes;
+		struct request *req;
+		struct _osd_req_data_segment *last_seg;
+		u8 *pad_buff;
+	} out, in;
+
+	gfp_t alloc_flags;
+	unsigned timeout;
+	unsigned retries;
+	u8 sense[OSD_MAX_SENSE_LEN];
+	enum osd_attributes_mode attributes_mode;
+
+	osd_req_done_fn *async_done;
+	void *async_private;
+	int async_error;
+};
+
+/*
+ * How to use the osd library:
+ *
+ * osd_start_request
+ *	Allocates a request.
+ *
+ * osd_req_*
+ *	Call one of, to encode the desired operation.
+ *
+ * osd_add_{get,set}_attr
+ *	Optionally add attributes to the CDB, list or page mode.
+ *
+ * osd_finalize_request
+ *	Computes final data out/in offsets and signs the request,
+ *	making it ready for execution.
+ *
+ * osd_execute_request
+ *	May be called to execute it through the block layer. Other wise submit
+ *	the associated block request in some other way.
+ *
+ * After execution:
+ * osd_req_decode_sense
+ *	Decodes sense information to verify execution results.
+ *
+ * osd_req_decode_get_attr
+ *	Retrieve osd_add_get_attr_list() values if used.
+ *
+ * osd_end_request
+ *	Must be called to deallocate the request.
+ */
+
+/**
+ * osd_start_request - Allocate and initialize an osd_request
+ *
+ * @osd_dev:    OSD device that holds the scsi-device and default values
+ *              that the request is associated with.
+ * @gfp:        The allocation flags to use for request allocation, and all
+ *              subsequent allocations. This will be stored at
+ *              osd_request->alloc_flags, can be changed by user later
+ *
+ * Allocate osd_request and initialize all members to the
+ * default/initial state.
+ */
+struct osd_request *osd_start_request(struct osd_dev *od, gfp_t gfp);
+
+enum osd_req_options {
+	OSD_REQ_FUA = 0x08,	/* Force Unit Access */
+	OSD_REQ_DPO = 0x10,	/* Disable Page Out */
+
+	OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
+};
+
+/**
+ * osd_finalize_request - Sign request and prepare request for execution
+ *
+ * @or:		osd_request to prepare
+ * @options:	combination of osd_req_options bit flags or 0.
+ * @cap:	A Pointer to an OSD_CAP_LEN bytes buffer that is received from
+ *              The security manager as capabilities for this cdb.
+ * @cap_key:	The cryptographic key used to sign the cdb/data. Can be null
+ *              if NOSEC is used.
+ *
+ * The actual request and bios are only allocated here, so are the get_attr
+ * buffers that will receive the returned attributes. Copy's @cap to cdb.
+ * Sign the cdb/data with @cap_key.
+ */
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key);
+
+/**
+ * osd_execute_request - Execute the request synchronously through block-layer
+ *
+ * @or:		osd_request to Executed
+ *
+ * Calls blk_execute_rq to q the command and waits for completion.
+ */
+int osd_execute_request(struct osd_request *or);
+
+/**
+ * osd_execute_request_async - Execute the request without waitting.
+ *
+ * @or:                      - osd_request to Executed
+ * @done: (Optional)         - Called at end of execution
+ * @private:                 - Will be passed to @done function
+ *
+ * Calls blk_execute_rq_nowait to queue the command. When execution is done
+ * optionally calls @done with @private as parameter. @or->async_error will
+ * have the return code
+ */
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private);
+
+/**
+ * osd_end_request - return osd_request to free store
+ *
+ * @or:		osd_request to free
+ *
+ * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
+ */
+void osd_end_request(struct osd_request *or);
+
+/*
+ * CDB Encoding
+ *
+ * Note: call only one of the following methods.
+ */
+
+/*
+ * Device commands
+ */
+void osd_req_set_master_seed_xchg(struct osd_request *or, ...);/* NI */
+void osd_req_set_master_key(struct osd_request *or, ...);/* NI */
+
+void osd_req_format(struct osd_request *or, u64 tot_capacity);
+
+/* list all partitions
+ * @list header must be initialized to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values);
+
+void osd_req_perform_scsi_command(struct osd_request *or,
+	const u8 *cdb, ...);/* NI */
+void osd_req_task_management(struct osd_request *or, ...);/* NI */
+
+/*
+ * Partition commands
+ */
+void osd_req_create_partition(struct osd_request *or, osd_id partition);
+void osd_req_remove_partition(struct osd_request *or, osd_id partition);
+
+void osd_req_set_partition_key(struct osd_request *or,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
+
+/* list all collections in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+/* list all objects in the partition
+ * @list header must be init to zero on first run.
+ *
+ * Call osd_is_obj_list_done() to find if we got the complete list.
+ */
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values);
+
+/*
+ * Collection commands
+ */
+void osd_req_create_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+void osd_req_remove_collection(struct osd_request *or,
+	const struct osd_obj_id *);/* NI */
+
+/* list all objects in the collection */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem);
+
+/* V2 only filtered list of objects in the collection */
+void osd_req_query(struct osd_request *or, ...);/* NI */
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values);
+
+void osd_req_get_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+void osd_req_set_member_attrs(struct osd_request *or, ...);/* V2-only NI */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *);
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);
+void osd_req_append(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out);/* NI */
+void osd_req_create_write(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
+void osd_req_clear(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* NI */
+void osd_req_punch(struct osd_request *or,
+	const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
+
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *, enum osd_options_flush_scope_values,
+	/*V2*/ u64 offset, /*V2*/ u64 len);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *, struct bio *data_in, u64 offset);
+
+/*
+ * Root/Partition/Collection/Object Attributes commands
+ */
+
+/* get before set */
+void osd_req_get_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/* set before get */
+void osd_req_set_attributes(struct osd_request *or, const struct osd_obj_id *);
+
+/*
+ * Attributes appended to most commands
+ */
+
+/* Attributes List mode (or V2 CDB) */
+  /*
+   * TODO: In ver2 if at finalize time only one attr was set and no gets,
+   * then the Attributes CDB mode is used automatically to save IO.
+   */
+
+/* set a list of attributes. */
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/* get a list of attributes */
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *, unsigned nelem);
+
+/*
+ * Attributes list decoding
+ * Must be called after osd_request.request was executed
+ * It is called in a loop to decode the returned get_attr
+ * (see osd_add_get_attr)
+ */
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *, int *nelem, void **iterator);
+
+/* Attributes Page mode */
+
+/*
+ * Read an attribute page and optionally set one attribute
+ *
+ * Retrieves the attribute page directly to a user buffer.
+ * @attr_page_data shall stay valid until end of execution.
+ * See osd_attributes.h for common page structures
+ */
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attr_page_data, unsigned max_page_len,
+	const struct osd_attr *set_one);
+
+#endif /* __OSD_LIB_H__ */
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
new file mode 100644
index 0000000..ce1a877
--- /dev/null
+++ b/include/scsi/osd_protocol.h
@@ -0,0 +1,497 @@
+/*
+ * osd_protocol.h - OSD T10 standard C definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_PROTOCOL_H__
+#define __OSD_PROTOCOL_H__
+
+#include <linux/types.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+enum {
+	OSDv1_ADDITIONAL_CDB_LENGTH = 192,
+	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
+	OSDv1_CAP_LEN = 80,
+	/* Latest supported version */
+	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
+	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
+	OSD_CAP_LEN = OSDv1_CAP_LEN,
+
+	OSD_SYSTEMID_LEN = 20,
+	OSD_CRYPTO_KEYID_SIZE = 20,
+	OSD_CRYPTO_SEED_SIZE = 4,
+	OSD_CRYPTO_NONCE_SIZE = 12,
+	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
+
+	OSD_PARTITION_FIRST_ID = 0x10000,
+	OSD_OBJECT_FIRST_ID = 0x10000,
+};
+
+/* (osd-r10 5.2.4)
+ * osd2r03: 5.2.3 Caching control bits
+ */
+enum osd_options_byte {
+	OSD_CDB_FUA = 0x08,	/* Force Unit Access */
+	OSD_CDB_DPO = 0x10,	/* Disable Page Out */
+};
+
+/*
+ * osd2r03: 5.2.5 Isolation.
+ * First 3 bits, V2-only.
+ * Also for attr 110h "default isolation method" at Root Information page
+ */
+enum osd_options_byte_isolation {
+	OSD_ISOLATION_DEFAULT = 0,
+	OSD_ISOLATION_NONE = 1,
+	OSD_ISOLATION_STRICT = 2,
+	OSD_ISOLATION_RANGE = 4,
+	OSD_ISOLATION_FUNCTIONAL = 5,
+	OSD_ISOLATION_VENDOR = 7,
+};
+
+/* (osd-r10: 6.7)
+ * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION
+ */
+enum osd_options_flush_scope_values {
+	OSD_CDB_FLUSH_ALL = 0,
+	OSD_CDB_FLUSH_ATTR_ONLY = 1,
+
+	OSD_CDB_FLUSH_ALL_RECURSIVE = 2,
+	/* V2-only */
+	OSD_CDB_FLUSH_ALL_RANGE = 2,
+};
+
+/* osd2r03: 5.2.10 Timestamps control */
+enum {
+	OSD_CDB_NORMAL_TIMESTAMPS = 0,
+	OSD_CDB_BYPASS_TIMESTAMPS = 0x7f,
+};
+
+/* (osd-r10: 5.2.2.1)
+ * osd2r03: 5.2.4.1 Get and set attributes CDB format selection
+ *	2 bits at second nibble of command_specific_options byte
+ */
+enum osd_attributes_mode {
+	/* V2-only */
+	OSD_CDB_SET_ONE_ATTR = 0x10,
+
+	OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20,
+	OSD_CDB_GET_SET_ATTR_LISTS = 0x30,
+
+	OSD_CDB_GET_SET_ATTR_MASK = 0x30,
+};
+
+/* (osd-r10: 4.12.5)
+ * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets
+ *	byte offset = mantissa * (2^(exponent+8))
+ *	struct {
+ *		unsigned mantissa: 28;
+ *		int exponent: 04;
+ *	}
+ */
+typedef __be32 __bitwise osd_cdb_offset;
+
+enum {
+	OSD_OFFSET_UNUSED = 0xFFFFFFFF,
+	OSD_OFFSET_MAX_BITS = 28,
+
+	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MAX_SHIFT = 16,
+};
+
+/* Return the smallest allowed encoded offset that contains @offset.
+ *
+ * The actual encoded offset returned is @offset + *padding.
+ * (up to max_shift, non-inclusive)
+ */
+osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding,
+	int min_shift, int max_shift);
+
+/* Minimum alignment is 256 bytes
+ * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive)
+ * which is 8 to 23 but IBM code restricts it to 16, so be it.
+ */
+static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
+/* osd2r03: 5.2.1 Overview */
+struct osd_cdb_head {
+	struct scsi_varlen_cdb_hdr varlen_cdb;
+/*10*/	u8		options;
+	u8		command_specific_options;
+	u8		timestamp_control;
+/*13*/	u8		reserved1[3];
+/*16*/	__be64		partition;
+/*24*/	__be64		object;
+/*32*/	union { /* V1 vs V2 alignment differences */
+		struct __osdv1_cdb_addr_len {
+/*32*/			__be32 		list_identifier;/* Rarely used */
+/*36*/			__be64		length;
+/*44*/			__be64		start_address;
+		} __packed v1;
+	};
+/*52*/	union { /* selected attributes mode Page/List/Single */
+		struct osd_attributes_page_mode {
+/*52*/			__be32		get_attr_page;
+/*56*/			__be32		get_attr_alloc_length;
+/*60*/			osd_cdb_offset	get_attr_offset;
+
+/*64*/			__be32		set_attr_page;
+/*68*/			__be32		set_attr_id;
+/*72*/			__be32		set_attr_length;
+/*76*/			osd_cdb_offset	set_attr_offset;
+/*80*/		} __packed attrs_page;
+
+		struct osd_attributes_list_mode {
+/*52*/			__be32		get_attr_desc_bytes;
+/*56*/			osd_cdb_offset	get_attr_desc_offset;
+
+/*60*/			__be32		get_attr_alloc_length;
+/*64*/			osd_cdb_offset	get_attr_offset;
+
+/*68*/			__be32		set_attr_bytes;
+/*72*/			osd_cdb_offset	set_attr_offset;
+			__be32 not_used;
+/*80*/		} __packed attrs_list;
+
+		/* osd2r03:5.2.4.2 Set one attribute value using CDB fields */
+		struct osd_attributes_cdb_mode {
+/*52*/			__be32		set_attr_page;
+/*56*/			__be32		set_attr_id;
+/*60*/			__be16		set_attr_len;
+/*62*/			u8		set_attr_val[18];
+/*80*/		} __packed attrs_cdb;
+/*52*/		u8 get_set_attributes_parameters[28];
+	};
+} __packed;
+/*80*/
+
+/*160 v1*/
+struct osd_security_parameters {
+/*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+/*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*192*/osd_cdb_offset	data_in_integrity_check_offset;
+/*196*/osd_cdb_offset	data_out_integrity_check_offset;
+} __packed;
+/*200 v1*/
+
+struct osdv1_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSDv1_CAP_LEN];
+	struct osd_security_parameters sec_params;
+} __packed;
+
+struct osd_cdb {
+	union {
+		struct osdv1_cdb v1;
+		u8 buff[OSD_TOTAL_CDB_LEN];
+	};
+} __packed;
+
+static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb)
+{
+	return (struct osd_cdb_head *)ocdb->buff;
+}
+
+/* define both version actions
+ * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD
+ */
+#define OSD_ACT___(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num),
+
+/* V2 only actions */
+#define OSD_ACT_V2(Name, Num) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num),
+
+#define OSD_ACT_V1_V2(Name, Num1, Num2) \
+	OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \
+	OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1),
+
+enum osd_service_actions {
+	OSD_ACT_V2(OBJECT_STRUCTURE_CHECK,	0x00)
+	OSD_ACT___(FORMAT_OSD,			0x01)
+	OSD_ACT___(CREATE,			0x02)
+	OSD_ACT___(LIST,			0x03)
+	OSD_ACT_V2(PUNCH,			0x04)
+	OSD_ACT___(READ,			0x05)
+	OSD_ACT___(WRITE,			0x06)
+	OSD_ACT___(APPEND,			0x07)
+	OSD_ACT___(FLUSH,			0x08)
+	OSD_ACT_V2(CLEAR,			0x09)
+	OSD_ACT___(REMOVE,			0x0A)
+	OSD_ACT___(CREATE_PARTITION,		0x0B)
+	OSD_ACT___(REMOVE_PARTITION,		0x0C)
+	OSD_ACT___(GET_ATTRIBUTES,		0x0E)
+	OSD_ACT___(SET_ATTRIBUTES,		0x0F)
+	OSD_ACT___(CREATE_AND_WRITE,		0x12)
+	OSD_ACT___(CREATE_COLLECTION,		0x15)
+	OSD_ACT___(REMOVE_COLLECTION,		0x16)
+	OSD_ACT___(LIST_COLLECTION,		0x17)
+	OSD_ACT___(SET_KEY,			0x18)
+	OSD_ACT___(SET_MASTER_KEY,		0x19)
+	OSD_ACT___(FLUSH_COLLECTION,		0x1A)
+	OSD_ACT___(FLUSH_PARTITION,		0x1B)
+	OSD_ACT___(FLUSH_OSD,			0x1C)
+
+	OSD_ACT_V2(QUERY,			0x20)
+	OSD_ACT_V2(REMOVE_MEMBER_OBJECTS,	0x21)
+	OSD_ACT_V2(GET_MEMBER_ATTRIBUTES,	0x22)
+	OSD_ACT_V2(SET_MEMBER_ATTRIBUTES,	0x23)
+	OSD_ACT_V2(READ_MAP,			0x31)
+
+	OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND,	0x8F7E, 0x8F7C)
+	OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT,	0x8F7F, 0x8F7D)
+	/* 0x8F80 to 0x8FFF are Vendor specific */
+};
+
+/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */
+struct osd_attributes_list_attrid {
+	__be32 attr_page;
+	__be32 attr_id;
+} __packed;
+
+/*
+ * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
+ *                  for setting attributes
+ */
+struct osd_attributes_list_element {
+	__be32 attr_page;
+	__be32 attr_id;
+	__be16 attr_bytes;
+	u8 attr_val[0];
+} __packed;
+
+enum {
+	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+};
+
+enum {
+	OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF,
+	OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF,
+};
+
+static inline unsigned osdv1_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
+}
+
+/*
+ * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
+ */
+enum osd_attr_list_types {
+	OSD_ATTR_LIST_GET = 0x1, 	/* descriptors only */
+	OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/
+	OSD_V2_ATTR_LIST_MULTIPLE = 0xE,  /* ver2, Multiple Objects lists*/
+	OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/
+};
+
+/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */
+struct osd_attributes_list_multi_header {
+	__be64 object_id;
+	u8 object_type; /* object_type enum below */
+	u8 reserved[5];
+	__be16 list_bytes;
+	/* followed by struct osd_attributes_list_element's */
+};
+
+struct osdv1_attributes_list_header {
+	u8 type;	/* low 4-bit only */
+	u8 pad;
+	__be16 list_bytes; /* Initiator shall set to Zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
+{
+	return be16_to_cpu(h->list_bytes);
+}
+
+/* (osd-r10 6.13)
+ * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
+ *	for root_lstchg below
+ */
+enum {
+	OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */
+	OSD_OBJ_ID_LIST_LSTCHG = 0x2,
+};
+
+/*
+ * osd2r03: 6.15.2 LIST command parameter data
+ * (Also for LIST COLLECTION)
+ */
+struct osd_obj_id_list {
+	__be64 list_bytes; /* bytes in list excluding list_bytes (-8) */
+	__be64 continuation_id;
+	__be32 list_identifier;
+	u8 pad[3];
+	u8 root_lstchg;
+	__be64 object_ids[0];
+} __packed;
+
+static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list,
+	bool *is_changed)
+{
+	*is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG));
+	return 0 != list->continuation_id;
+}
+
+/*
+ * osd2r03: 4.12.4.5 The ALLDATA security method
+ */
+struct osd_data_out_integrity_info {
+	__be64 data_bytes;
+	__be64 set_attributes_bytes;
+	__be64 get_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_data_in_integrity_info {
+	__be64 data_bytes;
+	__be64 retrieved_attributes_bytes;
+	__be64 integrity_check_value;
+} __packed;
+
+struct osd_timestamp {
+	u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
+} __packed;
+/* FIXME: define helper functions to convert to/from osd time format */
+
+/*
+ * Capability & Security definitions
+ * osd2r03: 4.11.2.2 Capability format
+ * osd2r03: 5.2.8 Security parameters
+ */
+
+struct osd_key_identifier {
+	u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+} __packed;
+
+/* for osd_capability.format */
+enum {
+	OSD_SEC_CAP_FORMAT_NO_CAPS = 0,
+	OSD_SEC_CAP_FORMAT_VER1 = 1,
+	OSD_SEC_CAP_FORMAT_VER2 = 2,
+};
+
+/* security_method */
+enum {
+	OSD_SEC_NOSEC = 0,
+	OSD_SEC_CAPKEY = 1,
+	OSD_SEC_CMDRSP = 2,
+	OSD_SEC_ALLDATA = 3,
+};
+
+enum object_type {
+	OSD_SEC_OBJ_ROOT = 0x1,
+	OSD_SEC_OBJ_PARTITION = 0x2,
+	OSD_SEC_OBJ_COLLECTION = 0x40,
+	OSD_SEC_OBJ_USER = 0x80,
+};
+
+enum osd_capability_bit_masks {
+	OSD_SEC_CAP_APPEND	= BIT(0),
+	OSD_SEC_CAP_OBJ_MGMT	= BIT(1),
+	OSD_SEC_CAP_REMOVE	= BIT(2),
+	OSD_SEC_CAP_CREATE	= BIT(3),
+	OSD_SEC_CAP_SET_ATTR	= BIT(4),
+	OSD_SEC_CAP_GET_ATTR	= BIT(5),
+	OSD_SEC_CAP_WRITE	= BIT(6),
+	OSD_SEC_CAP_READ	= BIT(7),
+
+	OSD_SEC_CAP_NONE1	= BIT(8),
+	OSD_SEC_CAP_NONE2	= BIT(9),
+	OSD_SEC_CAP_NONE3	= BIT(10),
+	OSD_SEC_CAP_QUERY	= BIT(11), /*v2 only*/
+	OSD_SEC_CAP_M_OBJECT	= BIT(12), /*v2 only*/
+	OSD_SEC_CAP_POL_SEC	= BIT(13),
+	OSD_SEC_CAP_GLOBAL	= BIT(14),
+	OSD_SEC_CAP_DEV_MGMT	= BIT(15),
+};
+
+/* for object_descriptor_type (hi nibble used) */
+enum {
+	OSD_SEC_OBJ_DESC_NONE = 0,     /* Not allowed */
+	OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */
+	OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */
+	OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */
+};
+
+/* (osd-r10:4.9.2.2)
+ * osd2r03:4.11.2.2 Capability format
+ */
+struct osd_capability_head {
+	u8 format; /* low nibble */
+	u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */
+	u8 security_method;
+	u8 reserved1;
+/*04*/	struct osd_timestamp expiration_time;
+/*10*/	u8 audit[20];
+/*30*/	u8 discriminator[12];
+/*42*/	struct osd_timestamp object_created_time;
+/*48*/	u8 object_type;
+/*49*/	u8 permissions_bit_mask[5];
+/*54*/	u8 reserved2;
+/*55*/	u8 object_descriptor_type; /* high nibble */
+} __packed;
+
+/*56 v1*/
+struct osdv1_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 policy_access_tag;
+/*60*/			__be64 allowed_partition_id;
+/*68*/			__be64 allowed_object_id;
+/*76*/			__be32 reserved;
+		} __packed obj_desc;
+
+/*56*/		u8 object_descriptor[24];
+	};
+} __packed;
+/*80 v1*/
+
+struct osd_capability {
+	struct osd_capability_head h;
+	struct osdv1_cap_object_descriptor od;
+} __packed;
+
+/**
+ * osd_sec_set_caps - set cap-bits into the capabilities header
+ *
+ * @cap:	The osd_capability_head to set cap bits to.
+ * @bit_mask: 	Use an ORed list of enum osd_capability_bit_masks values
+ *
+ * permissions_bit_mask is unaligned use below to set into caps
+ * in a version independent way
+ */
+static inline void osd_sec_set_caps(struct osd_capability_head *cap,
+	u16 bit_mask)
+{
+	/*
+	 *Note: The bits above are defined LE order this is because this way
+	 *      they can grow in the future to more then 16, and still retain
+	 *      there constant values.
+	 */
+	put_unaligned_le16(bit_mask, &cap->permissions_bit_mask);
+}
+
+#endif /* ndef __OSD_PROTOCOL_H__ */
diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h
new file mode 100644
index 0000000..4c09fee
--- /dev/null
+++ b/include/scsi/osd_sec.h
@@ -0,0 +1,45 @@
+/*
+ * osd_sec.h - OSD security manager API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_SEC_H__
+#define __OSD_SEC_H__
+
+#include "osd_protocol.h"
+#include "osd_types.h"
+
+/*
+ * Contains types and constants of osd capabilities and security
+ * encoding/decoding.
+ * API is trying to keep security abstract so initiator of an object
+ * based pNFS client knows as little as possible about security and
+ * capabilities. It is the Server's osd-initiator place to know more.
+ * Also can be used by osd-target.
+ */
+void osd_sec_encode_caps(void *caps, ...);/* NI */
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1);
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_params);
+
+/* Conditionally sign the CDB according to security setting in ocdb
+ * with cap_key */
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key);
+
+/* Unconditionally sign the BIO data with cap_key.
+ * Check for osd_is_sec_alldata() was done prior to calling this. */
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key);
+
+/* Version independent copy of caps into the cdb */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps);
+
+#endif /* ndef __OSD_SEC_H__ */
diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h
new file mode 100644
index 0000000..3f5e88c
--- /dev/null
+++ b/include/scsi/osd_types.h
@@ -0,0 +1,40 @@
+/*
+ * osd_types.h - Types and constants which are not part of the protocol.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Contains types and constants that are implementation specific and are
+ * used by more than one part of the osd library.
+ *     (Eg initiator/target/security_manager/...)
+ */
+#ifndef __OSD_TYPES_H__
+#define __OSD_TYPES_H__
+
+struct osd_systemid {
+	u8 data[OSD_SYSTEMID_LEN];
+};
+
+typedef u64 __bitwise osd_id;
+
+struct osd_obj_id {
+	osd_id partition;
+	osd_id id;
+};
+
+static const struct __weak osd_obj_id osd_root_object = {0, 0};
+
+struct osd_attr {
+	u32 attr_page;
+	u32 attr_id;
+	u16 len;		/* byte count of operand */
+	void *val_ptr;		/* in network order */
+};
+
+#endif /* ndef __OSD_TYPES_H__ */
-- 
1.6.0.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 04/18] libosd: OSDv1 preliminary implementation
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (2 preceding siblings ...)
  2009-01-06 14:11   ` [PATCH 03/18] libosd: OSDv1 Headers Boaz Harrosh
@ 2009-01-06 14:13   ` Boaz Harrosh
  2009-01-06 14:14   ` [PATCH 05/18] osd_uld: OSD scsi ULD Boaz Harrosh
                     ` (13 subsequent siblings)
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:13 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Implementation of the most basic OSD functionality and
infrastructure. Mainly Format, Create/Remove Partition,
Create/Remove Object, and read/write.

- Add Makefile and Kbuild to compile libosd.ko
- osd_initiator.c Implementation file for osd_initiator.h
  and osd_sec.h APIs
- osd_debug.h - Some kprintf macro definitions

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild          |   32 +++
 drivers/scsi/osd/Makefile        |   37 +++
 drivers/scsi/osd/osd_debug.h     |   30 +++
 drivers/scsi/osd/osd_initiator.c |  448 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 547 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kbuild
 create mode 100755 drivers/scsi/osd/Makefile
 create mode 100644 drivers/scsi/osd/osd_debug.h
 create mode 100644 drivers/scsi/osd/osd_initiator.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
new file mode 100644
index 0000000..5672842
--- /dev/null
+++ b/drivers/scsi/osd/Kbuild
@@ -0,0 +1,32 @@
+#
+# Kbuild for the OSD modules
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+
+ifneq ($(OSD_INC),)
+# we are built out-of-tree Kconfigure everything as on
+
+CONFIG_SCSI_OSD_INITIATOR=m
+ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
+
+# Uncomment to turn debug on
+# ccflags-y += -DCONFIG_SCSI_OSD_DEBUG
+
+# if we are built out-of-tree and the hosting kernel has OSD headers
+# then "ccflags-y +=" will not pick the out-off-tree headers. Only by doing
+# this it will work. This might break in future kernels
+KBUILD_CPPFLAGS := -I$(OSD_INC) $(KBUILD_CPPFLAGS)
+
+endif
+
+# libosd.ko - osd-initiator library
+libosd-y := osd_initiator.o
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile
new file mode 100755
index 0000000..d905344
--- /dev/null
+++ b/drivers/scsi/osd/Makefile
@@ -0,0 +1,37 @@
+#
+# Makefile for the OSD modules (out of tree)
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+# This Makefile is used to call the kernel Makefile in case of an out-of-tree
+# build.
+# $KSRC should point to a Kernel source tree otherwise host's default is
+# used. (eg. /lib/modules/`uname -r`/build)
+
+# include path for out-of-tree Headers
+OSD_INC ?= `pwd`/../../../include
+
+# allow users to override these
+# e.g. to compile for a kernel that you aren't currently running
+KSRC ?= /lib/modules/$(shell uname -r)/build
+KBUILD_OUTPUT ?=
+ARCH ?=
+V ?= 0
+
+# this is the basic Kbuild out-of-tree invocation, with the M= option
+KBUILD_BASE = +$(MAKE) -C $(KSRC) M=`pwd` KBUILD_OUTPUT=$(KBUILD_OUTPUT) ARCH=$(ARCH) V=$(V)
+
+all: libosd
+
+libosd: ;
+	$(KBUILD_BASE) OSD_INC=$(OSD_INC) modules
+
+clean:
+	$(KBUILD_BASE) clean
diff --git a/drivers/scsi/osd/osd_debug.h b/drivers/scsi/osd/osd_debug.h
new file mode 100644
index 0000000..579e491
--- /dev/null
+++ b/drivers/scsi/osd/osd_debug.h
@@ -0,0 +1,30 @@
+/*
+ * osd_debug.h - Some kprintf macros
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_DEBUG_H__
+#define __OSD_DEBUG_H__
+
+#define OSD_ERR(fmt, a...) printk(KERN_ERR "osd: " fmt, ##a)
+#define OSD_INFO(fmt, a...) printk(KERN_NOTICE "osd: " fmt, ##a)
+
+#ifdef CONFIG_SCSI_OSD_DEBUG
+#define OSD_DEBUG(fmt, a...) \
+	printk(KERN_NOTICE "osd @%s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define OSD_DEBUG(fmt, a...) do {} while (0)
+#endif
+
+/* u64 has problems with printk this will cast it to unsigned long long */
+#define _LLU(x) (unsigned long long)(x)
+
+#endif /* ndef __OSD_DEBUG_H__ */
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
new file mode 100644
index 0000000..0e6d906
--- /dev/null
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -0,0 +1,448 @@
+/*
+ * osd_initiator - Main body of the osd initiator library.
+ *
+ * Note: The file does not contain the advanced security functionality which
+ * is only needed by the security_manager's initiators.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+#include <scsi/scsi_device.h>
+
+#include "osd_debug.h"
+
+enum { OSD_REQ_RETRIES = 1 };
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd initiator library libosd.ko");
+MODULE_LICENSE("GPL");
+
+static inline void build_test(void)
+{
+	/* structures were not packed */
+	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
+}
+
+static unsigned _osd_req_cdb_len(struct osd_request *or)
+{
+	return OSDv1_TOTAL_CDB_LEN;
+}
+
+void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
+{
+	memset(osdd, 0, sizeof(*osdd));
+	osdd->scsi_device = scsi_device;
+	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+	/* TODO: Allocate pools for osd_request attributes ... */
+}
+EXPORT_SYMBOL(osd_dev_init);
+
+void osd_dev_fini(struct osd_dev *osdd)
+{
+	/* TODO: De-allocate pools */
+
+	osdd->scsi_device = NULL;
+}
+EXPORT_SYMBOL(osd_dev_fini);
+
+static struct osd_request *_osd_request_alloc(gfp_t gfp)
+{
+	struct osd_request *or;
+
+	/* TODO: Use mempool with one saved request */
+	or = kzalloc(sizeof(*or), gfp);
+	return or;
+}
+
+static void _osd_request_free(struct osd_request *or)
+{
+	kfree(or);
+}
+
+struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp)
+{
+	struct osd_request *or;
+
+	or = _osd_request_alloc(gfp);
+	if (!or)
+		return NULL;
+
+	or->osd_dev = dev;
+	or->alloc_flags = gfp;
+	or->timeout = dev->def_timeout;
+	or->retries = OSD_REQ_RETRIES;
+
+	return or;
+}
+EXPORT_SYMBOL(osd_start_request);
+
+/*
+ * If osd_finalize_request() was called but the request was not executed through
+ * the block layer, then we must release BIOs.
+ */
+static void _abort_unexecuted_bios(struct request *rq)
+{
+	struct bio *bio;
+
+	while ((bio = rq->bio) != NULL) {
+		rq->bio = bio->bi_next;
+		bio_endio(bio, 0);
+	}
+}
+
+void osd_end_request(struct osd_request *or)
+{
+	struct request *rq = or->request;
+
+	if (rq) {
+		if (rq->next_rq) {
+			_abort_unexecuted_bios(rq->next_rq);
+			blk_put_request(rq->next_rq);
+		}
+
+		_abort_unexecuted_bios(rq);
+		blk_put_request(rq);
+	}
+	_osd_request_free(or);
+}
+EXPORT_SYMBOL(osd_end_request);
+
+int osd_execute_request(struct osd_request *or)
+{
+	return blk_execute_rq(or->request->q, NULL, or->request, 0);
+}
+EXPORT_SYMBOL(osd_execute_request);
+
+static void osd_request_async_done(struct request *req, int error)
+{
+	struct osd_request *or = req->end_io_data;
+
+	or->async_error = error;
+
+	if (error)
+		OSD_DEBUG("osd_request_async_done error recieved %d\n", error);
+
+	if (or->async_done)
+		or->async_done(or, or->async_private);
+	else
+		osd_end_request(or);
+}
+
+int osd_execute_request_async(struct osd_request *or,
+	osd_req_done_fn *done, void *private)
+{
+	or->request->end_io_data = or;
+	or->async_private = private;
+	or->async_done = done;
+
+	blk_execute_rq_nowait(or->request->q, NULL, or->request, 0,
+			      osd_request_async_done);
+	return 0;
+}
+EXPORT_SYMBOL(osd_execute_request_async);
+
+/*
+ * Common to all OSD commands
+ */
+
+static void _osdv1_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv1_cdb *ocdb = &or->cdb.v1;
+
+	/*
+	 * For speed, the commands
+	 *	OSD_ACT_PERFORM_SCSI_COMMAND	, V1 0x8F7E, V2 0x8F7C
+	 *	OSD_ACT_SCSI_TASK_MANAGEMENT	, V1 0x8F7F, V2 0x8F7D
+	 * are not supported here. Should pass zero and set after the call
+	 */
+	act &= cpu_to_be16(~0x0080); /* V1 action code */
+
+	OSD_DEBUG("OSDv1 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v1.length = cpu_to_be64(len);
+	ocdb->h.v1.start_address = cpu_to_be64(offset);
+}
+
+static void _osd_req_encode_common(struct osd_request *or,
+	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	_osdv1_req_encode_common(or, act, obj, offset, len);
+}
+
+/*
+ * Device commands
+ */
+void osd_req_format(struct osd_request *or, u64 tot_capacity)
+{
+	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
+				tot_capacity);
+}
+EXPORT_SYMBOL(osd_req_format);
+
+/*
+ * Partition commands
+ */
+static void _osd_req_encode_partition(struct osd_request *or,
+	__be16 act, osd_id partition)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	_osd_req_encode_common(or, act, &par, 0, 0);
+}
+
+void osd_req_create_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_CREATE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_create_partition);
+
+void osd_req_remove_partition(struct osd_request *or, osd_id partition)
+{
+	_osd_req_encode_partition(or, OSD_ACT_REMOVE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_remove_partition);
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_CREATE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_create_object);
+
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_REMOVE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_remove_object);
+
+void osd_req_write(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, bio->bi_size);
+	WARN_ON(or->out.bio || or->out.total_bytes);
+	bio->bi_rw |= (1 << BIO_RW);
+	or->out.bio = bio;
+	or->out.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_write);
+
+void osd_req_read(struct osd_request *or,
+	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+	_osd_req_encode_common(or, OSD_ACT_READ, obj, offset, bio->bi_size);
+	WARN_ON(or->in.bio || or->in.total_bytes);
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_read);
+
+/*
+ * osd_finalize_request and helpers
+ */
+
+static int _init_blk_request(struct osd_request *or,
+	bool has_in, bool has_out)
+{
+	gfp_t flags = or->alloc_flags;
+	struct scsi_device *scsi_device = or->osd_dev->scsi_device;
+	struct request_queue *q = scsi_device->request_queue;
+	struct request *req;
+	int ret = -ENOMEM;
+
+	req = blk_get_request(q, has_out, flags);
+	if (!req)
+		goto out;
+
+	or->request = req;
+	req->cmd_type = REQ_TYPE_BLOCK_PC;
+	req->timeout = or->timeout;
+	req->retries = or->retries;
+	req->sense = or->sense;
+	req->sense_len = 0;
+
+	if (has_out) {
+		or->out.req = req;
+		if (has_in) {
+			/* allocate bidi request */
+			req = blk_get_request(q, READ, flags);
+			if (!req) {
+				OSD_DEBUG("blk_get_request for bidi failed\n");
+				goto out;
+			}
+			req->cmd_type = REQ_TYPE_BLOCK_PC;
+			or->in.req = or->request->next_rq = req;
+		}
+	} else if (has_in)
+		or->in.req = req;
+
+	ret = 0;
+out:
+	OSD_DEBUG("or=%p has_in=%d has_out=%d => %d, %p\n",
+			or, has_in, has_out, ret, or->request);
+	return ret;
+}
+
+int osd_finalize_request(struct osd_request *or,
+	u8 options, const void *cap, const u8 *cap_key)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	bool has_in, has_out;
+	int ret;
+
+	if (options & OSD_REQ_FUA)
+		cdbh->options |= OSD_CDB_FUA;
+
+	if (options & OSD_REQ_DPO)
+		cdbh->options |= OSD_CDB_DPO;
+
+	if (options & OSD_REQ_BYPASS_TIMESTAMPS)
+		cdbh->timestamp_control = OSD_CDB_BYPASS_TIMESTAMPS;
+
+	osd_set_caps(&or->cdb, cap);
+
+	has_in = or->in.bio || or->get_attr.total_bytes;
+	has_out = or->out.bio || or->set_attr.total_bytes ||
+		or->enc_get_attr.total_bytes;
+
+	ret = _init_blk_request(or, has_in, has_out);
+	if (ret) {
+		OSD_DEBUG("_init_blk_request failed\n");
+		return ret;
+	}
+
+	if (or->out.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->out.req,
+					or->out.bio);
+		if (ret) {
+			OSD_DEBUG("blk_rq_append_bio out failed\n");
+			return ret;
+		}
+		OSD_DEBUG("out bytes=%llu (bytes_req=%u)\n",
+			_LLU(or->out.total_bytes), or->out.req->data_len);
+	}
+	if (or->in.bio) {
+		ret = blk_rq_append_bio(or->request->q, or->in.req, or->in.bio);
+		if (ret) {
+			OSD_DEBUG("blk_rq_append_bio in failed\n");
+			return ret;
+		}
+		OSD_DEBUG("in bytes=%llu (bytes_req=%u)\n",
+			_LLU(or->in.total_bytes), or->in.req->data_len);
+	}
+
+	if (!or->attributes_mode)
+		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+	cdbh->command_specific_options |= or->attributes_mode;
+
+	or->request->cmd = or->cdb.buff;
+	or->request->cmd_len = _osd_req_cdb_len(or);
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_finalize_request);
+
+/*
+ * Implementation of osd_sec.h API
+ * TODO: Move to a separate osd_sec.c file at a later stage.
+ */
+
+enum { OSD_SEC_CAP_V1_ALL_CAPS =
+	OSD_SEC_CAP_APPEND | OSD_SEC_CAP_OBJ_MGMT | OSD_SEC_CAP_REMOVE   |
+	OSD_SEC_CAP_CREATE | OSD_SEC_CAP_SET_ATTR | OSD_SEC_CAP_GET_ATTR |
+	OSD_SEC_CAP_WRITE  | OSD_SEC_CAP_READ     | OSD_SEC_CAP_POL_SEC  |
+	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
+};
+
+void osd_sec_init_nosec_doall_caps(void *caps,
+	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
+{
+	struct osd_capability *cap = caps;
+	u8 type;
+	u8 descriptor_type;
+
+	if (likely(obj->id)) {
+		if (unlikely(is_collection)) {
+			type = OSD_SEC_OBJ_COLLECTION;
+			descriptor_type = is_v1 ? OSD_SEC_OBJ_DESC_OBJ :
+						  OSD_SEC_OBJ_DESC_COL;
+		} else {
+			type = OSD_SEC_OBJ_USER;
+			descriptor_type = OSD_SEC_OBJ_DESC_OBJ;
+		}
+		WARN_ON(!obj->partition);
+	} else {
+		type = obj->partition ? OSD_SEC_OBJ_PARTITION :
+					OSD_SEC_OBJ_ROOT;
+		descriptor_type = OSD_SEC_OBJ_DESC_PAR;
+	}
+
+	memset(cap, 0, sizeof(*cap));
+
+	cap->h.format = OSD_SEC_CAP_FORMAT_VER1;
+	cap->h.integrity_algorithm__key_version = 0; /* MAKE_BYTE(0, 0); */
+	cap->h.security_method = OSD_SEC_NOSEC;
+/*	cap->expiration_time;
+	cap->AUDIT[30-10];
+	cap->discriminator[42-30];
+	cap->object_created_time; */
+	cap->h.object_type = type;
+	osd_sec_set_caps(&cap->h, OSD_SEC_CAP_V1_ALL_CAPS);
+	cap->h.object_descriptor_type = descriptor_type;
+	cap->od.obj_desc.policy_access_tag = 0;
+	cap->od.obj_desc.allowed_partition_id = cpu_to_be64(obj->partition);
+	cap->od.obj_desc.allowed_object_id = cpu_to_be64(obj->id);
+}
+EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
+
+void osd_set_caps(struct osd_cdb *cdb, const void *caps)
+{
+	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+}
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 05/18] osd_uld: OSD scsi ULD
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (3 preceding siblings ...)
  2009-01-06 14:13   ` [PATCH 04/18] libosd: OSDv1 preliminary implementation Boaz Harrosh
@ 2009-01-06 14:14   ` Boaz Harrosh
  2009-01-06 16:47     ` [PATCH ver2 05/16] " Boaz Harrosh
  2009-01-06 14:16   ` [PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel Boaz Harrosh
                     ` (12 subsequent siblings)
  17 siblings, 1 reply; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:14 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Add a Linux driver module that registers as a SCSI ULD and probes
for OSD type SCSI devices.

When an OSD-type SCSI device is found a character device is created
in the form of /dev/osdX - where X goes from 0 up to hard coded 64.
The Major character device number used is *260*, which is free
(as of Linux v2.6.28-rc8).

A single ioctl is currently supported that will invoke an in-kernel
test on the specified OSD device (lun).

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild       |    7 +
 drivers/scsi/osd/osd_ktests.h |   27 +++
 drivers/scsi/osd/osd_uld.c    |  388 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 422 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_ktests.h
 create mode 100644 drivers/scsi/osd/osd_uld.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index 5672842..4730cdc 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -17,6 +17,9 @@ ifneq ($(OSD_INC),)
 CONFIG_SCSI_OSD_INITIATOR=m
 ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
 
+CONFIG_SCSI_OSD_ULD=m
+ccflags-y += -DCONFIG_SCSI_OSD_ULD -DCONFIG_SCSI_OSD_ULD_MODULE
+
 # Uncomment to turn debug on
 # ccflags-y += -DCONFIG_SCSI_OSD_DEBUG
 
@@ -30,3 +33,7 @@ endif
 # libosd.ko - osd-initiator library
 libosd-y := osd_initiator.o
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
+
+# osd.ko - SCSI ULD and char-device
+osd-y := osd_uld.o
+obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
diff --git a/drivers/scsi/osd/osd_ktests.h b/drivers/scsi/osd/osd_ktests.h
new file mode 100644
index 0000000..a9e5e00
--- /dev/null
+++ b/drivers/scsi/osd/osd_ktests.h
@@ -0,0 +1,27 @@
+/*
+ * osd_ktests.h - Define the ktests.c API
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_KTESTS_H__
+#define __OSD_KTESTS_H__
+
+/* Tests from osd_ktests.c */
+/* TODO: Only one simple test for now. Later I will add a test definition
+ *	structure that will define what tests to preform and with some
+ *	parametrization, so concurrent tests could be run on same OSD lun
+ *	without stepping on each other. (E.g. Format called when other tests
+ *	are in progress)
+ */
+
+enum { OSD_TEST_ALL = 17 };
+
+#endif /*ndef __OSD_KTESTS_H__*/
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
new file mode 100644
index 0000000..bd6c018
--- /dev/null
+++ b/drivers/scsi/osd/osd_uld.c
@@ -0,0 +1,388 @@
+/*
+ * osd_uld.c - OSD Upper Layer Driver
+ *
+ * A Linux driver module that registers as a SCSI ULD and probes
+ * for OSD type SCSI devices.
+ * It's main function is to export osd devices to in-kernel users like
+ * osdfs and pNFS-objects-LD. It also provides one ioctl for running
+ * in Kernel tests.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/major.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_ioctl.h>
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+
+#include "osd_ktests.h"
+#include "osd_debug.h"
+
+#ifndef TYPE_OSD
+#  define TYPE_OSD 0x11
+#endif
+
+#ifndef SCSI_OSD_MAJOR
+#  define SCSI_OSD_MAJOR 260
+#endif
+#define SCSI_OSD_MAX_MINOR 64
+
+static const char osd_name[] = "osd";
+static const char *osd_version_string = "open-osd 0.1.0";
+const char osd_symlink[] = "scsi_osd";
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SCSI_OSD_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_OSD);
+
+struct osd_uld_device {
+	int minor;
+	struct kref kref;
+	struct cdev cdev;
+	struct osd_dev od;
+	struct gendisk *disk;
+	struct device *class_member;
+};
+
+static void __uld_get(struct osd_uld_device *oud);
+static void __uld_put(struct osd_uld_device *oud);
+
+/*
+ * Char Device operations
+ */
+
+static int osd_uld_open(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *oud = container_of(inode->i_cdev,
+					struct osd_uld_device, cdev);
+
+	__uld_get(oud);
+	/* cache osd_uld_device on file handle */
+	file->private_data = oud;
+	OSD_DEBUG("osd_uld_open %p\n", oud);
+	return 0;
+}
+
+static int osd_uld_release(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *oud = file->private_data;
+
+	OSD_DEBUG("osd_uld_release %p\n", file->private_data);
+	file->private_data = NULL;
+	__uld_put(oud);
+	return 0;
+}
+
+static long osd_uld_ioctl(struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	struct osd_uld_device *oud = file->private_data;
+	int ret;
+
+	switch (cmd) {
+	case OSD_TEST_ALL:
+		OSD_DEBUG("Kernel test %d: osd_uld_device=%p\n", cmd, oud);
+		ret = 0;
+		break;
+	default:
+		OSD_ERR("Unknown osd_uld_ioctl %d\n", cmd);
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+static const struct file_operations osd_fops = {
+	.owner          = THIS_MODULE,
+	.open           = osd_uld_open,
+	.release        = osd_uld_release,
+	.unlocked_ioctl = osd_uld_ioctl,
+};
+
+/*
+ * Scsi Device operations
+ */
+
+static int __detect_osd(struct osd_uld_device *oud)
+{
+	struct scsi_device *scsi_device = oud->od.scsi_device;
+	int error;
+
+	/* sending a test_unit_ready as first command seems to be needed
+	 * by some targets
+	 */
+	OSD_DEBUG("start scsi_test_unit_ready %p %p %p\n",
+			oud, scsi_device, scsi_device->request_queue);
+	error = scsi_test_unit_ready(scsi_device, 10*HZ, 5, NULL);
+	if (error)
+		OSD_ERR("warning: scsi_test_unit_ready failed\n");
+
+	return 0;
+}
+
+static struct class *osd_sysfs_class;
+static DEFINE_IDA(osd_minor_ida);
+
+static int osd_probe(struct device *dev)
+{
+	struct scsi_device *scsi_device = to_scsi_device(dev);
+	struct gendisk *disk;
+	struct osd_uld_device *oud;
+	int minor;
+	int error;
+
+	if (scsi_device->type != TYPE_OSD)
+		return -ENODEV;
+
+	do {
+		if (!ida_pre_get(&osd_minor_ida, GFP_KERNEL))
+			return -ENODEV;
+
+		error = ida_get_new(&osd_minor_ida, &minor);
+	} while (error == -EAGAIN);
+
+	if (error)
+		return error;
+	if (minor >= SCSI_OSD_MAX_MINOR) {
+		error = -EBUSY;
+		goto err_retract_minor;
+	}
+
+	error = -ENOMEM;
+	oud = kzalloc(sizeof(*oud), GFP_KERNEL);
+	if (NULL == oud)
+		goto err_retract_minor;
+
+	kref_init(&oud->kref);
+	dev_set_drvdata(dev, oud);
+	oud->minor = minor;
+
+	/* allocate a disk and set it up */
+	/* FIXME: do we need this since sg has already done that */
+	disk = alloc_disk(1);
+	if (!disk) {
+		OSD_ERR("alloc_disk failed\n");
+		goto err_free_osd;
+	}
+	disk->major = SCSI_OSD_MAJOR;
+	disk->first_minor = oud->minor;
+	sprintf(disk->disk_name, "osd%d", oud->minor);
+	oud->disk = disk;
+
+	/* hold one more reference to the scsi_device that will get released
+	 * in __release, in case a logout is happening while fs is mounted
+	 */
+	scsi_device_get(scsi_device);
+	osd_dev_init(&oud->od, scsi_device);
+
+	/* Detect the OSD Version */
+	error = __detect_osd(oud);
+	if (error) {
+		OSD_ERR("osd detection failed, non-compatible OSD device\n");
+		goto err_put_disk;
+	}
+
+	/* init the char-device for communication with user-mode */
+	cdev_init(&oud->cdev, &osd_fops);
+	oud->cdev.owner = THIS_MODULE;
+	error = cdev_add(&oud->cdev,
+			 MKDEV(SCSI_OSD_MAJOR, oud->minor), 1);
+	if (error) {
+		OSD_ERR("cdev_add failed\n");
+		goto err_put_disk;
+	}
+	kobject_get(&oud->cdev.kobj); /* 2nd ref see osd_remove() */
+
+	/* class_member */
+	oud->class_member = device_create(osd_sysfs_class, dev,
+		MKDEV(SCSI_OSD_MAJOR, oud->minor), "%s", disk->disk_name);
+	if (IS_ERR(oud->class_member)) {
+		OSD_ERR("class_device_create failed\n");
+		error = PTR_ERR(oud->class_member);
+		goto err_put_cdev;
+	}
+
+	dev_set_drvdata(oud->class_member, oud);
+	error = sysfs_create_link(&scsi_device->sdev_gendev.kobj,
+				  &oud->class_member->kobj, osd_symlink);
+	if (error)
+		OSD_ERR("warning: unable to make symlink\n");
+
+	OSD_INFO("osd_probe %s\n", disk->disk_name);
+	return 0;
+
+err_put_cdev:
+	cdev_del(&oud->cdev);
+err_put_disk:
+	scsi_device_put(scsi_device);
+	put_disk(disk);
+err_free_osd:
+	dev_set_drvdata(dev, NULL);
+	kfree(oud);
+err_retract_minor:
+	ida_remove(&osd_minor_ida, minor);
+	return error;
+}
+
+static int osd_remove(struct device *dev)
+{
+	struct scsi_device *scsi_device = to_scsi_device(dev);
+	struct osd_uld_device *oud = dev_get_drvdata(dev);
+
+	if (!oud || (oud->od.scsi_device != scsi_device)) {
+		OSD_ERR("Half cooked osd-device %p,%p || %p!=%p",
+			dev, oud, oud ? oud->od.scsi_device : NULL,
+			scsi_device);
+	}
+
+	sysfs_remove_link(&oud->od.scsi_device->sdev_gendev.kobj, osd_symlink);
+
+	if (oud->class_member)
+		device_destroy(osd_sysfs_class,
+			       MKDEV(SCSI_OSD_MAJOR, oud->minor));
+
+	/* We have 2 references to the cdev. One is released here
+	 * and also takes down the /dev/osdX mapping. The second
+	 * Will be released in __remove() after all users have released
+	 * the osd_uld_device.
+	 */
+	if (oud->cdev.owner)
+		cdev_del(&oud->cdev);
+
+	__uld_put(oud);
+	return 0;
+}
+
+static void __remove(struct kref *kref)
+{
+	struct osd_uld_device *oud = container_of(kref,
+					struct osd_uld_device, kref);
+	struct scsi_device *scsi_device = oud->od.scsi_device;
+
+	/* now let delete the char_dev */
+	kobject_put(&oud->cdev.kobj);
+
+	osd_dev_fini(&oud->od);
+	scsi_device_put(scsi_device);
+
+	OSD_INFO("osd_remove %s\n",
+		 oud->disk ? oud->disk->disk_name : NULL);
+
+	if (oud->disk)
+		put_disk(oud->disk);
+
+	ida_remove(&osd_minor_ida, oud->minor);
+	kfree(oud);
+}
+
+static void __uld_get(struct osd_uld_device *oud)
+{
+	kref_get(&oud->kref);
+}
+
+static void __uld_put(struct osd_uld_device *oud)
+{
+	kref_put(&oud->kref, __remove);
+}
+
+/*
+ * Global driver and scsi registration
+ */
+
+static struct scsi_driver osd_driver = {
+	.owner			= THIS_MODULE,
+	.gendrv = {
+		.name		= osd_name,
+		.probe		= osd_probe,
+		.remove		= osd_remove,
+	}
+};
+
+static int __init osd_uld_init(void)
+{
+	int err;
+
+	osd_sysfs_class = class_create(THIS_MODULE, osd_symlink);
+	if (IS_ERR(osd_sysfs_class)) {
+		OSD_ERR("Unable to register sysfs class => %ld\n",
+			PTR_ERR(osd_sysfs_class));
+		return PTR_ERR(osd_sysfs_class);
+	}
+
+	err = register_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0),
+				     SCSI_OSD_MAX_MINOR, osd_name);
+	if (err) {
+		OSD_ERR("Unable to register major %d for osd ULD => %d\n",
+			SCSI_OSD_MAJOR, err);
+		goto err_out;
+	}
+
+	err = scsi_register_driver(&osd_driver.gendrv);
+	if (err) {
+		OSD_ERR("scsi_register_driver failed => %d\n", err);
+		goto err_out_chrdev;
+	}
+
+	OSD_INFO("LOADED %s\n", osd_version_string);
+	return 0;
+
+err_out_chrdev:
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+err_out:
+	class_destroy(osd_sysfs_class);
+	return err;
+}
+
+static void __exit osd_uld_exit(void)
+{
+	scsi_unregister_driver(&osd_driver.gendrv);
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+	class_destroy(osd_sysfs_class);
+	OSD_INFO("UNLOADED %s\n", osd_version_string);
+}
+
+module_init(osd_uld_init);
+module_exit(osd_uld_exit);
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (4 preceding siblings ...)
  2009-01-06 14:14   ` [PATCH 05/18] osd_uld: OSD scsi ULD Boaz Harrosh
@ 2009-01-06 14:16   ` Boaz Harrosh
  2009-01-06 14:17   ` [PATCH 07/18] osd_ktests: Add basic OSD tests Boaz Harrosh
                     ` (11 subsequent siblings)
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:16 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Kernel clients like exofs can retrieve struct osd_dev(s)
by means of below API.

+ osduld_path_lookup() - given a path (e.g "/dev/osd0") locks and
returns the corresponding struct osd_dev, which is then needed
for subsequent libosd use.

+ osduld_put_device() - free up use of an osd_dev.

Devices can be shared by multiple clients. The osd_uld_device's
life time is governed by an embedded kref structure.

The osd_uld_device holds an extra reference to both it's
char-device and it's scsi_device, and will release these just
before the final deallocation.

There are three possible lock sources of the osd_uld_device
1. First and for most is the probe() function called by
  scsi-ml upon a successful login into a target. Released in release()
  when logout.
2. Second by user-mode file handles opened on the char-dev.
3. Third is here by Kernel users.
All three locks must be removed before the osd_uld_device is freed.

The MODULE has three lock sources as well:
1. scsi-ml at probe() time, removed after release(). (login/logout)
2. The user-mode file handles open/close.
3. Import symbols by client modules like exofs.

TODO:
  This API is not enough for the pNFS-objects LD. A more versatile
  API will be needed. Proposed API could be:
  struct osd_dev *osduld_sysid_lookup(const char id[OSD_SYSTEMID_LEN]);

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/osd/osd_uld.c   |   64 ++++++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_initiator.h |    5 +++
 2 files changed, 69 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index bd6c018..b8cb141 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -42,6 +42,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <linux/namei.h>
 #include <linux/cdev.h>
 #include <linux/fs.h>
 #include <linux/module.h>
@@ -142,6 +143,69 @@ static const struct file_operations osd_fops = {
 	.unlocked_ioctl = osd_uld_ioctl,
 };
 
+struct osd_dev *osduld_path_lookup(const char *path)
+{
+	struct nameidata nd;
+	struct inode *inode;
+	struct cdev *cdev;
+	struct osd_uld_device *uninitialized_var(oud);
+	int error;
+
+	if (!path || !*path) {
+		OSD_ERR("Mount with !path || !*path\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	error = path_lookup(path, LOOKUP_FOLLOW, &nd);
+	if (error) {
+		OSD_ERR("path_lookup of %s faild=>%d\n", path, error);
+		return ERR_PTR(error);
+	}
+
+	inode = nd.path.dentry->d_inode;
+	error = -EINVAL; /* Not the right device e.g osd_uld_device */
+	if (!S_ISCHR(inode->i_mode)) {
+		OSD_DEBUG("!S_ISCHR()\n");
+		goto out;
+	}
+
+	cdev = inode->i_cdev;
+	if (!cdev) {
+		OSD_ERR("Before mounting an OSD Based filesystem\n");
+		OSD_ERR("  user-mode must open+close the %s device\n", path);
+		OSD_ERR("  Example: bash: echo < %s\n", path);
+		goto out;
+	}
+
+	/* The Magic wand. Is it our char-dev */
+	/* TODO: Support sg devices */
+	if (cdev->owner != THIS_MODULE) {
+		OSD_ERR("Error mounting %s - is not an OSD device\n", path);
+		goto out;
+	}
+
+	oud = container_of(cdev, struct osd_uld_device, cdev);
+
+	__uld_get(oud);
+	error = 0;
+
+out:
+	path_put(&nd.path);
+	return error ? ERR_PTR(error) : &oud->od;
+}
+EXPORT_SYMBOL(osduld_path_lookup);
+
+void osduld_put_device(struct osd_dev *od)
+{
+	if (od) {
+		struct osd_uld_device *oud = container_of(od,
+						struct osd_uld_device, od);
+
+		__uld_put(oud);
+	}
+}
+EXPORT_SYMBOL(osduld_put_device);
+
 /*
  * Scsi Device operations
  */
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 1d92247..93fa86b 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -33,6 +33,11 @@ struct osd_dev {
 	unsigned def_timeout;
 };
 
+/* Retrieve/return osd_dev(s) for use by Kernel clients */
+struct osd_dev *osduld_path_lookup(const char *dev_name); /*Use IS_ERR/ERR_PTR*/
+void osduld_put_device(struct osd_dev *od);
+
+/* These are called by uld at probe time */
 void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
 void osd_dev_fini(struct osd_dev *od);
 
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 07/18] osd_ktests: Add basic OSD tests
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (5 preceding siblings ...)
  2009-01-06 14:16   ` [PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel Boaz Harrosh
@ 2009-01-06 14:17   ` Boaz Harrosh
  2009-01-06 14:42     ` FUJITA Tomonori
  2009-01-06 16:49     ` Boaz Harrosh
  2009-01-06 14:19   ` [PATCH 08/18] libosd: attributes Support Boaz Harrosh
                     ` (10 subsequent siblings)
  17 siblings, 2 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:17 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Currently testing what is implemented in the osd_initiator library.
That is - format, create/remove partition, create/remove object,
read and write to objects.

This test passes against the IBM-OSD-SIM OSDv1 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild       |    2 +-
 drivers/scsi/osd/osd_ktests.c |  331 +++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/osd/osd_ktests.h |    4 +
 drivers/scsi/osd/osd_uld.c    |    2 +-
 4 files changed, 337 insertions(+), 2 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_ktests.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index 4730cdc..6fb823f 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -35,5 +35,5 @@ libosd-y := osd_initiator.o
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
 
 # osd.ko - SCSI ULD and char-device
-osd-y := osd_uld.o
+osd-y := osd_uld.o osd_ktests.o
 obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
new file mode 100644
index 0000000..fba4934
--- /dev/null
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -0,0 +1,331 @@
+/*
+ * osd_ktests.c - An osd_initiator library in-kernel test suite
+ *              called by the osd_uld module
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <asm/unaligned.h>
+#include <linux/vmalloc.h>
+#include <scsi/scsi_device.h>
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+
+#include "osd_ktests.h"
+#include "osd_debug.h"
+
+enum {
+	K = 1024,
+	M = 1024 * K,
+	G = 1024 * M,
+};
+
+const u64 format_total_capacity = 128 * M;
+const osd_id first_par_id = 0x17171717L;
+const osd_id first_obj_id = 0x18181818L;
+const unsigned BUFF_SIZE = PAGE_SIZE;
+
+const int num_partitions = 1;
+const int num_objects = 2; /* per partition */
+
+int test_exec(struct osd_request *or, void *caps, const struct osd_obj_id *obj)
+{
+	int ret;
+
+	osd_sec_init_nosec_doall_caps(caps, obj, false, true);
+	ret = osd_finalize_request(or, 0, caps, NULL);
+	if (ret)
+		return ret;
+
+	ret = osd_execute_request(or);
+	/* osd_req_decode_sense(or, ret); */
+	return ret;
+}
+
+#define KTEST_START_REQ(osd_dev, or) do { \
+	or = osd_start_request(osd_dev, GFP_KERNEL); \
+	if (!or) { \
+		OSD_ERR("Error @%s:%d: osd_start_request", __func__,\
+			__LINE__); \
+		return -ENOMEM; \
+	} \
+} while (0)
+
+#define KTEST_EXEC_END(or, obj, g_caps, msg) do { \
+	ret = test_exec(or, g_caps, obj); \
+	osd_end_request(or); \
+	if (ret) { \
+		OSD_ERR("Error executing "msg" => %d\n", ret); \
+		return ret; \
+	} \
+	OSD_DEBUG(msg "\n"); \
+} while (0)
+
+int ktest_format(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+
+	KTEST_START_REQ(osd_dev, or);
+	osd_req_format(or, format_total_capacity);
+	KTEST_EXEC_END(or, &osd_root_object, g_caps, "format");
+	return 0;
+}
+
+int ktest_creat_par(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p;
+
+	for (p = 0; p < num_partitions; p++) {
+		struct osd_obj_id par = {
+			.partition = first_par_id + p,
+			.id = 0
+		};
+
+		KTEST_START_REQ(osd_dev, or);
+		osd_req_create_partition(or, par.partition);
+		KTEST_EXEC_END(or, &par, g_caps, "create_partition");
+	}
+
+	return 0;
+}
+
+int ktest_creat_obj(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			osd_req_create_object(or, &obj);
+			KTEST_EXEC_END(or, &obj, g_caps, "create_object");
+		}
+
+	return 0;
+}
+
+int ktest_write_obj(struct osd_dev *osd_dev, void *write_buff)
+{
+	struct request_queue *req_q = osd_dev->scsi_device->request_queue;
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o; u64 offset = 0;
+	struct bio *write_bio;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			write_bio = bio_map_kern(req_q, write_buff,
+						 BUFF_SIZE, GFP_KERNEL);
+			if (!write_bio) {
+				OSD_ERR("!!! Failed to allocate write BIO\n");
+				return -ENOMEM;
+			}
+
+			osd_req_write(or, &obj, write_bio, offset);
+			KTEST_EXEC_END(or, &obj, g_caps, "write");
+			write_bio = NULL; /* released by scsi_midlayer */
+			offset += BUFF_SIZE;
+		}
+
+	return 0;
+}
+
+int ktest_read_obj(struct osd_dev *osd_dev, void *write_buff, void *read_buff)
+{
+	struct request_queue *req_q = osd_dev->scsi_device->request_queue;
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o; u64 offset = 0;
+	struct bio *read_bio;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			read_bio = bio_map_kern(req_q, read_buff,
+						BUFF_SIZE, GFP_KERNEL);
+			if (!read_bio) {
+				OSD_ERR("!!! Failed to allocate read BIO\n");
+				return -ENOMEM;
+			}
+
+			osd_req_read(or, &obj, read_bio, offset);
+			KTEST_EXEC_END(or, &obj, g_caps, "read");
+			read_bio = NULL;
+			if (memcmp(read_buff, write_buff, BUFF_SIZE))
+				OSD_ERR("!!! Read did not compare");
+			offset += BUFF_SIZE;
+		}
+
+	return 0;
+}
+
+int ktest_remove_obj(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p, o;
+
+	for (p = 0; p < num_partitions; p++)
+		for (o = 0; o < num_objects; o++) {
+			struct osd_obj_id obj = {
+				.partition = first_par_id + p,
+				.id = first_obj_id + o
+			};
+
+			KTEST_START_REQ(osd_dev, or);
+			osd_req_remove_object(or, &obj);
+			KTEST_EXEC_END(or, &obj, g_caps, "remove_object");
+		}
+
+	return 0;
+}
+
+int ktest_remove_par(struct osd_dev *osd_dev)
+{
+	struct osd_request *or;
+	u8 g_caps[OSD_CAP_LEN];
+	int ret;
+	int p;
+
+	for (p = 0; p < num_partitions; p++) {
+		struct osd_obj_id par = {
+			.partition = first_par_id + p,
+			.id = 0
+		};
+
+		KTEST_START_REQ(osd_dev, or);
+		osd_req_remove_partition(or, par.partition);
+		KTEST_EXEC_END(or, &par, g_caps, "remove_partition");
+	}
+
+	return 0;
+}
+
+int do_test_17(struct osd_dev *od)
+{
+	void *write_buff = NULL;
+	void *read_buff = NULL;
+	int ret = -ENOMEM, i;
+
+/* osd_format */
+	if (ktest_format(od))
+		goto dev_fini;
+
+/* create some partition */
+	if (ktest_creat_par(od))
+		goto dev_fini;
+/* list partition see if they're all there */
+/* create some objects on some partitions */
+	if (ktest_creat_obj(od))
+		goto dev_fini;
+
+/* Alloc some buffers and bios */
+/*	write_buff = kmalloc(BUFF_SIZE, or->alloc_flags);*/
+/*	read_buff = kmalloc(BUFF_SIZE, or->alloc_flags);*/
+	write_buff = (void *)__get_free_page(GFP_KERNEL);
+	read_buff = (void *)__get_free_page(GFP_KERNEL);
+	if (!write_buff || !read_buff) {
+		OSD_ERR("!!! Failed to allocate memory for test\n");
+		goto dev_fini;
+	}
+	for (i = 0; i < BUFF_SIZE / 4; i++)
+		((int *)write_buff)[i] = i;
+	OSD_DEBUG("allocate buffers\n");
+
+/* write to objects */
+	ret = ktest_write_obj(od, write_buff);
+	if (ret)
+		goto dev_fini;
+
+/* read from objects and compare to write */
+	ret = ktest_read_obj(od, write_buff, read_buff);
+	if (ret)
+		goto dev_fini;
+
+/* List all objects */
+
+/* Write with get_attr */
+/* Write with set_attr */
+/* Write with set_attr + get_attr */
+/* Read with set_attr */
+/* Read with get_attr */
+/* Read with get_attr + set_attr */
+/* remove objects */
+	ret = ktest_remove_obj(od);
+	if (ret)
+		goto dev_fini;
+
+/* remove partitions */
+	ret = ktest_remove_par(od);
+	if (ret)
+		goto dev_fini;
+
+/* good and done */
+	OSD_INFO("test17: All good and done\n");
+dev_fini:
+	if (read_buff)
+		free_page((ulong)read_buff);
+	if (write_buff)
+		free_page((ulong)write_buff);
+
+	return ret;
+}
diff --git a/drivers/scsi/osd/osd_ktests.h b/drivers/scsi/osd/osd_ktests.h
index a9e5e00..b625ee5 100644
--- a/drivers/scsi/osd/osd_ktests.h
+++ b/drivers/scsi/osd/osd_ktests.h
@@ -24,4 +24,8 @@
 
 enum { OSD_TEST_ALL = 17 };
 
+#ifdef __KERNEL__
+extern int do_test_17(struct osd_dev *od);
+#endif /* __KERNEL__ */
+
 #endif /*ndef __OSD_KTESTS_H__*/
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index b8cb141..5ba7654 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -127,7 +127,7 @@ static long osd_uld_ioctl(struct file *file, unsigned int cmd,
 	switch (cmd) {
 	case OSD_TEST_ALL:
 		OSD_DEBUG("Kernel test %d: osd_uld_device=%p\n", cmd, oud);
-		ret = 0;
+		ret = do_test_17(&oud->od);
 		break;
 	default:
 		OSD_ERR("Unknown osd_uld_ioctl %d\n", cmd);
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 08/18] libosd: attributes Support
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (6 preceding siblings ...)
  2009-01-06 14:17   ` [PATCH 07/18] osd_ktests: Add basic OSD tests Boaz Harrosh
@ 2009-01-06 14:19   ` Boaz Harrosh
  2009-01-06 14:20   ` [PATCH 09/18] osd_ktests: Test Attribute lists Boaz Harrosh
                     ` (9 subsequent siblings)
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:19 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Support for both List-Mode and Page-Mode osd attributes. One of
these operations may be added to most other operations.

Define the OSD standard's attribute pages constants and structures
(osd_attributes.h)

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  574 ++++++++++++++++++++++++++++++++++++++
 include/scsi/osd_attributes.h    |  327 ++++++++++++++++++++++
 2 files changed, 901 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_attributes.h

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 0e6d906..68cf0ac 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -63,6 +63,50 @@ static unsigned _osd_req_cdb_len(struct osd_request *or)
 	return OSDv1_TOTAL_CDB_LEN;
 }
 
+static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
+{
+	return osdv1_attr_list_elem_size(len);
+}
+
+static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
+{
+	return osdv1_list_size(list_head);
+}
+
+static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
+{
+	return sizeof(struct osdv1_attributes_list_header);
+}
+
+static void _osd_req_set_alist_type(struct osd_request *or,
+	void *list, int list_type)
+{
+	struct osdv1_attributes_list_header *attr_list = list;
+
+	memset(attr_list, 0, sizeof(*attr_list));
+	attr_list->type = list_type;
+}
+
+static bool _osd_req_is_alist_type(struct osd_request *or,
+	void *list, int list_type)
+{
+	if (!list)
+		return false;
+
+	if (1) {
+		struct osdv1_attributes_list_header *attr_list = list;
+
+		return attr_list->type == list_type;
+	}
+}
+
+static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
+	u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
 {
 	memset(osdd, 0, sizeof(*osdd));
@@ -125,10 +169,25 @@ static void _abort_unexecuted_bios(struct request *rq)
 	}
 }
 
+static void _osd_free_seg(struct osd_request *or,
+	struct _osd_req_data_segment *seg)
+{
+	if (!seg->buff || !seg->alloc_size)
+		return;
+
+	kfree(seg->buff);
+	seg->buff = NULL;
+	seg->alloc_size = 0;
+}
+
 void osd_end_request(struct osd_request *or)
 {
 	struct request *rq = or->request;
 
+	_osd_free_seg(or, &or->set_attr);
+	_osd_free_seg(or, &or->enc_get_attr);
+	_osd_free_seg(or, &or->get_attr);
+
 	if (rq) {
 		if (rq->next_rq) {
 			_abort_unexecuted_bios(rq->next_rq);
@@ -176,6 +235,54 @@ int osd_execute_request_async(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_execute_request_async);
 
+u8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+u8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+
+static int _osd_realloc_seg(struct osd_request *or,
+	struct _osd_req_data_segment *seg, unsigned max_bytes)
+{
+	void *buff;
+
+	if (seg->alloc_size >= max_bytes)
+		return 0;
+
+	buff = krealloc(seg->buff, max_bytes, or->alloc_flags);
+	if (!buff) {
+		OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes,
+			seg->alloc_size);
+		return -ENOMEM;
+	}
+
+	memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size);
+	seg->buff = buff;
+	seg->alloc_size = max_bytes;
+	return 0;
+}
+
+static int _alloc_set_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem, unsigned add_bytes)
+{
+	unsigned total_bytes = add_bytes;
+
+	for (; nelem; --nelem, ++oa)
+		total_bytes += _osd_req_alist_elem_size(or, oa->len);
+
+	OSD_DEBUG("total_bytes=%d\n", total_bytes);
+	return _osd_realloc_seg(or, &or->set_attr, total_bytes);
+}
+
+static int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes)
+{
+	OSD_DEBUG("total_bytes=%d\n", max_bytes);
+	return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes);
+}
+
+static int _alloc_get_attr_list(struct osd_request *or)
+{
+	OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes);
+	return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes);
+}
+
 /*
  * Common to all OSD commands
  */
@@ -284,6 +391,409 @@ void osd_req_read(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_read);
 
+void osd_req_get_attributes(struct osd_request *or,
+	const struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_get_attributes);
+
+void osd_req_set_attributes(struct osd_request *or,
+	const struct osd_obj_id *obj)
+{
+	_osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_set_attributes);
+
+/*
+ * Attributes List-mode
+ */
+
+int osd_req_add_set_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem)
+{
+	unsigned total_bytes = or->set_attr.total_bytes;
+	void *attr_last;
+	int ret;
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+	if (!total_bytes) { /* first-time: allocate and put list header */
+		total_bytes = _osd_req_sizeof_alist_header(or);
+		ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+		if (ret)
+			return ret;
+		_osd_req_set_alist_type(or, or->set_attr.buff,
+					OSD_ATTR_LIST_SET_RETRIEVE);
+	}
+	attr_last = or->set_attr.buff + total_bytes;
+
+	for (; nelem; --nelem) {
+		struct osd_attributes_list_element *attr;
+		unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
+
+		total_bytes += elem_size;
+		if (unlikely(or->set_attr.alloc_size < total_bytes)) {
+			or->set_attr.total_bytes = total_bytes - elem_size;
+			ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+			if (ret)
+				return ret;
+			attr_last =
+				or->set_attr.buff + or->set_attr.total_bytes;
+		}
+
+		attr = attr_last;
+		attr->attr_page = cpu_to_be32(oa->attr_page);
+		attr->attr_id = cpu_to_be32(oa->attr_id);
+		attr->attr_bytes = cpu_to_be16(oa->len);
+		memcpy(attr->attr_val, oa->val_ptr, oa->len);
+
+		attr_last += elem_size;
+		++oa;
+	}
+
+	or->set_attr.total_bytes = total_bytes;
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_set_attr_list);
+
+static int _append_map_kern(struct request *req,
+	void *buff, unsigned len, gfp_t flags)
+{
+	struct bio *bio;
+	int ret;
+
+	bio = bio_map_kern(req->q, buff, len, flags);
+	if (IS_ERR(bio)) {
+		OSD_ERR("Failed bio_map_kern(%p, %d) => %ld\n", buff, len,
+			PTR_ERR(bio));
+		return PTR_ERR(bio);
+	}
+	ret = blk_rq_append_bio(req->q, req, bio);
+	if (ret) {
+		OSD_ERR("Failed blk_rq_append_bio(%p) => %d\n", bio, ret);
+		bio_put(bio);
+	}
+	return ret;
+}
+
+static int _req_append_segment(struct osd_request *or,
+	int padding, struct _osd_req_data_segment *seg,
+	struct _osd_req_data_segment *last_seg, struct _osd_io_info *io)
+{
+	void *pad_buff;
+	int ret;
+
+	if (padding) {
+		/* check if we can just add it to last buffer */
+		if (last_seg &&
+		    (padding <= last_seg->alloc_size - last_seg->total_bytes))
+			pad_buff = last_seg->buff + last_seg->total_bytes;
+		else
+			pad_buff = io->pad_buff;
+
+		ret = _append_map_kern(io->req, pad_buff, padding,
+				       or->alloc_flags);
+		if (ret)
+			return ret;
+		io->total_bytes += padding;
+	}
+
+	ret = _append_map_kern(io->req, seg->buff, seg->total_bytes,
+			       or->alloc_flags);
+	if (ret)
+		return ret;
+
+	io->total_bytes += seg->total_bytes;
+	OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff,
+		  seg->total_bytes);
+	return 0;
+}
+
+static int _osd_req_finalize_set_attr_list(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	int padding;
+	int ret;
+
+	if (!or->set_attr.total_bytes) {
+		cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED;
+		return 0;
+	}
+
+	cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes);
+	cdbh->attrs_list.set_attr_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &padding);
+
+	ret = _req_append_segment(or, padding, &or->set_attr,
+				  or->out.last_seg, &or->out);
+	if (ret)
+		return ret;
+
+	or->out.last_seg = &or->set_attr;
+	return 0;
+}
+
+int osd_req_add_get_attr_list(struct osd_request *or,
+	const struct osd_attr *oa, unsigned nelem)
+{
+	unsigned total_bytes = or->enc_get_attr.total_bytes;
+	void *attr_last;
+	int ret;
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+	/* first time calc data-in list header size */
+	if (!or->get_attr.total_bytes)
+		or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or);
+
+	/* calc data-out info */
+	if (!total_bytes) { /* first-time: allocate and put list header */
+		unsigned max_bytes;
+
+		total_bytes = _osd_req_sizeof_alist_header(or);
+		max_bytes = total_bytes +
+			nelem * sizeof(struct osd_attributes_list_attrid);
+		ret = _alloc_get_attr_desc(or, max_bytes);
+		if (ret)
+			return ret;
+
+		_osd_req_set_alist_type(or, or->enc_get_attr.buff,
+					OSD_ATTR_LIST_GET);
+	}
+	attr_last = or->enc_get_attr.buff + total_bytes;
+
+	for (; nelem; --nelem) {
+		struct osd_attributes_list_attrid *attrid;
+		const unsigned cur_size = sizeof(*attrid);
+
+		total_bytes += cur_size;
+		if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) {
+			or->enc_get_attr.total_bytes = total_bytes - cur_size;
+			ret = _alloc_get_attr_desc(or,
+					total_bytes + nelem * sizeof(*attrid));
+			if (ret)
+				return ret;
+			attr_last = or->enc_get_attr.buff +
+				or->enc_get_attr.total_bytes;
+		}
+
+		attrid = attr_last;
+		attrid->attr_page = cpu_to_be32(oa->attr_page);
+		attrid->attr_id = cpu_to_be32(oa->attr_id);
+
+		attr_last += cur_size;
+
+		/* calc data-in size */
+		or->get_attr.total_bytes +=
+			_osd_req_alist_elem_size(or, oa->len);
+		++oa;
+	}
+
+	or->enc_get_attr.total_bytes = total_bytes;
+
+	OSD_DEBUG(
+	       "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n",
+	       or->get_attr.total_bytes,
+	       or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or),
+	       or->enc_get_attr.total_bytes,
+	       (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or))
+			/ sizeof(struct osd_attributes_list_attrid));
+
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_list);
+
+static int _osd_req_finalize_get_attr_list(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	unsigned out_padding;
+	unsigned in_padding;
+	int ret;
+
+	if (!or->enc_get_attr.total_bytes) {
+		cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED;
+		cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED;
+		return 0;
+	}
+
+	ret = _alloc_get_attr_list(or);
+	if (ret)
+		return ret;
+
+	/* The out-going buffer info update */
+	OSD_DEBUG("out-going\n");
+	cdbh->attrs_list.get_attr_desc_bytes =
+		cpu_to_be32(or->enc_get_attr.total_bytes);
+
+	cdbh->attrs_list.get_attr_desc_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+	ret = _req_append_segment(or, out_padding, &or->enc_get_attr,
+				  or->out.last_seg, &or->out);
+	if (ret)
+		return ret;
+	or->out.last_seg = &or->enc_get_attr;
+
+	/* The incoming buffer info update */
+	OSD_DEBUG("in-coming\n");
+	cdbh->attrs_list.get_attr_alloc_length =
+		cpu_to_be32(or->get_attr.total_bytes);
+
+	cdbh->attrs_list.get_attr_offset =
+		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+				  &or->in);
+	if (ret)
+		return ret;
+	or->in.last_seg = &or->get_attr;
+
+	return 0;
+}
+
+int osd_req_decode_get_attr_list(struct osd_request *or,
+	struct osd_attr *oa, int *nelem, void **iterator)
+{
+	unsigned cur_bytes, returned_bytes, n;
+	const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or);
+	void *cur_p;
+
+	if (!_osd_req_is_alist_type(or, or->get_attr.buff,
+				    OSD_ATTR_LIST_SET_RETRIEVE)) {
+		oa->attr_page = 0;
+		oa->attr_id = 0;
+		oa->val_ptr = NULL;
+		oa->len = 0;
+		*iterator = NULL;
+		return 0;
+	}
+
+	if (*iterator) {
+		BUG_ON((*iterator < or->get_attr.buff) ||
+		     (or->get_attr.buff + or->get_attr.alloc_size < *iterator));
+		cur_p = *iterator;
+		cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list;
+		returned_bytes = or->get_attr.total_bytes;
+	} else { /* first time decode the list header */
+		cur_bytes = sizeof_attr_list;
+		returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) +
+					sizeof_attr_list;
+
+		cur_p = or->get_attr.buff + sizeof_attr_list;
+
+		if (returned_bytes > or->get_attr.alloc_size) {
+			OSD_DEBUG("target report: space was not big enough! "
+				  "Allocate=%u Needed=%u\n",
+				  or->get_attr.alloc_size,
+				  returned_bytes + sizeof_attr_list);
+
+			returned_bytes =
+				or->get_attr.alloc_size - sizeof_attr_list;
+		}
+		or->get_attr.total_bytes = returned_bytes;
+	}
+
+	for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
+		struct osd_attributes_list_element *attr = cur_p;
+		unsigned inc;
+
+		oa->len = be16_to_cpu(attr->attr_bytes);
+		inc = _osd_req_alist_elem_size(or, oa->len);
+		OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n",
+			  oa->len, inc, cur_bytes);
+		cur_bytes += inc;
+		if (cur_bytes > returned_bytes) {
+			OSD_ERR("BAD FOOD from target. list not valid!"
+				"c=%d r=%d n=%d\n",
+				cur_bytes, returned_bytes, n);
+			oa->val_ptr = NULL;
+			break;
+		}
+
+		oa->attr_page = be32_to_cpu(attr->attr_page);
+		oa->attr_id = be32_to_cpu(attr->attr_id);
+		oa->val_ptr = attr->attr_val;
+
+		cur_p += inc;
+		++oa;
+	}
+
+	*iterator = (returned_bytes - cur_bytes) ? cur_p : NULL;
+	*nelem = n;
+	return returned_bytes - cur_bytes;
+}
+EXPORT_SYMBOL(osd_req_decode_get_attr_list);
+
+/*
+ * Attributes Page-mode
+ */
+
+int osd_req_add_get_attr_page(struct osd_request *or,
+	u32 page_id, void *attar_page, unsigned max_page_len,
+	const struct osd_attr *set_one_attr)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+	if (or->attributes_mode &&
+	    or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE;
+
+	or->get_attr.buff = attar_page;
+	or->get_attr.total_bytes = max_page_len;
+
+	or->set_attr.buff = set_one_attr->val_ptr;
+	or->set_attr.total_bytes = set_one_attr->len;
+
+	cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id);
+	cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len);
+	/* ocdb->attrs_page.get_attr_offset; */
+
+	cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->attr_page);
+	cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id);
+	cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len);
+	/* ocdb->attrs_page.set_attr_offset; */
+	return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_page);
+
+static int _osd_req_finalize_attr_page(struct osd_request *or)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+	int in_padding, out_padding;
+	int ret;
+
+	/* returned page */
+	cdbh->attrs_page.get_attr_offset =
+		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+				  &or->in);
+	if (ret)
+		return ret;
+
+	/* set one value */
+	cdbh->attrs_page.set_attr_offset =
+		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+	ret = _req_append_segment(or, out_padding, &or->enc_get_attr, NULL,
+				  &or->out);
+	return ret;
+}
+
 /*
  * osd_finalize_request and helpers
  */
@@ -378,9 +888,31 @@ int osd_finalize_request(struct osd_request *or,
 			_LLU(or->in.total_bytes), or->in.req->data_len);
 	}
 
+	or->out.pad_buff = sg_out_pad_buffer;
+	or->in.pad_buff = sg_in_pad_buffer;
+
 	if (!or->attributes_mode)
 		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
 	cdbh->command_specific_options |= or->attributes_mode;
+	if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+		ret = _osd_req_finalize_attr_page(or);
+	} else {
+		/* TODO: I think that for the GET_ATTR command these 2 should
+		 * be reversed to keep them in execution order (for embeded
+		 * targets with low memory footprint)
+		 */
+		ret = _osd_req_finalize_set_attr_list(or);
+		if (ret) {
+			OSD_DEBUG("_osd_req_finalize_set_attr_list failed\n");
+			return ret;
+		}
+
+		ret = _osd_req_finalize_get_attr_list(or);
+		if (ret) {
+			OSD_DEBUG("_osd_req_finalize_get_attr_list failed\n");
+			return ret;
+		}
+	}
 
 	or->request->cmd = or->cdb.buff;
 	or->request->cmd_len = _osd_req_cdb_len(or);
@@ -446,3 +978,45 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 {
 	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
 }
+
+/*
+ * Declared in osd_protocol.h
+ * 4.12.5 Data-In and Data-Out buffer offsets
+ * byte offset = mantissa * (2^(exponent+8))
+ * Returns the smallest allowed encoded offset that contains given @offset
+ * The actual encoded offset returned is @offset + *@padding.
+ */
+osd_cdb_offset __osd_encode_offset(
+	u64 offset, unsigned *padding, int min_shift, int max_shift)
+{
+	u64 try_offset = -1, mod, align;
+	osd_cdb_offset be32_offset;
+	int shift;
+
+	*padding = 0;
+	if (!offset)
+		return 0;
+
+	for (shift = min_shift; shift < max_shift; ++shift) {
+		try_offset = offset >> shift;
+		if (try_offset < (1 << OSD_OFFSET_MAX_BITS))
+			break;
+	}
+
+	BUG_ON(shift == max_shift);
+
+	align = 1 << shift;
+	mod = offset & (align - 1);
+	if (mod) {
+		*padding = align - mod;
+		try_offset += 1;
+	}
+
+	try_offset |= ((shift - 8) & 0xf) << 28;
+	be32_offset = cpu_to_be32((u32)try_offset);
+
+	OSD_DEBUG("offset=%llu mantissa=%llu exp=%d encoded=%x pad=%d\n",
+		 _LLU(offset), _LLU(try_offset & 0x0FFFFFFF), shift,
+		 be32_offset, *padding);
+	return be32_offset;
+}
diff --git a/include/scsi/osd_attributes.h b/include/scsi/osd_attributes.h
new file mode 100644
index 0000000..f888a6f
--- /dev/null
+++ b/include/scsi/osd_attributes.h
@@ -0,0 +1,327 @@
+#ifndef __OSD_ATTRIBUTES_H__
+#define __OSD_ATTRIBUTES_H__
+
+#include "osd_protocol.h"
+
+/*
+ * Contains types and constants that define attribute pages and attribute
+ * numbers and their data types.
+ */
+
+#define ATTR_SET(pg, id, l, ptr) \
+	{ .attr_page = pg, .attr_id = id, .len = l, .val_ptr = ptr }
+
+#define ATTR_DEF(pg, id, l) ATTR_SET(pg, id, l, NULL)
+
+/* osd-r10 4.7.3 Attributes pages */
+enum {
+	OSD_APAGE_OBJECT_FIRST		= 0x0,
+	OSD_APAGE_OBJECT_DIRECTORY	= 0,
+	OSD_APAGE_OBJECT_INFORMATION	= 1,
+	OSD_APAGE_OBJECT_QUOTAS		= 2,
+	OSD_APAGE_OBJECT_TIMESTAMP	= 3,
+	OSD_APAGE_OBJECT_COLLECTIONS	= 4,
+	OSD_APAGE_OBJECT_SECURITY	= 5,
+	OSD_APAGE_OBJECT_LAST		= 0x2fffffff,
+
+	OSD_APAGE_PARTITION_FIRST	= 0x30000000,
+	OSD_APAGE_PARTITION_DIRECTORY	= OSD_APAGE_PARTITION_FIRST + 0,
+	OSD_APAGE_PARTITION_INFORMATION = OSD_APAGE_PARTITION_FIRST + 1,
+	OSD_APAGE_PARTITION_QUOTAS	= OSD_APAGE_PARTITION_FIRST + 2,
+	OSD_APAGE_PARTITION_TIMESTAMP	= OSD_APAGE_PARTITION_FIRST + 3,
+	OSD_APAGE_PARTITION_SECURITY	= OSD_APAGE_PARTITION_FIRST + 5,
+	OSD_APAGE_PARTITION_LAST	= 0x5FFFFFFF,
+
+	OSD_APAGE_COLLECTION_FIRST	= 0x60000000,
+	OSD_APAGE_COLLECTION_DIRECTORY	= OSD_APAGE_COLLECTION_FIRST + 0,
+	OSD_APAGE_COLLECTION_INFORMATION = OSD_APAGE_COLLECTION_FIRST + 1,
+	OSD_APAGE_COLLECTION_TIMESTAMP	= OSD_APAGE_COLLECTION_FIRST + 3,
+	OSD_APAGE_COLLECTION_SECURITY	= OSD_APAGE_COLLECTION_FIRST + 5,
+	OSD_APAGE_COLLECTION_LAST	= 0x8FFFFFFF,
+
+	OSD_APAGE_ROOT_FIRST		= 0x90000000,
+	OSD_APAGE_ROOT_DIRECTORY	= OSD_APAGE_ROOT_FIRST + 0,
+	OSD_APAGE_ROOT_INFORMATION	= OSD_APAGE_ROOT_FIRST + 1,
+	OSD_APAGE_ROOT_QUOTAS		= OSD_APAGE_ROOT_FIRST + 2,
+	OSD_APAGE_ROOT_TIMESTAMP	= OSD_APAGE_ROOT_FIRST + 3,
+	OSD_APAGE_ROOT_SECURITY		= OSD_APAGE_ROOT_FIRST + 5,
+	OSD_APAGE_ROOT_LAST		= 0xBFFFFFFF,
+
+	OSD_APAGE_RESERVED_TYPE_FIRST	= 0xC0000000,
+	OSD_APAGE_RESERVED_TYPE_LAST	= 0xEFFFFFFF,
+
+	OSD_APAGE_COMMON_FIRST		= 0xF0000000,
+	OSD_APAGE_COMMON_LAST		= 0xFFFFFFFE,
+
+	OSD_APAGE_REQUEST_ALL		= 0xFFFFFFFF,
+};
+
+/* subcategories of attr pages within each range above */
+enum {
+	OSD_APAGE_STD_FIRST		= 0x0,
+	OSD_APAGE_STD_DIRECTORY		= 0,
+	OSD_APAGE_STD_INFORMATION	= 1,
+	OSD_APAGE_STD_QUOTAS		= 2,
+	OSD_APAGE_STD_TIMESTAMP		= 3,
+	OSD_APAGE_STD_COLLECTIONS	= 4,
+	OSD_APAGE_STD_POLICY_SECURITY	= 5,
+	OSD_APAGE_STD_LAST		= 0x0000007F,
+
+	OSD_APAGE_RESERVED_FIRST	= 0x00000080,
+	OSD_APAGE_RESERVED_LAST		= 0x00007FFF,
+
+	OSD_APAGE_OTHER_STD_FIRST	= 0x00008000,
+	OSD_APAGE_OTHER_STD_LAST	= 0x0000EFFF,
+
+	OSD_APAGE_PUBLIC_FIRST		= 0x0000F000,
+	OSD_APAGE_PUBLIC_LAST		= 0x0000FFFF,
+
+	OSD_APAGE_APP_DEFINED_FIRST	= 0x00010000,
+	OSD_APAGE_APP_DEFINED_LAST	= 0x1FFFFFFF,
+
+	OSD_APAGE_VENDOR_SPECIFIC_FIRST	= 0x20000000,
+	OSD_APAGE_VENDOR_SPECIFIC_LAST	= 0x2FFFFFFF,
+};
+
+enum {
+	OSD_ATTR_PAGE_IDENTIFICATION = 0, /* in all pages 40 bytes */
+};
+
+struct page_identification {
+	u8 vendor_identification[8];
+	u8 page_identification[32];
+}  __packed;
+
+struct osd_attr_page_header {
+	__be32 page_number;
+	__be32 page_length;
+} __packed;
+
+/* 7.1.2.8 Root Information attributes page (OSD_APAGE_ROOT_INFORMATION) */
+enum {
+	OSD_ATTR_RI_OSD_SYSTEM_ID            = 0x3,   /* 20       */
+	OSD_ATTR_RI_VENDOR_IDENTIFICATION    = 0x4,   /* 8        */
+	OSD_ATTR_RI_PRODUCT_IDENTIFICATION   = 0x5,   /* 16       */
+	OSD_ATTR_RI_PRODUCT_MODEL            = 0x6,   /* 32       */
+	OSD_ATTR_RI_PRODUCT_REVISION_LEVEL   = 0x7,   /* 4        */
+	OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER    = 0x8,   /* variable */
+	OSD_ATTR_RI_OSD_NAME                 = 0x9,   /* variable */
+	OSD_ATTR_RI_TOTAL_CAPACITY           = 0x80,  /* 8        */
+	OSD_ATTR_RI_USED_CAPACITY            = 0x81,  /* 8        */
+	OSD_ATTR_RI_NUMBER_OF_PARTITIONS     = 0xC0,  /* 8        */
+	OSD_ATTR_RI_CLOCK                    = 0x100, /* 6        */
+};
+/* Root_Information_attributes_page does not have a get_page structure */
+
+/* 7.1.2.9 Partition Information attributes page
+ * (OSD_APAGE_PARTITION_INFORMATION)
+ */
+enum {
+	OSD_ATTR_PI_PARTITION_ID            = 0x1,     /* 8        */
+	OSD_ATTR_PI_USERNAME                = 0x9,     /* variable */
+	OSD_ATTR_PI_USED_CAPACITY           = 0x81,    /* 8        */
+	OSD_ATTR_PI_NUMBER_OF_OBJECTS       = 0xC1,    /* 8        */
+};
+/* Partition Information attributes page does not have a get_page structure */
+
+/* 7.1.2.10 Collection Information attributes page
+ * (OSD_APAGE_COLLECTION_INFORMATION)
+ */
+enum {
+	OSD_ATTR_CI_PARTITION_ID           = 0x1,       /* 8        */
+	OSD_ATTR_CI_COLLECTION_OBJECT_ID   = 0x2,       /* 8        */
+	OSD_ATTR_CI_USERNAME               = 0x9,       /* variable */
+	OSD_ATTR_CI_USED_CAPACITY          = 0x81,      /* 8        */
+};
+/* Collection Information attributes page does not have a get_page structure */
+
+/* 7.1.2.11 User Object Information attributes page
+ * (OSD_APAGE_OBJECT_INFORMATION)
+ */
+enum {
+	OSD_ATTR_OI_PARTITION_ID         = 0x1,       /* 8        */
+	OSD_ATTR_OI_OBJECT_ID            = 0x2,       /* 8        */
+	OSD_ATTR_OI_USERNAME             = 0x9,       /* variable */
+	OSD_ATTR_OI_USED_CAPACITY        = 0x81,      /* 8        */
+	OSD_ATTR_OI_LOGICAL_LENGTH       = 0x82,      /* 8        */
+};
+/* Object Information attributes page does not have a get_page structure */
+
+/* 7.1.2.12 Root Quotas attributes page (OSD_APAGE_ROOT_QUOTAS) */
+enum {
+	OSD_ATTR_RQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH     = 0x1,      /* 8  */
+	OSD_ATTR_RQ_PARTITION_CAPACITY_QUOTA               = 0x10001,  /* 8  */
+	OSD_ATTR_RQ_PARTITION_OBJECT_COUNT                 = 0x10002,  /* 8  */
+	OSD_ATTR_RQ_PARTITION_COLLECTIONS_PER_USER_OBJECT  = 0x10081,  /* 4  */
+	OSD_ATTR_RQ_PARTITION_COUNT                        = 0x20002,  /* 8  */
+};
+
+struct Root_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+2, size=0x24 */
+	__be64 default_maximum_user_object_length;
+	__be64 partition_capacity_quota;
+	__be64 partition_object_count;
+	__be64 partition_collections_per_user_object;
+	__be64 partition_count;
+}  __packed;
+
+/* 7.1.2.13 Partition Quotas attributes page (OSD_APAGE_PARTITION_QUOTAS)*/
+enum {
+	OSD_ATTR_PQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH  = 0x1,        /* 8 */
+	OSD_ATTR_PQ_CAPACITY_QUOTA                      = 0x10001,    /* 8 */
+	OSD_ATTR_PQ_OBJECT_COUNT                        = 0x10002,    /* 8 */
+	OSD_ATTR_PQ_COLLECTIONS_PER_USER_OBJECT         = 0x10081,    /* 4 */
+};
+
+struct Partition_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=P+2, size=0x1C */
+	__be64 default_maximum_user_object_length;
+	__be64 capacity_quota;
+	__be64 object_count;
+	__be64 collections_per_user_object;
+}  __packed;
+
+/* 7.1.2.14 User Object Quotas attributes page (OSD_APAGE_OBJECT_QUOTAS) */
+enum {
+	OSD_ATTR_OQ_MAXIMUM_LENGTH  = 0x1,        /* 8 */
+};
+
+struct Object_Quotas_attributes_page {
+	struct osd_attr_page_header hdr; /* id=U+2, size=0x8 */
+	__be64 maximum_length;
+}  __packed;
+
+/* 7.1.2.15 Root Timestamps attributes page (OSD_APAGE_ROOT_TIMESTAMP) */
+enum {
+	OSD_ATTR_RT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_RT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_RT_TIMESTAMP_BYPASS          = 0xFFFFFFFE, /* 1 */
+};
+
+struct root_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+3, size=0xD */
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	u8 timestamp_bypass;
+}  __packed;
+
+/* 7.1.2.16 Partition Timestamps attributes page
+ * (OSD_APAGE_PARTITION_TIMESTAMP)
+ */
+enum {
+	OSD_ATTR_PT_CREATED_TIME              = 0x1,        /* 6 */
+	OSD_ATTR_PT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_PT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_PT_DATA_ACCESSED_TIME        = 0x4,        /* 6 */
+	OSD_ATTR_PT_DATA_MODIFIED_TIME        = 0x5,        /* 6 */
+	OSD_ATTR_PT_TIMESTAMP_BYPASS          = 0xFFFFFFFE, /* 1 */
+};
+
+struct partition_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=P+3, size=0x1F */
+	struct osd_timestamp created_time;
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	struct osd_timestamp data_accessed_time;
+	struct osd_timestamp data_modified_time;
+	u8 timestamp_bypass;
+}  __packed;
+
+/* 7.1.2.17/18 Collection/Object Timestamps attributes page
+ * (OSD_APAGE_COLLECTION_TIMESTAMP/OSD_APAGE_OBJECT_TIMESTAMP)
+ */
+enum {
+	OSD_ATTR_OT_CREATED_TIME              = 0x1,        /* 6 */
+	OSD_ATTR_OT_ATTRIBUTES_ACCESSED_TIME  = 0x2,        /* 6 */
+	OSD_ATTR_OT_ATTRIBUTES_MODIFIED_TIME  = 0x3,        /* 6 */
+	OSD_ATTR_OT_DATA_ACCESSED_TIME        = 0x4,        /* 6 */
+	OSD_ATTR_OT_DATA_MODIFIED_TIME        = 0x5,        /* 6 */
+};
+
+/* same for collection */
+struct object_timestamps_attributes_page {
+	struct osd_attr_page_header hdr; /* id=C+3/3, size=0x1E */
+	struct osd_timestamp created_time;
+	struct osd_timestamp attributes_accessed_time;
+	struct osd_timestamp attributes_modified_time;
+	struct osd_timestamp data_accessed_time;
+	struct osd_timestamp data_modified_time;
+}  __packed;
+
+/* 7.1.2.19 Collections attributes page */
+/* TBD */
+
+/* 7.1.2.20 Root Policy/Security attributes page (OSD_APAGE_ROOT_SECURITY) */
+enum {
+	OSD_ATTR_RS_DEFAULT_SECURITY_METHOD           = 0x1,       /* 1      */
+	OSD_ATTR_RS_OLDEST_VALID_NONCE_LIMIT          = 0x2,       /* 6      */
+	OSD_ATTR_RS_NEWEST_VALID_NONCE_LIMIT          = 0x3,       /* 6      */
+	OSD_ATTR_RS_PARTITION_DEFAULT_SECURITY_METHOD = 0x6,       /* 1      */
+	OSD_ATTR_RS_SUPPORTED_SECURITY_METHODS        = 0x7,       /* 2      */
+	OSD_ATTR_RS_ADJUSTABLE_CLOCK                  = 0x9,       /* 6      */
+	OSD_ATTR_RS_MASTER_KEY_IDENTIFIER             = 0x7FFD,    /* 0 or 7 */
+	OSD_ATTR_RS_ROOT_KEY_IDENTIFIER               = 0x7FFE,    /* 0 or 7 */
+	OSD_ATTR_RS_SUPPORTED_INTEGRITY_ALGORITHM_0   = 0x80000000,/* 1,(x16)*/
+	OSD_ATTR_RS_SUPPORTED_DH_GROUP_0              = 0x80000010,/* 1,(x16)*/
+};
+
+struct root_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=R+5, size=0x3F */
+	u8 default_security_method;
+	u8 partition_default_security_method;
+	__be16 supported_security_methods;
+	u8 mki_valid_rki_valid;
+	struct osd_timestamp oldest_valid_nonce_limit;
+	struct osd_timestamp newest_valid_nonce_limit;
+	struct osd_timestamp adjustable_clock;
+	u8 master_key_identifier[32-25];
+	u8 root_key_identifier[39-32];
+	u8 supported_integrity_algorithm[16];
+	u8 supported_dh_group[16];
+}  __packed;
+
+/* 7.1.2.21 Partition Policy/Security attributes page
+ * (OSD_APAGE_PARTITION_SECURITY)
+ */
+enum {
+	OSD_ATTR_PS_DEFAULT_SECURITY_METHOD        = 0x1,        /* 1      */
+	OSD_ATTR_PS_OLDEST_VALID_NONCE             = 0x2,        /* 6      */
+	OSD_ATTR_PS_NEWEST_VALID_NONCE             = 0x3,        /* 6      */
+	OSD_ATTR_PS_REQUEST_NONCE_LIST_DEPTH       = 0x4,        /* 2      */
+	OSD_ATTR_PS_FROZEN_WORKING_KEY_BIT_MASK    = 0x5,        /* 2      */
+	OSD_ATTR_PS_PARTITION_KEY_IDENTIFIER       = 0x7FFF,     /* 0 or 7 */
+	OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_FIRST   = 0x8000,     /* 0 or 7 */
+	OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_LAST    = 0x800F,     /* 0 or 7 */
+	OSD_ATTR_PS_POLICY_ACCESS_TAG              = 0x40000001, /* 4      */
+	OSD_ATTR_PS_USER_OBJECT_POLICY_ACCESS_TAG  = 0x40000002, /* 4      */
+};
+
+struct partition_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=p+5, size=0x8f */
+	u8 reserved[3];
+	u8 default_security_method;
+	struct osd_timestamp oldest_valid_nonce;
+	struct osd_timestamp newest_valid_nonce;
+	__be16 request_nonce_list_depth;
+	__be16 frozen_working_key_bit_mask;
+	__be32 policy_access_tag;
+	__be32 user_object_policy_access_tag;
+	u8 pki_valid;
+	__be16 wki_00_0f_vld;
+	struct osd_key_identifier partition_key_identifier;
+	struct osd_key_identifier working_key_identifiers[16];
+}  __packed;
+
+/* 7.1.2.22/23 Collection/Object Policy-Security attributes page
+ * (OSD_APAGE_COLLECTION_SECURITY/OSD_APAGE_OBJECT_SECURITY)
+ */
+enum {
+	OSD_ATTR_OS_POLICY_ACCESS_TAG              = 0x40000001, /* 4      */
+};
+
+struct object_security_attributes_page {
+	struct osd_attr_page_header hdr; /* id=C+5/5, size=4 */
+	__be32 policy_access_tag;
+}  __packed;
+
+#endif /*ndef __OSD_ATTRIBUTES_H__*/
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 09/18] osd_ktests: Test Attribute lists
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (7 preceding siblings ...)
  2009-01-06 14:19   ` [PATCH 08/18] libosd: attributes Support Boaz Harrosh
@ 2009-01-06 14:20   ` Boaz Harrosh
  2009-01-06 16:50     ` Boaz Harrosh
  2009-01-06 14:21   ` [PATCH 10/18] libosd: OSD Security processing stubs Boaz Harrosh
                     ` (8 subsequent siblings)
  17 siblings, 1 reply; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:20 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Add tests for setting/getting Attribute lists. All combinations
of read/write with set/get attributes are tested.
(6 possibilities), So all but data integrity request structure
layouts are attempted.

This test passes against the IBM-OSD-SIM OSDv1 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_ktests.c |  110 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
index fba4934..d098323 100644
--- a/drivers/scsi/osd/osd_ktests.c
+++ b/drivers/scsi/osd/osd_ktests.c
@@ -43,6 +43,7 @@
 
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
+#include <scsi/osd_attributes.h>
 
 #include "osd_ktests.h"
 #include "osd_debug.h"
@@ -260,6 +261,91 @@ int ktest_remove_par(struct osd_dev *osd_dev)
 	return 0;
 }
 
+int ktest_write_read_attr(struct osd_dev *osd_dev, void *buff,
+	bool doread, bool doset, bool doget)
+{
+	struct request_queue *req_q = osd_dev->scsi_device->request_queue;
+	struct osd_request *or;
+	char g_caps[OSD_CAP_LEN];
+	int ret;
+	struct bio *bio;
+	char *domsg;
+	/* set attrs */
+	static char name[] = "ktest_write_read_attr";
+	__be64 max_len = cpu_to_be64(0x80000000L);
+	struct osd_obj_id obj = {
+		.partition = first_par_id,
+		.id = first_obj_id,
+	};
+	struct osd_attr set_attrs[] = {
+		ATTR_SET(OSD_APAGE_OBJECT_QUOTAS, OSD_ATTR_OQ_MAXIMUM_LENGTH,
+			sizeof(max_len), &max_len),
+		ATTR_SET(OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_USERNAME,
+			sizeof(name), name),
+	};
+	struct osd_attr get_attrs[] = {
+		ATTR_DEF(OSD_APAGE_OBJECT_INFORMATION,
+			OSD_ATTR_OI_USED_CAPACITY, sizeof(__be64)),
+		ATTR_DEF(OSD_APAGE_OBJECT_INFORMATION,
+			OSD_ATTR_OI_LOGICAL_LENGTH, sizeof(__be64)),
+	};
+
+	KTEST_START_REQ(osd_dev, or);
+	bio = bio_map_kern(req_q, buff, BUFF_SIZE, GFP_KERNEL);
+	if (!bio) {
+		OSD_ERR("!!! Failed to allocate BIO\n");
+		return -ENOMEM;
+	}
+
+	if (doread) {
+		osd_req_read(or, &obj, bio, 0);
+		domsg = "Read-with-attr";
+	} else {
+		osd_req_write(or, &obj, bio, 0);
+		domsg = "Write-with-attr";
+	}
+
+	if (doset)
+		osd_req_add_set_attr_list(or, set_attrs, 2);
+	if (doget)
+		osd_req_add_get_attr_list(or, get_attrs, 2);
+
+/*	KTEST_EXEC_END(or, &obj, "");*/
+	ret = test_exec(or, g_caps, &obj);
+	if (!ret && doget) {
+		void *iter = NULL, *pFirst, *pSec;
+		int nelem = 2;
+		u64 capacity_len = ~0;
+		u64 logical_len = ~0;
+
+		osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+		/*FIXME: Std does not guaranty order of return attrs */
+		pFirst = get_attrs[0].val_ptr;
+		if (pFirst)
+			capacity_len = get_unaligned_be64(pFirst);
+		else
+			OSD_ERR("failed to read capacity_used\n");
+		pSec = get_attrs[1].val_ptr;
+		if (pSec)
+			logical_len = get_unaligned_be64(pSec);
+		else
+			OSD_ERR("failed to read logical_length\n");
+		OSD_INFO("%s capacity=%llu len=%llu\n",
+			domsg, _LLU(capacity_len), _LLU(logical_len));
+	}
+
+	osd_end_request(or);
+	if (ret) {
+		OSD_ERR("!!! Error executing %s => %d doset=%d doget=%d\n",
+			domsg, ret, doset, doget);
+		return ret;
+	}
+	OSD_DEBUG("%s\n", domsg);
+
+	return 0;
+}
+
 int do_test_17(struct osd_dev *od)
 {
 	void *write_buff = NULL;
@@ -304,11 +390,35 @@ int do_test_17(struct osd_dev *od)
 /* List all objects */
 
 /* Write with get_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, false, true);
+	if (ret)
+		goto dev_fini;
+
 /* Write with set_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, true, false);
+	if (ret)
+		goto dev_fini;
+
 /* Write with set_attr + get_attr */
+	ret = ktest_write_read_attr(od, write_buff, false, true, true);
+	if (ret)
+		goto dev_fini;
+
 /* Read with set_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, true, false);
+	if (ret)
+		goto dev_fini;
+
 /* Read with get_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, false, true);
+	if (ret)
+		goto dev_fini;
+
 /* Read with get_attr + set_attr */
+	ret = ktest_write_read_attr(od, write_buff, true, true, true);
+	if (ret)
+		goto dev_fini;
+
 /* remove objects */
 	ret = ktest_remove_obj(od);
 	if (ret)
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 10/18] libosd: OSD Security processing stubs
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (8 preceding siblings ...)
  2009-01-06 14:20   ` [PATCH 09/18] osd_ktests: Test Attribute lists Boaz Harrosh
@ 2009-01-06 14:21   ` Boaz Harrosh
  2009-01-06 14:23   ` [PATCH 11/18] libosd: Add Flush and List-objects support Boaz Harrosh
                     ` (7 subsequent siblings)
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:21 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Layout the signing of OSD's CDB and all-data security modes. The actual
code for signing the data and CDB is missing, but the code flow and the extra
buffer segments are all in place.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   85 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 85 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 68cf0ac..367337c 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -107,6 +107,14 @@ static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
 }
 
+static struct osd_security_parameters *
+_osd_req_sec_params(struct osd_request *or)
+{
+	struct osd_cdb *ocdb = &or->cdb;
+
+	return &ocdb->v1.sec_params;
+}
+
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
 {
 	memset(osdd, 0, sizeof(*osdd));
@@ -794,6 +802,64 @@ static int _osd_req_finalize_attr_page(struct osd_request *or)
 	return ret;
 }
 
+static int _osd_req_finalize_data_integrity(struct osd_request *or,
+	bool has_in, bool has_out, const u8 *cap_key)
+{
+	struct osd_security_parameters *sec_parms = _osd_req_sec_params(or);
+	int ret;
+
+	if (!osd_is_sec_alldata(sec_parms))
+		return 0;
+
+	if (has_out) {
+		struct _osd_req_data_segment seg = {
+			.buff = &or->out_data_integ,
+			.total_bytes = sizeof(or->out_data_integ),
+		};
+		int pad;
+
+		or->out_data_integ.data_bytes = cpu_to_be64(
+			or->out.bio ? or->out.bio->bi_size : 0);
+		or->out_data_integ.set_attributes_bytes = cpu_to_be64(
+			or->set_attr.total_bytes);
+		or->out_data_integ.get_attributes_bytes = cpu_to_be64(
+			or->enc_get_attr.total_bytes);
+
+		sec_parms->data_out_integrity_check_offset =
+			osd_req_encode_offset(or, or->out.total_bytes, &pad);
+
+		ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
+					  &or->out);
+		if (ret)
+			return ret;
+		or->out.last_seg = NULL;
+
+		/* they are now all chained to request sign them all together */
+		osd_sec_sign_data(&or->out_data_integ, or->out.req->bio,
+				  cap_key);
+	}
+
+	if (has_in) {
+		struct _osd_req_data_segment seg = {
+			.buff = &or->in_data_integ,
+			.total_bytes = sizeof(or->in_data_integ),
+		};
+		int pad;
+
+		sec_parms->data_in_integrity_check_offset =
+			osd_req_encode_offset(or, or->in.total_bytes, &pad);
+
+		ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
+					  &or->in);
+		if (ret)
+			return ret;
+
+		or->in.last_seg = NULL;
+	}
+
+	return 0;
+}
+
 /*
  * osd_finalize_request and helpers
  */
@@ -914,6 +980,12 @@ int osd_finalize_request(struct osd_request *or,
 		}
 	}
 
+	ret = _osd_req_finalize_data_integrity(or, has_in, has_out, cap_key);
+	if (ret)
+		return ret;
+
+	osd_sec_sign_cdb(&or->cdb, cap_key);
+
 	or->request->cmd = or->cdb.buff;
 	or->request->cmd_len = _osd_req_cdb_len(or);
 
@@ -979,6 +1051,19 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
 }
 
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms)
+{
+	return false;
+}
+
+void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key)
+{
+}
+
+void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key)
+{
+}
+
 /*
  * Declared in osd_protocol.h
  * 4.12.5 Data-In and Data-Out buffer offsets
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 11/18] libosd: Add Flush and List-objects support
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (9 preceding siblings ...)
  2009-01-06 14:21   ` [PATCH 10/18] libosd: OSD Security processing stubs Boaz Harrosh
@ 2009-01-06 14:23   ` Boaz Harrosh
  2009-01-06 14:24   ` [PATCH 12/18] libosd: Not implemented commands Boaz Harrosh
                     ` (6 subsequent siblings)
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:23 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Add support for the various List-objects commands. List-partitions-in-device,
List-collections-in-partition, List-objects-in-partition,
List-objects-in-collection. All these support partial listing and continuation.

Add support for the different Flush commands and options.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  124 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 124 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 367337c..d892400 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -100,6 +100,16 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
 	}
 }
 
+/* This is for List-objects not Attributes-Lists */
+static void _osd_req_encode_olist(struct osd_request *or,
+	struct osd_obj_id_list *list)
+{
+	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+	cdbh->v1.list_identifier = list->list_identifier;
+	cdbh->v1.start_address = list->continuation_id;
+}
+
 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 	u64 offset, unsigned *padding)
 {
@@ -336,6 +346,29 @@ void osd_req_format(struct osd_request *or, u64 tot_capacity)
 }
 EXPORT_SYMBOL(osd_req_format);
 
+int osd_req_list_dev_partitions(struct osd_request *or,
+	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem)
+{
+	return osd_req_list_partition_objects(or, 0, initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_dev_partitions);
+
+static void _osd_req_encode_flush(struct osd_request *or,
+	enum osd_options_flush_scope_values op)
+{
+	struct osd_cdb_head *ocdb = osd_cdb_head(&or->cdb);
+
+	ocdb->command_specific_options = op;
+}
+
+void osd_req_flush_obsd(struct osd_request *or,
+	enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH_OSD, &osd_root_object, 0, 0);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_obsd);
+
 /*
  * Partition commands
  */
@@ -362,6 +395,88 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition)
 }
 EXPORT_SYMBOL(osd_req_remove_partition);
 
+static int _osd_req_list_objects(struct osd_request *or,
+	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem)
+{
+	struct request_queue *q = or->osd_dev->scsi_device->request_queue;
+	u64 len = nelem * sizeof(osd_id) + sizeof(*list);
+	struct bio *bio;
+
+	_osd_req_encode_common(or, action, obj, (u64)initial_id, len);
+
+	if (list->list_identifier)
+		_osd_req_encode_olist(or, list);
+
+	WARN_ON(or->in.bio);
+	bio = bio_map_kern(q, list, len, or->alloc_flags);
+	if (!bio) {
+		OSD_ERR("!!! Failed to allocate list_objects BIO\n");
+		return -ENOMEM;
+	}
+
+	bio->bi_rw &= ~(1 << BIO_RW);
+	or->in.bio = bio;
+	or->in.total_bytes = bio->bi_size;
+	return 0;
+}
+
+int osd_req_list_partition_collections(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	return osd_req_list_collection_objects(or, &par, initial_id, list,
+					       nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_collections);
+
+int osd_req_list_partition_objects(struct osd_request *or,
+	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+	unsigned nelem)
+{
+	struct osd_obj_id par = {
+		.partition = partition,
+		.id = 0,
+	};
+
+	return _osd_req_list_objects(or, OSD_ACT_LIST, &par, initial_id, list,
+				     nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_objects);
+
+void osd_req_flush_partition(struct osd_request *or,
+	osd_id partition, enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_partition(or, OSD_ACT_FLUSH_PARTITION, partition);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_partition);
+
+/*
+ * Collection commands
+ */
+int osd_req_list_collection_objects(struct osd_request *or,
+	const struct osd_obj_id *obj, osd_id initial_id,
+	struct osd_obj_id_list *list, unsigned nelem)
+{
+	return _osd_req_list_objects(or, OSD_ACT_LIST_COLLECTION, obj,
+				     initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_collection_objects);
+
+void osd_req_flush_collection(struct osd_request *or,
+	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH_PARTITION, obj, 0, 0);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_collection);
+
 /*
  * Object commands
  */
@@ -388,6 +503,15 @@ void osd_req_write(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_write);
 
+void osd_req_flush_object(struct osd_request *or,
+	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
+	/*V2*/ u64 offset, /*V2*/ u64 len)
+{
+	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
+	_osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_object);
+
 void osd_req_read(struct osd_request *or,
 	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
 {
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 12/18] libosd: Not implemented commands
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (10 preceding siblings ...)
  2009-01-06 14:23   ` [PATCH 11/18] libosd: Add Flush and List-objects support Boaz Harrosh
@ 2009-01-06 14:24   ` Boaz Harrosh
  2009-01-06 14:25   ` [PATCH 13/18] libosd: OSD version 2 Support Boaz Harrosh
                     ` (5 subsequent siblings)
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:24 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Some commands declared in header are not yet implemented. Put them
as stubs in .c file, just so they take their place in the file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   35 +++++++++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index d892400..f064c2e 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -339,6 +339,9 @@ static void _osd_req_encode_common(struct osd_request *or,
 /*
  * Device commands
  */
+/*TODO: void osd_req_set_master_seed_xchg(struct osd_request *, ...); */
+/*TODO: void osd_req_set_master_key(struct osd_request *, ...); */
+
 void osd_req_format(struct osd_request *or, u64 tot_capacity)
 {
 	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
@@ -369,6 +372,10 @@ void osd_req_flush_obsd(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_flush_obsd);
 
+/*TODO: void osd_req_perform_scsi_command(struct osd_request *,
+	const u8 *cdb, ...); */
+/*TODO: void osd_req_task_management(struct osd_request *, ...); */
+
 /*
  * Partition commands
  */
@@ -395,6 +402,10 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition)
 }
 EXPORT_SYMBOL(osd_req_remove_partition);
 
+/*TODO: void osd_req_set_partition_key(struct osd_request *,
+	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+	u8 seed[OSD_CRYPTO_SEED_SIZE]); */
+
 static int _osd_req_list_objects(struct osd_request *or,
 	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
 	struct osd_obj_id_list *list, unsigned nelem)
@@ -460,6 +471,11 @@ EXPORT_SYMBOL(osd_req_flush_partition);
 /*
  * Collection commands
  */
+/*TODO: void osd_req_create_collection(struct osd_request *,
+	const struct osd_obj_id *); */
+/*TODO: void osd_req_remove_collection(struct osd_request *,
+	const struct osd_obj_id *); */
+
 int osd_req_list_collection_objects(struct osd_request *or,
 	const struct osd_obj_id *obj, osd_id initial_id,
 	struct osd_obj_id_list *list, unsigned nelem)
@@ -469,6 +485,8 @@ int osd_req_list_collection_objects(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_list_collection_objects);
 
+/*TODO: void query(struct osd_request *, ...); V2 */
+
 void osd_req_flush_collection(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
 {
@@ -477,6 +495,9 @@ void osd_req_flush_collection(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_flush_collection);
 
+/*TODO: void get_member_attrs(struct osd_request *, ...); V2 */
+/*TODO: void set_member_attrs(struct osd_request *, ...); V2 */
+
 /*
  * Object commands
  */
@@ -492,6 +513,11 @@ void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
 }
 EXPORT_SYMBOL(osd_req_remove_object);
 
+
+/*TODO: void osd_req_create_multi(struct osd_request *or,
+	struct osd_obj_id *first, struct osd_obj_id_list *list, unsigned nelem);
+*/
+
 void osd_req_write(struct osd_request *or,
 	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
 {
@@ -503,6 +529,15 @@ void osd_req_write(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_req_write);
 
+/*TODO: void osd_req_append(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out); */
+/*TODO: void osd_req_create_write(struct osd_request *,
+	const struct osd_obj_id *, struct bio *data_out, u64 offset); */
+/*TODO: void osd_req_clear(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len); */
+/*TODO: void osd_req_punch(struct osd_request *,
+	const struct osd_obj_id *, u64 offset, u64 len); V2 */
+
 void osd_req_flush_object(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
 	/*V2*/ u64 offset, /*V2*/ u64 len)
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 13/18] libosd: OSD version 2 Support
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (11 preceding siblings ...)
  2009-01-06 14:24   ` [PATCH 12/18] libosd: Not implemented commands Boaz Harrosh
@ 2009-01-06 14:25   ` Boaz Harrosh
  2009-01-06 14:27   ` [PATCH 14/18] libosd: OSDv2 auto detection Boaz Harrosh
                     ` (4 subsequent siblings)
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:25 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Add support for OSD2 at run time. It is now possible to run with
both OSDv1 and OSDv2 targets at the same time. The actual detection
should be preformed by the security manager, as the version is encoded
in the capability structure.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |   94 ++++++++++++++++++++++++++++++++------
 include/scsi/osd_initiator.h     |   39 ++++++++++++++++
 include/scsi/osd_protocol.h      |   90 ++++++++++++++++++++++++++++++++++--
 3 files changed, 205 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index f064c2e..6bda439 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -55,36 +55,50 @@ static inline void build_test(void)
 {
 	/* structures were not packed */
 	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+	BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
 	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
 }
 
 static unsigned _osd_req_cdb_len(struct osd_request *or)
 {
-	return OSDv1_TOTAL_CDB_LEN;
+	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
 }
 
 static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
 {
-	return osdv1_attr_list_elem_size(len);
+	return osd_req_is_ver1(or) ?
+		osdv1_attr_list_elem_size(len) :
+		osdv2_attr_list_elem_size(len);
 }
 
 static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
 {
-	return osdv1_list_size(list_head);
+	return osd_req_is_ver1(or) ?
+		osdv1_list_size(list_head) :
+		osdv2_list_size(list_head);
 }
 
 static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
 {
-	return sizeof(struct osdv1_attributes_list_header);
+	return osd_req_is_ver1(or) ?
+		sizeof(struct osdv1_attributes_list_header) :
+		sizeof(struct osdv2_attributes_list_header);
 }
 
 static void _osd_req_set_alist_type(struct osd_request *or,
 	void *list, int list_type)
 {
-	struct osdv1_attributes_list_header *attr_list = list;
+	if (osd_req_is_ver1(or)) {
+		struct osdv1_attributes_list_header *attr_list = list;
+
+		memset(attr_list, 0, sizeof(*attr_list));
+		attr_list->type = list_type;
+	} else {
+		struct osdv2_attributes_list_header *attr_list = list;
 
-	memset(attr_list, 0, sizeof(*attr_list));
-	attr_list->type = list_type;
+		memset(attr_list, 0, sizeof(*attr_list));
+		attr_list->type = list_type;
+	}
 }
 
 static bool _osd_req_is_alist_type(struct osd_request *or,
@@ -93,10 +107,14 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
 	if (!list)
 		return false;
 
-	if (1) {
+	if (osd_req_is_ver1(or)) {
 		struct osdv1_attributes_list_header *attr_list = list;
 
 		return attr_list->type == list_type;
+	} else {
+		struct osdv2_attributes_list_header *attr_list = list;
+
+		return attr_list->type == list_type;
 	}
 }
 
@@ -106,15 +124,22 @@ static void _osd_req_encode_olist(struct osd_request *or,
 {
 	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
 
-	cdbh->v1.list_identifier = list->list_identifier;
-	cdbh->v1.start_address = list->continuation_id;
+	if (osd_req_is_ver1(or)) {
+		cdbh->v1.list_identifier = list->list_identifier;
+		cdbh->v1.start_address = list->continuation_id;
+	} else {
+		cdbh->v2.list_identifier = list->list_identifier;
+		cdbh->v2.start_address = list->continuation_id;
+	}
 }
 
 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
 	u64 offset, unsigned *padding)
 {
 	return __osd_encode_offset(offset, padding,
-				  OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+			osd_req_is_ver1(or) ?
+				OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT,
+			OSD_OFFSET_MAX_SHIFT);
 }
 
 static struct osd_security_parameters *
@@ -122,7 +147,10 @@ _osd_req_sec_params(struct osd_request *or)
 {
 	struct osd_cdb *ocdb = &or->cdb;
 
-	return &ocdb->v1.sec_params;
+	if (osd_req_is_ver1(or))
+		return &ocdb->v1.sec_params;
+	else
+		return &ocdb->v2.sec_params;
 }
 
 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
@@ -130,6 +158,9 @@ void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
 	memset(osdd, 0, sizeof(*osdd));
 	osdd->scsi_device = scsi_device;
 	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+#ifdef OSD_VER1_SUPPORT
+	osdd->version = OSD_VER2;
+#endif
 	/* TODO: Allocate pools for osd_request attributes ... */
 }
 EXPORT_SYMBOL(osd_dev_init);
@@ -330,10 +361,30 @@ static void _osdv1_req_encode_common(struct osd_request *or,
 	ocdb->h.v1.start_address = cpu_to_be64(offset);
 }
 
+static void _osdv2_req_encode_common(struct osd_request *or,
+	 __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+	struct osdv2_cdb *ocdb = &or->cdb.v2;
+
+	OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act));
+
+	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+	ocdb->h.varlen_cdb.service_action = act;
+
+	ocdb->h.partition = cpu_to_be64(obj->partition);
+	ocdb->h.object = cpu_to_be64(obj->id);
+	ocdb->h.v2.length = cpu_to_be64(len);
+	ocdb->h.v2.start_address = cpu_to_be64(offset);
+}
+
 static void _osd_req_encode_common(struct osd_request *or,
 	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
 {
-	_osdv1_req_encode_common(or, act, obj, offset, len);
+	if (osd_req_is_ver1(or))
+		_osdv1_req_encode_common(or, act, obj, offset, len);
+	else
+		_osdv2_req_encode_common(or, act, obj, offset, len);
 }
 
 /*
@@ -542,6 +593,12 @@ void osd_req_flush_object(struct osd_request *or,
 	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
 	/*V2*/ u64 offset, /*V2*/ u64 len)
 {
+	if (unlikely(osd_req_is_ver1(or) && (offset || len))) {
+		OSD_DEBUG("OSD Ver1 flush on specific range ignored\n");
+		offset = 0;
+		len = 0;
+	}
+
 	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
 	_osd_req_encode_flush(or, op);
 }
@@ -1164,6 +1221,10 @@ enum { OSD_SEC_CAP_V1_ALL_CAPS =
 	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
 };
 
+enum { OSD_SEC_CAP_V2_ALL_CAPS =
+	OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT
+};
+
 void osd_sec_init_nosec_doall_caps(void *caps,
 	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
 {
@@ -1205,9 +1266,14 @@ void osd_sec_init_nosec_doall_caps(void *caps,
 }
 EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
 
+/* FIXME: Extract version from caps pointer.
+ *        Also Pete's target only supports caps from OSDv1 for now
+ */
 void osd_set_caps(struct osd_cdb *cdb, const void *caps)
 {
-	memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
+	bool is_ver1 = true;
+	/* NOTE: They start at same address */
+	memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN);
 }
 
 bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms)
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 93fa86b..778a624 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -21,6 +21,23 @@
 
 /* Note: "NI" in comments below means "Not Implemented yet" */
 
+/* Configure of code:
+ * #undef if you *don't* want OSD v1 support in runtime.
+ * If #defined the initiator will dynamically configure to encode OSD v1
+ * CDB's if the target is detected to be OSD v1 only.
+ * OSD v2 only commands, options, and attributes will be ignored if target
+ * is v1 only.
+ * If #defined will result in bigger/slower code (OK Slower maybe not)
+ * Q: Should this be CONFIG_SCSI_OSD_VER1_SUPPORT and set from Kconfig?
+ */
+#define OSD_VER1_SUPPORT y
+
+enum osd_std_version {
+	OSD_VER_NONE = 0,
+	OSD_VER1 = 1,
+	OSD_VER2 = 2,
+};
+
 /*
  * Object-based Storage Device.
  * This object represents an OSD device.
@@ -31,6 +48,10 @@
 struct osd_dev {
 	struct scsi_device *scsi_device;
 	unsigned def_timeout;
+
+#ifdef OSD_VER1_SUPPORT
+	enum osd_std_version version;
+#endif
 };
 
 /* Retrieve/return osd_dev(s) for use by Kernel clients */
@@ -41,6 +62,14 @@ void osduld_put_device(struct osd_dev *od);
 void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
 void osd_dev_fini(struct osd_dev *od);
 
+/* we might want to use function vector in the future */
+static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v)
+{
+#ifdef OSD_VER1_SUPPORT
+	od->version = v;
+#endif
+}
+
 struct osd_request;
 typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
 
@@ -77,6 +106,16 @@ struct osd_request {
 	int async_error;
 };
 
+/* OSD Version control */
+static inline bool osd_req_is_ver1(struct osd_request *or)
+{
+#ifdef OSD_VER1_SUPPORT
+	return or->osd_dev->version == OSD_VER1;
+#else
+	return false;
+#endif
+}
+
 /*
  * How to use the osd library:
  *
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h
index ce1a877..cd3cbf7 100644
--- a/include/scsi/osd_protocol.h
+++ b/include/scsi/osd_protocol.h
@@ -25,12 +25,16 @@ enum {
 	OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
 	OSDv1_CAP_LEN = 80,
 	/* Latest supported version */
-	OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH,
-	OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN,
-	OSD_CAP_LEN = OSDv1_CAP_LEN,
+/* 	OSD_ADDITIONAL_CDB_LENGTH = 216,*/
+	OSD_ADDITIONAL_CDB_LENGTH =
+		OSDv1_ADDITIONAL_CDB_LENGTH, /* FIXME: Pete rev-001 sup */
+	OSD_TOTAL_CDB_LEN = OSD_ADDITIONAL_CDB_LENGTH + 8,
+/* 	OSD_CAP_LEN = 104,*/
+	OSD_CAP_LEN = OSDv1_CAP_LEN,/* FIXME: Pete rev-001 sup */
 
 	OSD_SYSTEMID_LEN = 20,
 	OSD_CRYPTO_KEYID_SIZE = 20,
+	/*FIXME: OSDv2_CRYPTO_KEYID_SIZE = 32,*/
 	OSD_CRYPTO_SEED_SIZE = 4,
 	OSD_CRYPTO_NONCE_SIZE = 12,
 	OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
@@ -108,6 +112,7 @@ enum {
 	OSD_OFFSET_MAX_BITS = 28,
 
 	OSDv1_OFFSET_MIN_SHIFT = 8,
+	OSD_OFFSET_MIN_SHIFT = 3,
 	OSD_OFFSET_MAX_SHIFT = 16,
 };
 
@@ -129,6 +134,16 @@ static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding)
 				OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
 }
 
+/* Minimum 8 bytes alignment
+ * Same as v1 but since exponent can be signed than a less than
+ * 256 alignment can be reached with small offsets (<2GB)
+ */
+static inline osd_cdb_offset osd_encode_offset_v2(u64 offset, unsigned *padding)
+{
+	return __osd_encode_offset(offset, padding,
+				   OSD_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
+}
+
 /* osd2r03: 5.2.1 Overview */
 struct osd_cdb_head {
 	struct scsi_varlen_cdb_hdr varlen_cdb;
@@ -144,6 +159,13 @@ struct osd_cdb_head {
 /*36*/			__be64		length;
 /*44*/			__be64		start_address;
 		} __packed v1;
+
+		struct __osdv2_cdb_addr_len {
+			/* called allocation_length in some commands */
+/*32*/			__be64	length;
+/*40*/			__be64	start_address;
+/*48*/			__be32 list_identifier;/* Rarely used */
+		} __packed v2;
 	};
 /*52*/	union { /* selected attributes mode Page/List/Single */
 		struct osd_attributes_page_mode {
@@ -182,6 +204,7 @@ struct osd_cdb_head {
 /*80*/
 
 /*160 v1*/
+/*184 v2*/
 struct osd_security_parameters {
 /*160*/u8	integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
 /*180*/u8	request_nonce[OSD_CRYPTO_NONCE_SIZE];
@@ -189,6 +212,9 @@ struct osd_security_parameters {
 /*196*/osd_cdb_offset	data_out_integrity_check_offset;
 } __packed;
 /*200 v1*/
+/*224 v2*/
+
+/* FIXME: osdv2_security_parameters */
 
 struct osdv1_cdb {
 	struct osd_cdb_head h;
@@ -196,9 +222,17 @@ struct osdv1_cdb {
 	struct osd_security_parameters sec_params;
 } __packed;
 
+struct osdv2_cdb {
+	struct osd_cdb_head h;
+	u8 caps[OSD_CAP_LEN];
+	struct osd_security_parameters sec_params;
+	/* FIXME: osdv2_security_parameters */
+} __packed;
+
 struct osd_cdb {
 	union {
 		struct osdv1_cdb v1;
+		struct osdv2_cdb v2;
 		u8 buff[OSD_TOTAL_CDB_LEN];
 	};
 } __packed;
@@ -269,6 +303,7 @@ struct osd_attributes_list_attrid {
 /*
  * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
  *                  for setting attributes
+ * NOTE: v2 is 8-bytes aligned, v1 is not aligned.
  */
 struct osd_attributes_list_element {
 	__be32 attr_page;
@@ -279,6 +314,7 @@ struct osd_attributes_list_element {
 
 enum {
 	OSDv1_ATTRIBUTES_ELEM_ALIGN = 1,
+	OSD_ATTRIBUTES_ELEM_ALIGN = 8,
 };
 
 enum {
@@ -292,6 +328,12 @@ static inline unsigned osdv1_attr_list_elem_size(unsigned len)
 		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
 }
 
+static inline unsigned osdv2_attr_list_elem_size(unsigned len)
+{
+	return ALIGN(len + sizeof(struct osd_attributes_list_element),
+		     OSD_ATTRIBUTES_ELEM_ALIGN);
+}
+
 /*
  * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values
  */
@@ -326,6 +368,21 @@ static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h)
 	return be16_to_cpu(h->list_bytes);
 }
 
+struct osdv2_attributes_list_header {
+	u8 type;	/* lower 4-bits only */
+	u8 pad[3];
+/*4*/	__be32 list_bytes; /* Initiator shall set to zero. Only set by target */
+	/*
+	 * type=9 followed by struct osd_attributes_list_element's
+	 * type=E followed by struct osd_attributes_list_multi_header's
+	 */
+} __packed;
+
+static inline unsigned osdv2_list_size(struct osdv2_attributes_list_header *h)
+{
+	return be32_to_cpu(h->list_bytes);
+}
+
 /* (osd-r10 6.13)
  * osd2r03: 6.15 LIST (Table 79) LIST command parameter data.
  *	for root_lstchg below
@@ -469,11 +526,36 @@ struct osdv1_cap_object_descriptor {
 } __packed;
 /*80 v1*/
 
-struct osd_capability {
+/*56 v2*/
+struct osd_cap_object_descriptor {
+	union {
+		struct {
+/*56*/			__be32 allowed_attributes_access;
+/*60*/			__be32 policy_access_tag;
+/*64*/			__be16 boot_epoch;
+/*66*/			u8 reserved[6];
+/*72*/			__be64 allowed_partition_id;
+/*80*/			__be64 allowed_object_id;
+/*88*/			__be64 allowed_range_length;
+/*96*/			__be64 allowed_range_start;
+		} __packed obj_desc;
+
+/*56*/		u8 object_descriptor[48];
+	};
+} __packed;
+/*104 v2*/
+
+struct osdv1_capability {
 	struct osd_capability_head h;
 	struct osdv1_cap_object_descriptor od;
 } __packed;
 
+struct osd_capability {
+	struct osd_capability_head h;
+/* 	struct osd_cap_object_descriptor od;*/
+	struct osdv1_cap_object_descriptor od; /* FIXME: Pete rev-001 sup */
+} __packed;
+
 /**
  * osd_sec_set_caps - set cap-bits into the capabilities header
  *
-- 
1.6.0.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 14/18] libosd: OSDv2 auto detection
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (12 preceding siblings ...)
  2009-01-06 14:25   ` [PATCH 13/18] libosd: OSD version 2 Support Boaz Harrosh
@ 2009-01-06 14:27   ` Boaz Harrosh
  2009-01-06 14:29   ` [PATCH 15/18] libosd: SCSI/OSD Sense decoding support Boaz Harrosh
                     ` (3 subsequent siblings)
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:27 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Auto detect an OSDv2 or OSDv1 target at run time. Note how none
of the OSD API calls change. The tests do not know what device
version it is.

This test now passes against both the IBM-OSD-SIM OSD1 target
as well as OSC's OSD2 target.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/osd_initiator.c |  125 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/osd/osd_uld.c       |    5 ++
 include/scsi/osd_initiator.h     |    3 +
 3 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 6bda439..6abc885 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -41,6 +41,7 @@
 
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
+#include <scsi/osd_attributes.h>
 #include <scsi/scsi_device.h>
 
 #include "osd_debug.h"
@@ -59,6 +60,130 @@ static inline void build_test(void)
 	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
 }
 
+static char *_osd_ver_desc(struct osd_request *or)
+{
+	return osd_req_is_ver1(or) ? "OSD1" : "OSD2";
+}
+
+#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
+
+static int _osd_print_system_info(struct osd_dev *od, void *caps)
+{
+	struct osd_request *or;
+	struct osd_attr get_attrs[] = {
+		ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4),
+		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/),
+		ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/),
+		ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8),
+		ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6),
+		/* IBM-OSD-SIM Has a bug with this one put it last */
+		ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20),
+	};
+	void *iter = NULL, *pFirst;
+	int nelem = ARRAY_SIZE(get_attrs), a = 0;
+	int ret;
+
+	or = osd_start_request(od, GFP_KERNEL);
+	if (!or)
+		return -ENOMEM;
+
+	/* get attrs */
+	osd_req_get_attributes(or, &osd_root_object);
+	osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs));
+
+	ret = osd_finalize_request(or, 0, caps, NULL);
+	if (ret)
+		goto out;
+
+	ret = osd_execute_request(or);
+	if (ret) {
+		OSD_ERR("Failed to detect %s => %d\n", _osd_ver_desc(or), ret);
+		goto out;
+	}
+
+	osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+	OSD_INFO("Detected %s device\n",
+		_osd_ver_desc(or));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_VENDOR_IDENTIFICATION [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_IDENTIFICATION [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_MODEL [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_REVISION_LEVEL [%u]\n",
+		get_unaligned_be32(pFirst));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER [%s]\n",
+		(char *)pFirst);
+
+	pFirst = get_attrs[a].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_OSD_NAME [%s]\n", (char *)pFirst);
+	a++;
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_TOTAL_CAPACITY [0x%llx]\n",
+		_LLU(get_unaligned_be64(pFirst)));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_USED_CAPACITY [0x%llx]\n",
+		_LLU(get_unaligned_be64(pFirst)));
+
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_NUMBER_OF_PARTITIONS [%llu]\n",
+		_LLU(get_unaligned_be64(pFirst)));
+
+	/* FIXME: Where are the time utilities */
+	pFirst = get_attrs[a++].val_ptr;
+	OSD_INFO("OSD_ATTR_RI_CLOCK [0x%02x%02x%02x%02x%02x%02x]\n",
+		((char *)pFirst)[0], ((char *)pFirst)[1],
+		((char *)pFirst)[2], ((char *)pFirst)[3],
+		((char *)pFirst)[4], ((char *)pFirst)[5]);
+
+	if (a < nelem) { /* IBM-OSD-SIM bug, Might not have it */
+		int len = get_attrs[a].len;
+		u8 sid_dump[32*4 + 2]; /* 2nibbles+space+ASCII */
+
+		hex_dump_to_buffer(get_attrs[a].val_ptr, len, 32, 1,
+				   sid_dump, sizeof(sid_dump), true);
+		OSD_INFO("OSD_ATTR_RI_OSD_SYSTEM_ID(%d) [%s]\n", len, sid_dump);
+		a++;
+	}
+out:
+	osd_end_request(or);
+	return ret;
+}
+
+int osd_auto_detect_ver(struct osd_dev *od, void *caps)
+{
+	int ret;
+
+	/* Auto-detect the osd version */
+	ret = _osd_print_system_info(od, caps);
+	if (ret) {
+		osd_dev_set_ver(od, OSD_VER1);
+		OSD_DEBUG("converting to OSD1\n");
+		ret = _osd_print_system_info(od, caps);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(osd_auto_detect_ver);
+
 static unsigned _osd_req_cdb_len(struct osd_request *or)
 {
 	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 5ba7654..fa69e09 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -213,6 +213,7 @@ EXPORT_SYMBOL(osduld_put_device);
 static int __detect_osd(struct osd_uld_device *oud)
 {
 	struct scsi_device *scsi_device = oud->od.scsi_device;
+	char caps[OSD_CAP_LEN];
 	int error;
 
 	/* sending a test_unit_ready as first command seems to be needed
@@ -224,6 +225,10 @@ static int __detect_osd(struct osd_uld_device *oud)
 	if (error)
 		OSD_ERR("warning: scsi_test_unit_ready failed\n");
 
+	osd_sec_init_nosec_doall_caps(caps, &osd_root_object, false, true);
+	if (osd_auto_detect_ver(&oud->od, caps))
+		return -ENODEV;
+
 	return 0;
 }
 
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 778a624..8a0fd35 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -62,6 +62,9 @@ void osduld_put_device(struct osd_dev *od);
 void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
 void osd_dev_fini(struct osd_dev *od);
 
+/* some hi level device operations */
+int osd_auto_detect_ver(struct osd_dev *od, void *caps);    /* GFP_KERNEL */
+
 /* we might want to use function vector in the future */
 static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v)
 {
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 15/18] libosd: SCSI/OSD Sense decoding support
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (13 preceding siblings ...)
  2009-01-06 14:27   ` [PATCH 14/18] libosd: OSDv2 auto detection Boaz Harrosh
@ 2009-01-06 14:29   ` Boaz Harrosh
  2009-01-06 14:31   ` [PATCH 16/18] osd: Documentation for OSD library Boaz Harrosh
                     ` (2 subsequent siblings)
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:29 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Implementation of the osd_req_decode_sense() API. Can be called by
library users to decode what failed in command executions.

Add SCSI_OSD_DPRINT_SENSE Kconfig variable. Possible values are:
0 - Do not print any errors to messages file <KERN_ERR>
1 - (Default) Print only decoded errors that are not recoverable.
    Recoverable errors are those that the target has complied with
    the request but with a warning. For example read passed end of
    object will return zeros after the last valid byte.
2- Print all errors.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
 drivers/scsi/osd/Kbuild          |    6 +
 drivers/scsi/osd/osd_initiator.c |  189 +++++++++++++++++++++++++++
 include/scsi/osd_initiator.h     |   49 +++++++
 include/scsi/osd_sense.h         |  260 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 504 insertions(+), 0 deletions(-)
 create mode 100644 include/scsi/osd_sense.h

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index 6fb823f..29f7ddd 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -20,6 +20,12 @@ ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
 CONFIG_SCSI_OSD_ULD=m
 ccflags-y += -DCONFIG_SCSI_OSD_ULD -DCONFIG_SCSI_OSD_ULD_MODULE
 
+# CONFIG_SCSI_OSD_DPRINT_SENSE =
+#	0 - no print of errors
+#	1 - print errors
+#	2 - errors + warrnings
+ccflags-y += -DCONFIG_SCSI_OSD_DPRINT_SENSE=1
+
 # Uncomment to turn debug on
 # ccflags-y += -DCONFIG_SCSI_OSD_DEBUG
 
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 6abc885..11bf42b 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -42,6 +42,8 @@
 #include <scsi/osd_initiator.h>
 #include <scsi/osd_sec.h>
 #include <scsi/osd_attributes.h>
+#include <scsi/osd_sense.h>
+
 #include <scsi/scsi_device.h>
 
 #include "osd_debug.h"
@@ -1334,6 +1336,193 @@ int osd_finalize_request(struct osd_request *or,
 }
 EXPORT_SYMBOL(osd_finalize_request);
 
+#define OSD_SENSE_PRINT1(fmt, a...) \
+	do { \
+		if (__cur_sense_need_output) \
+			OSD_ERR(fmt, ##a); \
+	} while (0)
+
+#define OSD_SENSE_PRINT2(fmt, a...) OSD_SENSE_PRINT1("    " fmt, ##a)
+
+int osd_req_decode_sense_full(struct osd_request *or,
+	struct osd_sense_info *osi, bool silent,
+	struct osd_obj_id *bad_obj_list, int max_obj,
+	struct osd_attr *bad_attr_list, int max_attr)
+{
+	int sense_len, original_sense_len;
+	struct osd_sense_info local_osi;
+	struct scsi_sense_descriptor_based *ssdb;
+	void *cur_descriptor;
+#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 0)
+	const bool __cur_sense_need_output = false;
+#else
+	bool __cur_sense_need_output = !silent;
+#endif
+
+	if (!or->request->errors)
+		return 0;
+
+	ssdb = or->request->sense;
+	sense_len = or->request->sense_len;
+	if ((sense_len < sizeof(*ssdb) || !ssdb->sense_key)) {
+		OSD_ERR("Block-layer returned error(%x) but sense is empty\n",
+			or->request->errors);
+		return 0;
+	}
+
+	if ((ssdb->response_code != 0x72) && (ssdb->response_code != 0x73)) {
+		OSD_ERR("Unrecognized scsi sense: rcode=%x length=%d\n",
+			ssdb->response_code, sense_len);
+		return -EIO;
+	}
+
+	osi = osi ? : &local_osi;
+	memset(osi, 0, sizeof(*osi));
+	osi->key = ssdb->sense_key;
+	osi->additional_code = be16_to_cpu(ssdb->additional_sense_code);
+	original_sense_len = ssdb->additional_sense_length + 8;
+
+#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 1)
+	if (__cur_sense_need_output)
+		__cur_sense_need_output = (osi->key > scsi_sk_recovered_error);
+#endif
+	OSD_SENSE_PRINT1("Main Sense information key=0x%x length(%d, %d) "
+			"additional_code=0x%x\n",
+			osi->key, original_sense_len, sense_len,
+			osi->additional_code);
+
+	if (original_sense_len < sense_len)
+		sense_len = original_sense_len;
+
+	cur_descriptor = ssdb->ssd;
+	sense_len -= sizeof(*ssdb);
+	while (sense_len > 0) {
+		struct scsi_sense_descriptor *ssd = cur_descriptor;
+		int cur_len = ssd->additional_length + 2;
+
+		sense_len -= cur_len;
+
+		if (sense_len < 0)
+			break; /* sense was truncated */
+
+		switch (ssd->descriptor_type) {
+		case scsi_sense_information:
+		case scsi_sense_command_specific_information:
+		{
+			struct scsi_sense_command_specific_data_descriptor
+				*sscd = cur_descriptor;
+
+			osi->command_info =
+				get_unaligned_be64(&sscd->information) ;
+			OSD_SENSE_PRINT2(
+				"command_specific_information 0x%llx \n",
+				_LLU(osi->command_info));
+			break;
+		}
+		case scsi_sense_key_specific:
+		{
+			struct scsi_sense_key_specific_data_descriptor
+				*ssks = cur_descriptor;
+
+			osi->sense_info = get_unaligned_be16(&ssks->value);
+			OSD_SENSE_PRINT2(
+				"sense_key_specific_information %u"
+				"sksv_cd_bpv_bp (0x%x)\n",
+				osi->sense_info, ssks->sksv_cd_bpv_bp);
+			break;
+		}
+		case osd_sense_object_identification:
+		{ /*FIXME: Keep first not last, Store in array*/
+			struct osd_sense_identification_data_descriptor
+				*osidd = cur_descriptor;
+
+			osi->not_initiated_command_functions =
+				le32_to_cpu(osidd->not_initiated_functions);
+			osi->completed_command_functions =
+				le32_to_cpu(osidd->completed_functions);
+			osi->obj.partition = be64_to_cpu(osidd->partition_id);
+			osi->obj.id = be64_to_cpu(osidd->object_id);
+			OSD_SENSE_PRINT2(
+				"object_identification pid=0x%llx oid=0x%llx\n",
+				_LLU(osi->obj.partition), _LLU(osi->obj.id));
+			OSD_SENSE_PRINT2(
+				"not_initiated_bits(%x) "
+				"completed_command_bits(%x)\n",
+				osi->not_initiated_command_functions,
+				osi->completed_command_functions);
+			break;
+		}
+		case osd_sense_response_integrity_check:
+		{
+			struct osd_sense_response_integrity_check_descriptor
+				*osricd = cur_descriptor;
+			const int len = sizeof(osricd->integrity_check_value);
+			u8 key_dump[len*4 + 2]; /* 2nibbles+space+ASCII */
+
+			hex_dump_to_buffer(osricd->integrity_check_value, len,
+				       32, 1, key_dump, sizeof(key_dump), true);
+			OSD_SENSE_PRINT2("response_integrity [%s]\n", key_dump);
+		}
+		case osd_sense_attribute_identification:
+		{
+			struct osd_sense_attributes_data_descriptor
+				*osadd = cur_descriptor;
+			int len = min(cur_len, sense_len);
+			int i = 0;
+			struct osd_sense_attr *pattr = osadd->sense_attrs;
+
+			while (len < 0) {
+				u32 attr_page = be32_to_cpu(pattr->attr_page);
+				u32 attr_id = be32_to_cpu(pattr->attr_id);
+
+				if (i++ == 0) {
+					osi->attr.attr_page = attr_page;
+					osi->attr.attr_id = attr_id;
+				}
+
+				if (bad_attr_list && max_attr) {
+					bad_attr_list->attr_page = attr_page;
+					bad_attr_list->attr_id = attr_id;
+					bad_attr_list++;
+					max_attr--;
+				}
+				OSD_SENSE_PRINT2(
+					"osd_sense_attribute_identification"
+					"attr_page=0x%x attr_id=0x%x\n",
+					attr_page, attr_id);
+			}
+		}
+		/*These are not legal for OSD*/
+		case scsi_sense_field_replaceable_unit:
+			OSD_SENSE_PRINT2("scsi_sense_field_replaceable_unit\n");
+			break;
+		case scsi_sense_stream_commands:
+			OSD_SENSE_PRINT2("scsi_sense_stream_commands\n");
+			break;
+		case scsi_sense_block_commands:
+			OSD_SENSE_PRINT2("scsi_sense_block_commands\n");
+			break;
+		case scsi_sense_ata_return:
+			OSD_SENSE_PRINT2("scsi_sense_ata_return\n");
+			break;
+		default:
+			if (ssd->descriptor_type <= scsi_sense_Reserved_last)
+				OSD_SENSE_PRINT2(
+					"scsi_sense Reserved descriptor (0x%x)",
+					ssd->descriptor_type);
+			else
+				OSD_SENSE_PRINT2(
+					"scsi_sense Vendor descriptor (0x%x)",
+					ssd->descriptor_type);
+		}
+
+		cur_descriptor += cur_len;
+	}
+
+	return (osi->key > scsi_sk_recovered_error) ? -EIO : 0;
+}
+EXPORT_SYMBOL(osd_req_decode_sense_full);
+
 /*
  * Implementation of osd_sec.h API
  * TODO: Move to a separate osd_sec.c file at a later stage.
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 8a0fd35..83b6976 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -212,6 +212,55 @@ int osd_execute_request_async(struct osd_request *or,
 	osd_req_done_fn *done, void *private);
 
 /**
+ * osd_req_decode_sense_full - Decode sense information after execution.
+ *
+ * @or:           - osd_request to examine
+ * @osi           - Recievs a more detailed error report information (optional).
+ * @silent        - Do not print to dmsg (Even if enabled)
+ * @bad_obj_list  - Some commands act on multiple objects. Failed objects will
+ *                  be recieved here (optional)
+ * @max_obj       - Size of @bad_obj_list.
+ * @bad_attr_list - List of failing attributes (optional)
+ * @max_attr      - Size of @bad_attr_list.
+ *
+ * After execution, sense + return code can be analyzed using this function. The
+ * return code is the final disposition on the error. So it is possible that a
+ * CHECK_CONDITION was returned from target but this will return NO_ERROR, for
+ * example on recovered errors. All parameters are optional if caller does
+ * not need any returned information.
+ * Note: This function will also dump the error to dmsg according to settings
+ * of the SCSI_OSD_DPRINT_SENSE Kconfig value. Set @silent if you know the
+ * command would routinely fail, to not spam the dmsg file.
+ */
+struct osd_sense_info {
+	int key;		/* one of enum scsi_sense_keys */
+	int additional_code ;	/* enum osd_additional_sense_codes */
+	union { /* Sense specific information */
+		u16 sense_info;
+		u16 cdb_field_offset; 	/* scsi_invalid_field_in_cdb */
+	};
+	union { /* Command specific information */
+		u64 command_info;
+	};
+
+	u32 not_initiated_command_functions; /* osd_command_functions_bits */
+	u32 completed_command_functions; /* osd_command_functions_bits */
+	struct osd_obj_id obj;
+	struct osd_attr attr;
+};
+
+int osd_req_decode_sense_full(struct osd_request *or,
+	struct osd_sense_info *osi, bool silent,
+	struct osd_obj_id *bad_obj_list, int max_obj,
+	struct osd_attr *bad_attr_list, int max_attr);
+
+static inline int osd_req_decode_sense(struct osd_request *or,
+	struct osd_sense_info *osi)
+{
+	return osd_req_decode_sense_full(or, osi, false, NULL, 0, NULL, 0);
+}
+
+/**
  * osd_end_request - return osd_request to free store
  *
  * @or:		osd_request to free
diff --git a/include/scsi/osd_sense.h b/include/scsi/osd_sense.h
new file mode 100644
index 0000000..ff9b33c
--- /dev/null
+++ b/include/scsi/osd_sense.h
@@ -0,0 +1,260 @@
+/*
+ * osd_sense.h - OSD Related sense handling definitions.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * This file contains types and constants that are defined by the protocol
+ * Note: All names and symbols are taken from the OSD standard's text.
+ */
+#ifndef __OSD_SENSE_H__
+#define __OSD_SENSE_H__
+
+#include <scsi/osd_protocol.h>
+
+/* SPC3r23 4.5.6 Sense key and sense code definitions table 27 */
+enum scsi_sense_keys {
+	scsi_sk_no_sense        = 0x0,
+	scsi_sk_recovered_error = 0x1,
+	scsi_sk_not_ready       = 0x2,
+	scsi_sk_medium_error    = 0x3,
+	scsi_sk_hardware_error  = 0x4,
+	scsi_sk_illegal_request = 0x5,
+	scsi_sk_unit_attention  = 0x6,
+	scsi_sk_data_protect    = 0x7,
+	scsi_sk_blank_check     = 0x8,
+	scsi_sk_vendor_specific = 0x9,
+	scsi_sk_copy_aborted    = 0xa,
+	scsi_sk_aborted_command = 0xb,
+	scsi_sk_volume_overflow = 0xd,
+	scsi_sk_miscompare      = 0xe,
+	scsi_sk_reserved        = 0xf,
+};
+
+/* SPC3r23 4.5.6 Sense key and sense code definitions table 28 */
+/* Note: only those which can be returned by an OSD target. Most of
+ *       these errors are taken care of by the generic scsi layer.
+ */
+enum osd_additional_sense_codes {
+	scsi_no_additional_sense_information			= 0x0000,
+	scsi_operation_in_progress				= 0x0016,
+	scsi_cleaning_requested					= 0x0017,
+	scsi_lunr_cause_not_reportable				= 0x0400,
+	scsi_logical_unit_is_in_process_of_becoming_ready	= 0x0401,
+	scsi_lunr_initializing_command_required			= 0x0402,
+	scsi_lunr_manual_intervention_required			= 0x0403,
+	scsi_lunr_operation_in_progress				= 0x0407,
+	scsi_lunr_selftest_in_progress				= 0x0409,
+	scsi_luna_asymmetric_access_state_transition		= 0x040a,
+	scsi_luna_target_port_in_standby_state			= 0x040b,
+	scsi_luna_target_port_in_unavailable_state		= 0x040c,
+	scsi_lunr_notify_enable_spinup_required			= 0x0411,
+	scsi_logical_unit_does_not_respond_to_selection		= 0x0500,
+	scsi_logical_unit_communication_failure			= 0x0800,
+	scsi_logical_unit_communication_timeout			= 0x0801,
+	scsi_logical_unit_communication_parity_error		= 0x0802,
+	scsi_error_log_overflow					= 0x0a00,
+	scsi_warning						= 0x0b00,
+	scsi_warning_specified_temperature_exceeded		= 0x0b01,
+	scsi_warning_enclosure_degraded				= 0x0b02,
+	scsi_write_error_unexpected_unsolicited_data		= 0x0c0c,
+	scsi_write_error_not_enough_unsolicited_data		= 0x0c0d,
+	scsi_invalid_information_unit				= 0x0e00,
+	scsi_invalid_field_in_command_information_unit		= 0x0e03,
+	scsi_read_error_failed_retransmission_request		= 0x1113,
+	scsi_parameter_list_length_error			= 0x1a00,
+	scsi_invalid_command_operation_code			= 0x2000,
+	scsi_invalid_field_in_cdb				= 0x2400,
+	osd_security_audit_value_frozen				= 0x2404,
+	osd_security_working_key_frozen				= 0x2405,
+	osd_nonce_not_unique					= 0x2406,
+	osd_nonce_timestamp_out_of_range			= 0x2407,
+	scsi_logical_unit_not_supported				= 0x2500,
+	scsi_invalid_field_in_parameter_list			= 0x2600,
+	scsi_parameter_not_supported				= 0x2601,
+	scsi_parameter_value_invalid				= 0x2602,
+	scsi_invalid_release_of_persistent_reservation		= 0x2604,
+	osd_invalid_dataout_buffer_integrity_check_value	= 0x260f,
+	scsi_not_ready_to_ready_change_medium_may_have_changed	= 0x2800,
+	scsi_power_on_reset_or_bus_device_reset_occurred	= 0x2900,
+	scsi_power_on_occurred					= 0x2901,
+	scsi_scsi_bus_reset_occurred				= 0x2902,
+	scsi_bus_device_reset_function_occurred			= 0x2903,
+	scsi_device_internal_reset				= 0x2904,
+	scsi_transceiver_mode_changed_to_single_ended		= 0x2905,
+	scsi_transceiver_mode_changed_to_lvd			= 0x2906,
+	scsi_i_t_nexus_loss_occurred				= 0x2907,
+	scsi_parameters_changed					= 0x2a00,
+	scsi_mode_parameters_changed				= 0x2a01,
+	scsi_asymmetric_access_state_changed			= 0x2a06,
+	scsi_priority_changed					= 0x2a08,
+	scsi_command_sequence_error				= 0x2c00,
+	scsi_previous_busy_status				= 0x2c07,
+	scsi_previous_task_set_full_status			= 0x2c08,
+	scsi_previous_reservation_conflict_status		= 0x2c09,
+	osd_partition_or_collection_contains_user_objects	= 0x2c0a,
+	scsi_commands_cleared_by_another_initiator		= 0x2f00,
+	scsi_cleaning_failure					= 0x3007,
+	scsi_enclosure_failure					= 0x3400,
+	scsi_enclosure_services_failure				= 0x3500,
+	scsi_unsupported_enclosure_function			= 0x3501,
+	scsi_enclosure_services_unavailable			= 0x3502,
+	scsi_enclosure_services_transfer_failure		= 0x3503,
+	scsi_enclosure_services_transfer_refused		= 0x3504,
+	scsi_enclosure_services_checksum_error			= 0x3505,
+	scsi_rounded_parameter					= 0x3700,
+	osd_read_past_end_of_user_object			= 0x3b17,
+	scsi_logical_unit_has_not_self_configured_yet		= 0x3e00,
+	scsi_logical_unit_failure				= 0x3e01,
+	scsi_timeout_on_logical_unit				= 0x3e02,
+	scsi_logical_unit_failed_selftest			= 0x3e03,
+	scsi_logical_unit_unable_to_update_selftest_log		= 0x3e04,
+	scsi_target_operating_conditions_have_changed		= 0x3f00,
+	scsi_microcode_has_been_changed				= 0x3f01,
+	scsi_inquiry_data_has_changed				= 0x3f03,
+	scsi_echo_buffer_overwritten				= 0x3f0f,
+	scsi_diagnostic_failure_on_component_nn_first		= 0x4080,
+	scsi_diagnostic_failure_on_component_nn_last		= 0x40ff,
+	scsi_message_error					= 0x4300,
+	scsi_internal_target_failure				= 0x4400,
+	scsi_select_or_reselect_failure				= 0x4500,
+	scsi_scsi_parity_error					= 0x4700,
+	scsi_data_phase_crc_error_detected			= 0x4701,
+	scsi_scsi_parity_error_detected_during_st_data_phase	= 0x4702,
+	scsi_asynchronous_information_protection_error_detected	= 0x4704,
+	scsi_protocol_service_crc_error				= 0x4705,
+	scsi_phy_test_function_in_progress			= 0x4706,
+	scsi_invalid_message_error				= 0x4900,
+	scsi_command_phase_error				= 0x4a00,
+	scsi_data_phase_error					= 0x4b00,
+	scsi_logical_unit_failed_self_configuration		= 0x4c00,
+	scsi_overlapped_commands_attempted			= 0x4e00,
+	osd_quota_error						= 0x5507,
+	scsi_failure_prediction_threshold_exceeded		= 0x5d00,
+	scsi_failure_prediction_threshold_exceeded_false	= 0x5dff,
+	scsi_voltage_fault					= 0x6500,
+};
+
+enum scsi_descriptor_types {
+	scsi_sense_information			= 0x0,
+	scsi_sense_command_specific_information	= 0x1,
+	scsi_sense_key_specific			= 0x2,
+	scsi_sense_field_replaceable_unit	= 0x3,
+	scsi_sense_stream_commands		= 0x4,
+	scsi_sense_block_commands		= 0x5,
+	osd_sense_object_identification		= 0x6,
+	osd_sense_response_integrity_check	= 0x7,
+	osd_sense_attribute_identification	= 0x8,
+	scsi_sense_ata_return			= 0x9,
+
+	scsi_sense_Reserved_first		= 0x0A,
+	scsi_sense_Reserved_last		= 0x7F,
+	scsi_sense_Vendor_specific_first	= 0x80,
+	scsi_sense_Vendor_specific_last		= 0xFF,
+};
+
+struct scsi_sense_descriptor { /* for picking into desc type */
+	u8	descriptor_type; /* one of enum scsi_descriptor_types */
+	u8	additional_length; /* n - 1 */
+	u8	data[];
+} __packed;
+
+/* OSD deploys only scsi descriptor_based sense buffers */
+struct scsi_sense_descriptor_based {
+/*0*/	u8 	response_code; /* 0x72 or 0x73 */
+/*1*/	u8 	sense_key; /* one of enum scsi_sense_keys (4 lower bits) */
+/*2*/	__be16	additional_sense_code; /* enum osd_additional_sense_codes */
+/*4*/	u8	Reserved[3];
+/*7*/	u8	additional_sense_length; /* n - 7 */
+/*8*/	struct	scsi_sense_descriptor ssd[0]; /* variable length, 1 or more */
+} __packed;
+
+/* some descriptors deployed by OSD */
+
+/* SPC3r23 4.5.2.3 Command-specific information sense data descriptor */
+/* Note: this is the same for descriptor_type=00 but with type=00 the
+ *        Reserved[0] == 0x80 (ie. bit-7 set)
+ */
+struct scsi_sense_command_specific_data_descriptor {
+/*0*/	u8	descriptor_type; /* (00h/01h) */
+/*1*/	u8	additional_length; /* (0Ah) */
+/*2*/	u8	Reserved[2];
+/*4*/	__be64  information;
+} __packed;
+/*12*/
+
+struct scsi_sense_key_specific_data_descriptor {
+/*0*/	u8	descriptor_type; /* (02h) */
+/*1*/	u8	additional_length; /* (06h) */
+/*2*/	u8	Reserved[2];
+/* SKSV, C/D, Reserved (2), BPV, BIT POINTER (3) */
+/*4*/	u8	sksv_cd_bpv_bp;
+/*5*/	__be16	value; /* field-pointer/progress-value/retry-count/... */
+/*7*/	u8	Reserved2;
+} __packed;
+/*8*/
+
+/* 4.16.2.1 OSD error identification sense data descriptor - table 52 */
+/* Note: these bits are defined LE order for easy definition, this way the BIT()
+ * number is the same as in the documentation. Below members at
+ * osd_sense_identification_data_descriptor are therefore defined __le32.
+ */
+enum osd_command_functions_bits {
+	OSD_CFB_COMMAND		 = BIT(4),
+	OSD_CFB_CMD_CAP_VERIFIED = BIT(5),
+	OSD_CFB_VALIDATION	 = BIT(7),
+	OSD_CFB_IMP_ST_ATT	 = BIT(12),
+	OSD_CFB_SET_ATT		 = BIT(20),
+	OSD_CFB_SA_CAP_VERIFIED	 = BIT(21),
+	OSD_CFB_GET_ATT		 = BIT(28),
+	OSD_CFB_GA_CAP_VERIFIED	 = BIT(29),
+};
+
+struct osd_sense_identification_data_descriptor {
+/*0*/	u8	descriptor_type; /* (06h) */
+/*1*/	u8	additional_length; /* (1Eh) */
+/*2*/	u8	Reserved[6];
+/*8*/	__le32	not_initiated_functions; /*osd_command_functions_bits*/
+/*12*/	__le32	completed_functions; /*osd_command_functions_bits*/
+/*16*/ 	__be64	partition_id;
+/*24*/	__be64	object_id;
+} __packed;
+/*32*/
+
+struct osd_sense_response_integrity_check_descriptor {
+/*0*/	u8	descriptor_type; /* (07h) */
+/*1*/	u8	additional_length; /* (20h) */
+/*2*/	u8	integrity_check_value[32]; /*FIXME: OSDv2_CRYPTO_KEYID_SIZE*/
+} __packed;
+/*34*/
+
+struct osd_sense_attributes_data_descriptor {
+/*0*/	u8	descriptor_type; /* (08h) */
+/*1*/	u8	additional_length; /* (n-2) */
+/*2*/	u8	Reserved[6];
+	struct osd_sense_attr {
+/*8*/		__be32	attr_page;
+/*12*/		__be32	attr_id;
+/*16*/	} sense_attrs[0]; /* 1 or more */
+} __packed;
+/*variable*/
+
+/* Dig into scsi_sk_illegal_request/scsi_invalid_field_in_cdb errors */
+
+/*FIXME: Support also field in CAPS*/
+#define OSD_CDB_OFFSET(F) offsetof(struct osd_cdb_head, F)
+
+enum osdv2_cdb_field_offset {
+	OSDv1_CFO_STARTING_BYTE	= OSD_CDB_OFFSET(v1.start_address),
+	OSD_CFO_STARTING_BYTE	= OSD_CDB_OFFSET(v2.start_address),
+	OSD_CFO_PARTITION_ID	= OSD_CDB_OFFSET(partition),
+	OSD_CFO_OBJECT_ID	= OSD_CDB_OFFSET(object),
+};
+
+#endif /* ndef __OSD_SENSE_H__ */
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 16/18] osd: Documentation for OSD library
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (14 preceding siblings ...)
  2009-01-06 14:29   ` [PATCH 15/18] libosd: SCSI/OSD Sense decoding support Boaz Harrosh
@ 2009-01-06 14:31   ` Boaz Harrosh
  2009-01-06 14:32   ` [PATCH 17/18] osd: Kconfig file for in-tree builds Boaz Harrosh
  2009-01-06 14:34   ` [PATCH 18/18] scsi: Add osd library to build system Boaz Harrosh
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:31 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Add osd.txt to Documentation/scsi/

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 Documentation/scsi/osd.txt |  198 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 198 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/scsi/osd.txt

diff --git a/Documentation/scsi/osd.txt b/Documentation/scsi/osd.txt
new file mode 100644
index 0000000..da162f7
--- /dev/null
+++ b/Documentation/scsi/osd.txt
@@ -0,0 +1,198 @@
+The OSD Standard
+================
+OSD (Object-Based Storage Device) is a T10 SCSI command set that is designed
+to provide efficient operation of input/output logical units that manage the
+allocation, placement, and accessing of variable-size data-storage containers,
+called objects. Objects are intended to contain operating system and application
+constructs. Each object has associated attributes attached to it, which are
+integral part of the object and provide metadata about the object. The standard
+defines some common obligatory attributes, but user attributes can be added as
+needed.
+
+See: http://www.t10.org/ftp/t10/drafts/osd2/ for the latest draft for OSD 2
+or search the web for "OSD SCSI"
+
+OSD in the Linux Kernel
+=======================
+osd-initiator:
+  The main component of OSD in Kernel is the osd-initiator library. Its main
+user is intended to be the pNFS-over-objects layout driver, which uses objects
+as its back-end data storage. Other clients are the other osd parts listed below.
+
+osd-uld:
+  This is a SCSI ULD that registers for OSD type devices and provides a testing
+platform, both for the in-kernel initiator as well as connected targets. It
+currently has no useful user-mode API, though it could have if need be.
+
+exofs:
+  Is an OSD based Linux file system. It uses the osd-initiator and osd-uld,
+to export a usable file system for users.
+See Documentation/filesystems/exofs.txt for more details
+
+osd target:
+  There are no current plans for an OSD target implementation in kernel. For all
+needs, a user-mode target that is based on the scsi tgt target framework is
+available from Ohio Supercomputer Center (OSC) at:
+http://www.open-osd.org/bin/view/Main/OscOsdProject
+There are several other target implementations. See http://open-osd.org for more
+links.
+
+Files and Folders
+=================
+This is the complete list of files included in this work:
+include/scsi/
+	osd_initiator.h   Main API for the initiator library
+	osd_types.h	  Common OSD types
+	osd_sec.h	  Security Manager API
+	osd_protocol.h	  Wire definitions of the OSD standard protocol
+	osd_attributes.h  Wire definitions of OSD attributes
+
+drivers/scsi/osd/
+	osd_initiator.c   OSD-Initiator library implementation
+	osd_uld.c	  The OSD scsi ULD
+	osd_ktest.{h,c}	  In-kernel test suite (called by osd_uld)
+	osd_debug.h	  Some printk macros
+	Makefile	  For both in-tree and out-of-tree compilation
+	Kconfig		  Enables inclusion of the different pieces
+	osd_test.c	  User-mode application to call the kernel tests
+
+The OSD-Initiator Library
+=========================
+osd_initiator is a low level implementation of an osd initiator encoder.
+But even though, it should be intuitive and easy to use. Perhaps over time an
+higher lever will form that automates some of the more common recipes.
+
+init/fini:
+- osd_dev_init() associates a scsi_device with an osd_dev structure
+  and initializes some global pools. This should be done once per scsi_device
+  (OSD LUN). The osd_dev structure is needed for calling osd_start_request().
+
+- osd_dev_fini() cleans up before a osd_dev/scsi_device destruction.
+
+OSD commands encoding, execution, and decoding of results:
+
+struct osd_request's is used to iteratively encode an OSD command and carry
+its state throughout execution. Each request goes through these stages:
+
+a. osd_start_request() allocates the request.
+
+b. Any of the osd_req_* methods is used to encode a request of the specified
+   type.
+
+c. osd_req_add_{get,set}_attr_* may be called to add get/set attributes to the
+   CDB. "List" or "Page" mode can be used exclusively. The attribute-list API
+   can be called multiple times on the same request. However, only one
+   attribute-page can be read, as mandated by the OSD standard.
+
+d. osd_finalize_request() computes offsets into the data-in and data-out buffers
+   and signs the request using the provided capability key and integrity-
+   check parameters.
+
+e. osd_execute_request() may be called to execute the request via the block
+   layer and wait for its completion.  The request can be executed
+   asynchronously by calling the block layer API directly.
+
+f. After execution, osd_req_decode_sense() can be called to decode the request's
+   sense information.
+
+g. osd_req_decode_get_attr() may be called to retrieve osd_add_get_attr_list()
+   values.
+
+h. osd_end_request() must be called to deallocate the request and any resource
+   associated with it. Note that osd_end_request cleans up the request at any
+   stage and it must always be called after a successful osd_start_request().
+
+osd_request's structure:
+
+The OSD standard defines a complex structure of IO segments pointed to by
+members in the CDB. Up to 3 segments can be deployed in the IN-Buffer and up to
+4 in the OUT-Buffer. The ASCII illustration below depicts a secure-read with
+associated get+set of attributes-lists. Other combinations very on the same
+basic theme. From no-segments-used up to all-segments-used.
+
+|________OSD-CDB__________|
+|                         |
+|read_len (offset=0)     -|---------\
+|                         |         |
+|get_attrs_list_length    |         |
+|get_attrs_list_offset   -|----\    |
+|                         |    |    |
+|retrieved_attrs_alloc_len|    |    |
+|retrieved_attrs_offset  -|----|----|-\
+|                         |    |    | |
+|set_attrs_list_length    |    |    | |
+|set_attrs_list_offset   -|-\  |    | |
+|                         | |  |    | |
+|in_data_integ_offset    -|-|--|----|-|-\
+|out_data_integ_offset   -|-|--|--\ | | |
+\_________________________/ |  |  | | | |
+                            |  |  | | | |
+|_______OUT-BUFFER________| |  |  | | | |
+|      Set attr list      |</  |  | | | |
+|                         |    |  | | | |
+|-------------------------|    |  | | | |
+|   Get attr descriptors  |<---/  | | | |
+|                         |       | | | |
+|-------------------------|       | | | |
+|    Out-data integrity   |<------/ | | |
+|                         |         | | |
+\_________________________/         | | |
+                                    | | |
+|________IN-BUFFER________|         | | |
+|      In-Data read       |<--------/ | |
+|                         |           | |
+|-------------------------|           | |
+|      Get attr list      |<----------/ |
+|                         |             |
+|-------------------------|             |
+|    In-data integrity    |<------------/
+|                         |
+\_________________________/
+
+A block device request can carry bidirectional payload by means of associating
+a bidi_read request with a main write-request. Each in/out request is described
+by a chain of BIOs associated with each request.
+The CDB is of a SCSI VARLEN CDB format, as described by OSD standard.
+The OSD standard also mandates alignment restrictions at start of each segment.
+
+In the code, in struct osd_request, there are two _osd_io_info structures to
+describe the IN/OUT buffers above, two BIOs for the data payload and up to five
+_osd_req_data_segment structures to hold the different segments allocation and
+information.
+
+Important: We have chosen to disregard the assumption that a BIO-chain (and
+the resulting sg-list) describes a linear memory buffer. Meaning only first and
+last scatter chain can be incomplete and all the middle chains are of PAGE_SIZE.
+For us, a scatter-gather-list, as its name implies and as used by the Networking
+layer, is to describe a vector of buffers that will be transferred to/from the
+wire. It works very well with current iSCSI transport. iSCSI is currently the
+only deployed OSD transport. In the future we anticipate SAS and FC attached OSD
+devices as well.
+
+The OSD Testing ULD
+===================
+TODO: More user-mode control on tests.
+
+Authors, Mailing list
+=====================
+Please communicate with us on any deployment of osd, whether using this code
+or not.
+
+Any problems, questions, bug reports, lonely OSD nights, please email:
+   OSD Dev List <osd-dev@open-osd.org>
+
+More up-to-date information can be found on:
+http://open-osd.org
+
+Boaz Harrosh <bharrosh@panasas.com>
+Benny Halevy <bhalevy@panasas.com>
+
+References
+==========
+Weber, R., "SCSI Object-Based Storage Device Commands",
+T10/1355-D ANSI/INCITS 400-2004,
+http://www.t10.org/ftp/t10/drafts/osd/osd-r10.pdf
+
+Weber, R., "SCSI Object-Based Storage Device Commands -2 (OSD-2)"
+T10/1729-D, Working Draft, rev. 3
+http://www.t10.org/ftp/t10/drafts/osd2/osd2r03.pdf
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 17/18] osd: Kconfig file for in-tree builds
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (15 preceding siblings ...)
  2009-01-06 14:31   ` [PATCH 16/18] osd: Documentation for OSD library Boaz Harrosh
@ 2009-01-06 14:32   ` Boaz Harrosh
  2009-01-06 17:40     ` Randy Dunlap
  2009-01-06 14:34   ` [PATCH 18/18] scsi: Add osd library to build system Boaz Harrosh
  17 siblings, 1 reply; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:32 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Kconfig file for the drivers/scsi/osd subdirectory.
Adds the following config items:
	config SCSI_OSD_INITIATOR
	config SCSI_OSD_ULD
	config SCSI_OSD_DPRINT_SENSE
	config SCSI_OSD_DEBUG

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kconfig |   53 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 53 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kconfig

diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
new file mode 100644
index 0000000..861b5ce
--- /dev/null
+++ b/drivers/scsi/osd/Kconfig
@@ -0,0 +1,53 @@
+#
+# Kernel configuration file for the OSD scsi protocol
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public version 2 License as
+# published by the Free Software Foundation
+#
+# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
+#        How is it done properly?
+#
+
+config SCSI_OSD_INITIATOR
+	tristate "OSD-Initiator library"
+	depends on SCSI
+	help
+		Enable the OSD-Initiator library (libosd.ko).
+		NOTE: You must also select CRYPTO_SHA1 + CRYPTO_HMAC and their
+		dependencies
+
+config SCSI_OSD_ULD
+	tristate "OSD Upper Level driver"
+	depends on SCSI_OSD_INITIATOR
+	help
+		Build a SCSI upper layer driver that exports /dev/osdX devices
+		to user-mode for testing and controlling OSD devices. It is also
+		needed by exofs, for mounting an OSD based file system.
+
+config SCSI_OSD_DPRINT_SENSE
+    int "(0-2) When sense is returned, DEBUG print all sense descriptors"
+    default 1
+    depends on SCSI_OSD_INITIATOR
+    help
+        When a CHECK_CONDITION status is returned from a target, and a
+        sense-buffer is retrieved, turning this on will dump a full
+        sense-decoding message. Setting to 2 will also print recoverable
+        errors that might be regularly returned for some filesystem
+        operations.
+
+config SCSI_OSD_DEBUG
+	bool "Compile All OSD modules with lots of DEBUG prints"
+	default n
+	depends on SCSI_OSD_INITIATOR
+	help
+		OSD Code is populated with lots of OSD_DEBUG(..) printouts to
+		dmesg. Enable this if you found a bug and you want to help us
+		track the problem (see also MAINTAINERS). Setting this will also
+		force SCSI_OSD_DPRINT_SENSE=2.
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* [PATCH 18/18] scsi: Add osd library to build system
  2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
                     ` (16 preceding siblings ...)
  2009-01-06 14:32   ` [PATCH 17/18] osd: Kconfig file for in-tree builds Boaz Harrosh
@ 2009-01-06 14:34   ` Boaz Harrosh
  17 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:34 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

OSD in kernel source code is assumed to be at:
drivers/scsi/osd/ with its own Makefile and Kconfig

Add includes to them from drivers/scsi Makefile and Kconfig
Add OSD to MAINTAINERS file

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 MAINTAINERS           |   10 ++++++++++
 drivers/scsi/Kconfig  |    2 ++
 drivers/scsi/Makefile |    2 ++
 3 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index ceb32ee..3dcc11c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3241,6 +3241,16 @@ L:	orinoco-devel@lists.sourceforge.net
 W:	http://www.nongnu.org/orinoco/
 S:	Maintained
 
+OSD LIBRARY
+P:	Boaz Harrosh
+M:	bharrosh@panasas.com
+P:	Benny Halevy
+M:	bhalevy@panasas.com
+L:	osd-dev@open-osd.org
+W:	http://open-osd.org
+T:	git://git.open-osd.org/open-osd.git
+S:	Maintained
+
 P54 WIRELESS DRIVER
 P:	Michael Wu
 M:	flamingice@sourmilk.net
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 152d4aa..7cadcf8 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1802,4 +1802,6 @@ source "drivers/scsi/pcmcia/Kconfig"
 
 source "drivers/scsi/device_handler/Kconfig"
 
+source "drivers/scsi/osd/Kconfig"
+
 endmenu
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 1410697..ec2be4e 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -138,6 +138,8 @@ obj-$(CONFIG_CHR_DEV_SG)	+= sg.o
 obj-$(CONFIG_CHR_DEV_SCH)	+= ch.o
 obj-$(CONFIG_SCSI_ENCLOSURE)	+= ses.o
 
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += osd/
+
 # This goes last, so that "real" scsi devices probe earlier
 obj-$(CONFIG_SCSI_DEBUG)	+= scsi_debug.o
 
-- 
1.6.0.1


^ permalink raw reply related	[flat|nested] 183+ messages in thread

* Re: [PATCH 07/18] osd_ktests: Add basic OSD tests
  2009-01-06 14:17   ` [PATCH 07/18] osd_ktests: Add basic OSD tests Boaz Harrosh
@ 2009-01-06 14:42     ` FUJITA Tomonori
  2009-01-06 14:56       ` Boaz Harrosh
  2009-01-06 16:49     ` Boaz Harrosh
  1 sibling, 1 reply; 183+ messages in thread
From: FUJITA Tomonori @ 2009-01-06 14:42 UTC (permalink / raw)
  To: bharrosh; +Cc: James.Bottomley, linux-scsi, osd-dev, akpm

On Tue,  6 Jan 2009 16:17:16 +0200
Boaz Harrosh <bharrosh@panasas.com> wrote:

> Currently testing what is implemented in the osd_initiator library.
> That is - format, create/remove partition, create/remove object,
> read and write to objects.
> 
> This test passes against the IBM-OSD-SIM OSDv1 target.
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> Reviewed-by: Benny Halevy <bhalevy@panasas.com>
> ---
>  drivers/scsi/osd/Kbuild       |    2 +-
>  drivers/scsi/osd/osd_ktests.c |  331 +++++++++++++++++++++++++++++++++++++++++
>  drivers/scsi/osd/osd_ktests.h |    4 +
>  drivers/scsi/osd/osd_uld.c    |    2 +-
>  4 files changed, 337 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/scsi/osd/osd_ktests.c
> 
> diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
> index 4730cdc..6fb823f 100644
> --- a/drivers/scsi/osd/Kbuild
> +++ b/drivers/scsi/osd/Kbuild
> @@ -35,5 +35,5 @@ libosd-y := osd_initiator.o
>  obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
>  
>  # osd.ko - SCSI ULD and char-device
> -osd-y := osd_uld.o
> +osd-y := osd_uld.o osd_ktests.o
>  obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
> diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
> new file mode 100644
> index 0000000..fba4934
> --- /dev/null
> +++ b/drivers/scsi/osd/osd_ktests.c
> @@ -0,0 +1,331 @@
> +/*
> + * osd_ktests.c - An osd_initiator library in-kernel test suite
> + *              called by the osd_uld module

Why do we need in-kernel test suite?

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 07/18] osd_ktests: Add basic OSD tests
  2009-01-06 14:42     ` FUJITA Tomonori
@ 2009-01-06 14:56       ` Boaz Harrosh
  2009-01-06 15:12         ` FUJITA Tomonori
  0 siblings, 1 reply; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 14:56 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: James.Bottomley, linux-scsi, osd-dev, akpm

FUJITA Tomonori wrote:
> On Tue,  6 Jan 2009 16:17:16 +0200
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> Currently testing what is implemented in the osd_initiator library.
>> That is - format, create/remove partition, create/remove object,
>> read and write to objects.
>>
>> This test passes against the IBM-OSD-SIM OSDv1 target.
>>
>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>> Reviewed-by: Benny Halevy <bhalevy@panasas.com>
>> ---
>>  drivers/scsi/osd/Kbuild       |    2 +-
>>  drivers/scsi/osd/osd_ktests.c |  331 +++++++++++++++++++++++++++++++++++++++++
>>  drivers/scsi/osd/osd_ktests.h |    4 +
>>  drivers/scsi/osd/osd_uld.c    |    2 +-
>>  4 files changed, 337 insertions(+), 2 deletions(-)
>>  create mode 100644 drivers/scsi/osd/osd_ktests.c
>>
>> diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
>> index 4730cdc..6fb823f 100644
>> --- a/drivers/scsi/osd/Kbuild
>> +++ b/drivers/scsi/osd/Kbuild
>> @@ -35,5 +35,5 @@ libosd-y := osd_initiator.o
>>  obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
>>  
>>  # osd.ko - SCSI ULD and char-device
>> -osd-y := osd_uld.o
>> +osd-y := osd_uld.o osd_ktests.o
>>  obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
>> diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
>> new file mode 100644
>> index 0000000..fba4934
>> --- /dev/null
>> +++ b/drivers/scsi/osd/osd_ktests.c
>> @@ -0,0 +1,331 @@
>> +/*
>> + * osd_ktests.c - An osd_initiator library in-kernel test suite
>> + *              called by the osd_uld module
> 
> Why do we need in-kernel test suite?

It must be in kernel, because it tests the in-kernel library.
However it could be in it's own Module, which makes it more
complicated, but doable.

Please note that the submitted tests are the bare minimum and
will be enhanced in the future. Perhaps later when the test grow
I will put them in their own module.

The test is most valuable when bringing up a new target/initiator
to check for compatibility. I'll send a patch ASAP that adds an
option to Kconfigure it out of compilation.

Thanks
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 07/18] osd_ktests: Add basic OSD tests
  2009-01-06 14:56       ` Boaz Harrosh
@ 2009-01-06 15:12         ` FUJITA Tomonori
  2009-01-06 15:49           ` Boaz Harrosh
  0 siblings, 1 reply; 183+ messages in thread
From: FUJITA Tomonori @ 2009-01-06 15:12 UTC (permalink / raw)
  To: bharrosh; +Cc: fujita.tomonori, James.Bottomley, linux-scsi, osd-dev, akpm

On Tue, 06 Jan 2009 16:56:23 +0200
Boaz Harrosh <bharrosh@panasas.com> wrote:

> FUJITA Tomonori wrote:
> > On Tue,  6 Jan 2009 16:17:16 +0200
> > Boaz Harrosh <bharrosh@panasas.com> wrote:
> > 
> >> Currently testing what is implemented in the osd_initiator library.
> >> That is - format, create/remove partition, create/remove object,
> >> read and write to objects.
> >>
> >> This test passes against the IBM-OSD-SIM OSDv1 target.
> >>
> >> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> >> Reviewed-by: Benny Halevy <bhalevy@panasas.com>
> >> ---
> >>  drivers/scsi/osd/Kbuild       |    2 +-
> >>  drivers/scsi/osd/osd_ktests.c |  331 +++++++++++++++++++++++++++++++++++++++++
> >>  drivers/scsi/osd/osd_ktests.h |    4 +
> >>  drivers/scsi/osd/osd_uld.c    |    2 +-
> >>  4 files changed, 337 insertions(+), 2 deletions(-)
> >>  create mode 100644 drivers/scsi/osd/osd_ktests.c
> >>
> >> diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
> >> index 4730cdc..6fb823f 100644
> >> --- a/drivers/scsi/osd/Kbuild
> >> +++ b/drivers/scsi/osd/Kbuild
> >> @@ -35,5 +35,5 @@ libosd-y := osd_initiator.o
> >>  obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
> >>  
> >>  # osd.ko - SCSI ULD and char-device
> >> -osd-y := osd_uld.o
> >> +osd-y := osd_uld.o osd_ktests.o
> >>  obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
> >> diff --git a/drivers/scsi/osd/osd_ktests.c b/drivers/scsi/osd/osd_ktests.c
> >> new file mode 100644
> >> index 0000000..fba4934
> >> --- /dev/null
> >> +++ b/drivers/scsi/osd/osd_ktests.c
> >> @@ -0,0 +1,331 @@
> >> +/*
> >> + * osd_ktests.c - An osd_initiator library in-kernel test suite
> >> + *              called by the osd_uld module
> > 
> > Why do we need in-kernel test suite?
> 
> It must be in kernel, because it tests the in-kernel library.
> However it could be in it's own Module, which makes it more
> complicated, but doable.

Why do we need the code to tests the in-kernel library?

I expect that you guys have tested the osd in-kernel library heavily
and will. I don't think people want to do the same. Then why do we
need to have the test suite in mainline?


> Please note that the submitted tests are the bare minimum and
> will be enhanced in the future. Perhaps later when the test grow
> I will put them in their own module.

If you can have it as a module, it's very easy for you guys to keep it
out-of-mainline.

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 07/18] osd_ktests: Add basic OSD tests
  2009-01-06 15:12         ` FUJITA Tomonori
@ 2009-01-06 15:49           ` Boaz Harrosh
  2009-01-06 16:58             ` FUJITA Tomonori
  0 siblings, 1 reply; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 15:49 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: James.Bottomley, linux-scsi, osd-dev, akpm

FUJITA Tomonori wrote:
> On Tue, 06 Jan 2009 16:56:23 +0200
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> FUJITA Tomonori wrote:
>>> On Tue,  6 Jan 2009 16:17:16 +0200
>>> Why do we need in-kernel test suite?
>> It must be in kernel, because it tests the in-kernel library.
>> However it could be in it's own Module, which makes it more
>> complicated, but doable.
> 
> Why do we need the code to tests the in-kernel library?
> 
> I expect that you guys have tested the osd in-kernel library heavily
> and will. I don't think people want to do the same. Then why do we
> need to have the test suite in mainline?
> 

one - There are things that can regress. Lots of stuff in current
kernel are only used by OSD, like bidi and varlen. all the way down
to LLDs. So this should be a regression test for future kernels.

two - To test compatibility, some thing is broken, the test can help
pinpoint the problems. So it's a debugging tool.

Sure, the lib itself is heavily tested but this is to test the
round trip.

> 
>> Please note that the submitted tests are the bare minimum and
>> will be enhanced in the future. Perhaps later when the test grow
>> I will put them in their own module.
> 
> If you can have it as a module, it's very easy for you guys to keep it
> out-of-mainline.

I have it out-of-mainline for a long time ;). I can do that. I thought that
I should provide a minimal test, so developers can check if they broke
something. If no one wants it I'll remove it.

Thanks
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* [PATCH ver2 05/16] osd_uld: OSD scsi ULD
  2009-01-06 14:14   ` [PATCH 05/18] osd_uld: OSD scsi ULD Boaz Harrosh
@ 2009-01-06 16:47     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 16:47 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton


Add a Linux driver module that registers as a SCSI ULD and probes
for OSD type SCSI devices.

When an OSD-type SCSI device is found a character device is created
in the form of /dev/osdX - where X goes from 0 up to hard coded 64.
The Major character device number used is *260*, which is free
(as of Linux v2.6.28).

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kbuild    |    7 +
 drivers/scsi/osd/osd_uld.c |  383 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 390 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/osd_uld.c

diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
index 5672842..4730cdc 100644
--- a/drivers/scsi/osd/Kbuild
+++ b/drivers/scsi/osd/Kbuild
@@ -17,6 +17,9 @@ ifneq ($(OSD_INC),)
 CONFIG_SCSI_OSD_INITIATOR=m
 ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
 
+CONFIG_SCSI_OSD_ULD=m
+ccflags-y += -DCONFIG_SCSI_OSD_ULD -DCONFIG_SCSI_OSD_ULD_MODULE
+
 # Uncomment to turn debug on
 # ccflags-y += -DCONFIG_SCSI_OSD_DEBUG
 
@@ -30,3 +33,7 @@ endif
 # libosd.ko - osd-initiator library
 libosd-y := osd_initiator.o
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
+
+# osd.ko - SCSI ULD and char-device
+osd-y := osd_uld.o
+obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
new file mode 100644
index 0000000..fe86f08
--- /dev/null
+++ b/drivers/scsi/osd/osd_uld.c
@@ -0,0 +1,383 @@
+/*
+ * osd_uld.c - OSD Upper Layer Driver
+ *
+ * A Linux driver module that registers as a SCSI ULD and probes
+ * for OSD type SCSI devices.
+ * It's main function is to export osd devices to in-kernel users like
+ * osdfs and pNFS-objects-LD. It also provides one ioctl for running
+ * in Kernel tests.
+ *
+ * Copyright (C) 2008 Panasas Inc.  All rights reserved.
+ *
+ * Authors:
+ *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the Panasas company nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/major.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_ioctl.h>
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+
+#include "osd_debug.h"
+
+#ifndef TYPE_OSD
+#  define TYPE_OSD 0x11
+#endif
+
+#ifndef SCSI_OSD_MAJOR
+#  define SCSI_OSD_MAJOR 260
+#endif
+#define SCSI_OSD_MAX_MINOR 64
+
+static const char osd_name[] = "osd";
+static const char *osd_version_string = "open-osd 0.1.0";
+const char osd_symlink[] = "scsi_osd";
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SCSI_OSD_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_OSD);
+
+struct osd_uld_device {
+	int minor;
+	struct kref kref;
+	struct cdev cdev;
+	struct osd_dev od;
+	struct gendisk *disk;
+	struct device *class_member;
+};
+
+static void __uld_get(struct osd_uld_device *oud);
+static void __uld_put(struct osd_uld_device *oud);
+
+/*
+ * Char Device operations
+ */
+
+static int osd_uld_open(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *oud = container_of(inode->i_cdev,
+					struct osd_uld_device, cdev);
+
+	__uld_get(oud);
+	/* cache osd_uld_device on file handle */
+	file->private_data = oud;
+	OSD_DEBUG("osd_uld_open %p\n", oud);
+	return 0;
+}
+
+static int osd_uld_release(struct inode *inode, struct file *file)
+{
+	struct osd_uld_device *oud = file->private_data;
+
+	OSD_DEBUG("osd_uld_release %p\n", file->private_data);
+	file->private_data = NULL;
+	__uld_put(oud);
+	return 0;
+}
+
+static long osd_uld_ioctl(struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	struct osd_uld_device *oud = file->private_data;
+	int ret;
+
+	switch (cmd) {
+	default:
+		OSD_ERR("Unknown ioctl %d: osd_uld_device=%p\n", cmd, oud);
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+static const struct file_operations osd_fops = {
+	.owner          = THIS_MODULE,
+	.open           = osd_uld_open,
+	.release        = osd_uld_release,
+	.unlocked_ioctl = osd_uld_ioctl,
+};
+
+/*
+ * Scsi Device operations
+ */
+
+static int __detect_osd(struct osd_uld_device *oud)
+{
+	struct scsi_device *scsi_device = oud->od.scsi_device;
+	int error;
+
+	/* sending a test_unit_ready as first command seems to be needed
+	 * by some targets
+	 */
+	OSD_DEBUG("start scsi_test_unit_ready %p %p %p\n",
+			oud, scsi_device, scsi_device->request_queue);
+	error = scsi_test_unit_ready(scsi_device, 10*HZ, 5, NULL);
+	if (error)
+		OSD_ERR("warning: scsi_test_unit_ready failed\n");
+
+	return 0;
+}
+
+static struct class *osd_sysfs_class;
+static DEFINE_IDA(osd_minor_ida);
+
+static int osd_probe(struct device *dev)
+{
+	struct scsi_device *scsi_device = to_scsi_device(dev);
+	struct gendisk *disk;
+	struct osd_uld_device *oud;
+	int minor;
+	int error;
+
+	if (scsi_device->type != TYPE_OSD)
+		return -ENODEV;
+
+	do {
+		if (!ida_pre_get(&osd_minor_ida, GFP_KERNEL))
+			return -ENODEV;
+
+		error = ida_get_new(&osd_minor_ida, &minor);
+	} while (error == -EAGAIN);
+
+	if (error)
+		return error;
+	if (minor >= SCSI_OSD_MAX_MINOR) {
+		error = -EBUSY;
+		goto err_retract_minor;
+	}
+
+	error = -ENOMEM;
+	oud = kzalloc(sizeof(*oud), GFP_KERNEL);
+	if (NULL == oud)
+		goto err_retract_minor;
+
+	kref_init(&oud->kref);
+	dev_set_drvdata(dev, oud);
+	oud->minor = minor;
+
+	/* allocate a disk and set it up */
+	/* FIXME: do we need this since sg has already done that */
+	disk = alloc_disk(1);
+	if (!disk) {
+		OSD_ERR("alloc_disk failed\n");
+		goto err_free_osd;
+	}
+	disk->major = SCSI_OSD_MAJOR;
+	disk->first_minor = oud->minor;
+	sprintf(disk->disk_name, "osd%d", oud->minor);
+	oud->disk = disk;
+
+	/* hold one more reference to the scsi_device that will get released
+	 * in __release, in case a logout is happening while fs is mounted
+	 */
+	scsi_device_get(scsi_device);
+	osd_dev_init(&oud->od, scsi_device);
+
+	/* Detect the OSD Version */
+	error = __detect_osd(oud);
+	if (error) {
+		OSD_ERR("osd detection failed, non-compatible OSD device\n");
+		goto err_put_disk;
+	}
+
+	/* init the char-device for communication with user-mode */
+	cdev_init(&oud->cdev, &osd_fops);
+	oud->cdev.owner = THIS_MODULE;
+	error = cdev_add(&oud->cdev,
+			 MKDEV(SCSI_OSD_MAJOR, oud->minor), 1);
+	if (error) {
+		OSD_ERR("cdev_add failed\n");
+		goto err_put_disk;
+	}
+	kobject_get(&oud->cdev.kobj); /* 2nd ref see osd_remove() */
+
+	/* class_member */
+	oud->class_member = device_create(osd_sysfs_class, dev,
+		MKDEV(SCSI_OSD_MAJOR, oud->minor), "%s", disk->disk_name);
+	if (IS_ERR(oud->class_member)) {
+		OSD_ERR("class_device_create failed\n");
+		error = PTR_ERR(oud->class_member);
+		goto err_put_cdev;
+	}
+
+	dev_set_drvdata(oud->class_member, oud);
+	error = sysfs_create_link(&scsi_device->sdev_gendev.kobj,
+				  &oud->class_member->kobj, osd_symlink);
+	if (error)
+		OSD_ERR("warning: unable to make symlink\n");
+
+	OSD_INFO("osd_probe %s\n", disk->disk_name);
+	return 0;
+
+err_put_cdev:
+	cdev_del(&oud->cdev);
+err_put_disk:
+	scsi_device_put(scsi_device);
+	put_disk(disk);
+err_free_osd:
+	dev_set_drvdata(dev, NULL);
+	kfree(oud);
+err_retract_minor:
+	ida_remove(&osd_minor_ida, minor);
+	return error;
+}
+
+static int osd_remove(struct device *dev)
+{
+	struct scsi_device *scsi_device = to_scsi_device(dev);
+	struct osd_uld_device *oud = dev_get_drvdata(dev);
+
+	if (!oud || (oud->od.scsi_device != scsi_device)) {
+		OSD_ERR("Half cooked osd-device %p,%p || %p!=%p",
+			dev, oud, oud ? oud->od.scsi_device : NULL,
+			scsi_device);
+	}
+
+	sysfs_remove_link(&oud->od.scsi_device->sdev_gendev.kobj, osd_symlink);
+
+	if (oud->class_member)
+		device_destroy(osd_sysfs_class,
+			       MKDEV(SCSI_OSD_MAJOR, oud->minor));
+
+	/* We have 2 references to the cdev. One is released here
+	 * and also takes down the /dev/osdX mapping. The second
+	 * Will be released in __remove() after all users have released
+	 * the osd_uld_device.
+	 */
+	if (oud->cdev.owner)
+		cdev_del(&oud->cdev);
+
+	__uld_put(oud);
+	return 0;
+}
+
+static void __remove(struct kref *kref)
+{
+	struct osd_uld_device *oud = container_of(kref,
+					struct osd_uld_device, kref);
+	struct scsi_device *scsi_device = oud->od.scsi_device;
+
+	/* now let delete the char_dev */
+	kobject_put(&oud->cdev.kobj);
+
+	osd_dev_fini(&oud->od);
+	scsi_device_put(scsi_device);
+
+	OSD_INFO("osd_remove %s\n",
+		 oud->disk ? oud->disk->disk_name : NULL);
+
+	if (oud->disk)
+		put_disk(oud->disk);
+
+	ida_remove(&osd_minor_ida, oud->minor);
+	kfree(oud);
+}
+
+static void __uld_get(struct osd_uld_device *oud)
+{
+	kref_get(&oud->kref);
+}
+
+static void __uld_put(struct osd_uld_device *oud)
+{
+	kref_put(&oud->kref, __remove);
+}
+
+/*
+ * Global driver and scsi registration
+ */
+
+static struct scsi_driver osd_driver = {
+	.owner			= THIS_MODULE,
+	.gendrv = {
+		.name		= osd_name,
+		.probe		= osd_probe,
+		.remove		= osd_remove,
+	}
+};
+
+static int __init osd_uld_init(void)
+{
+	int err;
+
+	osd_sysfs_class = class_create(THIS_MODULE, osd_symlink);
+	if (IS_ERR(osd_sysfs_class)) {
+		OSD_ERR("Unable to register sysfs class => %ld\n",
+			PTR_ERR(osd_sysfs_class));
+		return PTR_ERR(osd_sysfs_class);
+	}
+
+	err = register_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0),
+				     SCSI_OSD_MAX_MINOR, osd_name);
+	if (err) {
+		OSD_ERR("Unable to register major %d for osd ULD => %d\n",
+			SCSI_OSD_MAJOR, err);
+		goto err_out;
+	}
+
+	err = scsi_register_driver(&osd_driver.gendrv);
+	if (err) {
+		OSD_ERR("scsi_register_driver failed => %d\n", err);
+		goto err_out_chrdev;
+	}
+
+	OSD_INFO("LOADED %s\n", osd_version_string);
+	return 0;
+
+err_out_chrdev:
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+err_out:
+	class_destroy(osd_sysfs_class);
+	return err;
+}
+
+static void __exit osd_uld_exit(void)
+{
+	scsi_unregister_driver(&osd_driver.gendrv);
+	unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+	class_destroy(osd_sysfs_class);
+	OSD_INFO("UNLOADED %s\n", osd_version_string);
+}
+
+module_init(osd_uld_init);
+module_exit(osd_uld_exit);
-- 
1.6.0.1



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* Re: [PATCH 07/18] osd_ktests: Add basic OSD tests
  2009-01-06 14:17   ` [PATCH 07/18] osd_ktests: Add basic OSD tests Boaz Harrosh
  2009-01-06 14:42     ` FUJITA Tomonori
@ 2009-01-06 16:49     ` Boaz Harrosh
  1 sibling, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 16:49 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Boaz Harrosh wrote:
> Currently testing what is implemented in the osd_initiator library.
> That is - format, create/remove partition, create/remove object,
> read and write to objects.
> 
> This test passes against the IBM-OSD-SIM OSDv1 target.
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> Reviewed-by: Benny Halevy <bhalevy@panasas.com>

James hi if it is decided to drop the in kernel test
then Just drop this patch. After using:
  [PATCH ver2 05/16] osd_uld: OSD scsi ULD

I sent as reply to the patch it replaces

Thanks
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 09/18] osd_ktests: Test Attribute lists
  2009-01-06 14:20   ` [PATCH 09/18] osd_ktests: Test Attribute lists Boaz Harrosh
@ 2009-01-06 16:50     ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 16:50 UTC (permalink / raw)
  To: James Bottomley, linux-scsi, open-osd ml; +Cc: Andrew Morton

Boaz Harrosh wrote:
> Add tests for setting/getting Attribute lists. All combinations
> of read/write with set/get attributes are tested.
> (6 possibilities), So all but data integrity request structure
> layouts are attempted.
> 
> This test passes against the IBM-OSD-SIM OSDv1 target.
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> Reviewed-by: Benny Halevy <bhalevy@panasas.com>

If it is decided to drop the in kernel test
then Just drop this patch to.

Thanks
Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 07/18] osd_ktests: Add basic OSD tests
  2009-01-06 15:49           ` Boaz Harrosh
@ 2009-01-06 16:58             ` FUJITA Tomonori
  2009-01-06 17:04               ` Boaz Harrosh
  0 siblings, 1 reply; 183+ messages in thread
From: FUJITA Tomonori @ 2009-01-06 16:58 UTC (permalink / raw)
  To: bharrosh; +Cc: fujita.tomonori, James.Bottomley, linux-scsi, osd-dev, akpm

On Tue, 06 Jan 2009 17:49:04 +0200
Boaz Harrosh <bharrosh@panasas.com> wrote:

> FUJITA Tomonori wrote:
> > On Tue, 06 Jan 2009 16:56:23 +0200
> > Boaz Harrosh <bharrosh@panasas.com> wrote:
> > 
> >> FUJITA Tomonori wrote:
> >>> On Tue,  6 Jan 2009 16:17:16 +0200
> >>> Why do we need in-kernel test suite?
> >> It must be in kernel, because it tests the in-kernel library.
> >> However it could be in it's own Module, which makes it more
> >> complicated, but doable.
> > 
> > Why do we need the code to tests the in-kernel library?
> > 
> > I expect that you guys have tested the osd in-kernel library heavily
> > and will. I don't think people want to do the same. Then why do we
> > need to have the test suite in mainline?
> > 
> 
> one - There are things that can regress. Lots of stuff in current
> kernel are only used by OSD, like bidi and varlen. all the way down
> to LLDs. So this should be a regression test for future kernels.

SMP has been using BIDI support. FC will use it too soon, I guess.

If you want to test bidi and varlen, you can just send SCSI commands
via bsg. That's what I did. I don't see how it can be a reason why we
need the in-kernel test suite.


> two - To test compatibility, some thing is broken, the test can help
> pinpoint the problems. So it's a debugging tool.
> 
> Sure, the lib itself is heavily tested but this is to test the
> round trip.

I think that it's fine if people want a debugging tool. I've not seen
any developer who say that.

IMHO, it's better to have only useful debugging stuff in mainline for
many people like scsi_debug.

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 07/18] osd_ktests: Add basic OSD tests
  2009-01-06 16:58             ` FUJITA Tomonori
@ 2009-01-06 17:04               ` Boaz Harrosh
  0 siblings, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-06 17:04 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: James.Bottomley, linux-scsi, osd-dev, akpm

FUJITA Tomonori wrote:
> 
> IMHO, it's better to have only useful debugging stuff in mainline for
> many people like scsi_debug.

Believe me, for any one who is using OSD this stuff is a must
just as scsi_debug.

Since everybody will run OSD in 10 years then this is very useful,
right? ;)

Anyway it is removed.

Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 17/18] osd: Kconfig file for in-tree builds
  2009-01-06 14:32   ` [PATCH 17/18] osd: Kconfig file for in-tree builds Boaz Harrosh
@ 2009-01-06 17:40     ` Randy Dunlap
  2009-01-07  8:48       ` Boaz Harrosh
  2009-01-07  8:53       ` [PATCH ver2 15/16] " Boaz Harrosh
  0 siblings, 2 replies; 183+ messages in thread
From: Randy Dunlap @ 2009-01-06 17:40 UTC (permalink / raw)
  To: Boaz Harrosh; +Cc: James Bottomley, linux-scsi, open-osd ml, Andrew Morton

Boaz Harrosh wrote:
> Kconfig file for the drivers/scsi/osd subdirectory.
> Adds the following config items:
> 	config SCSI_OSD_INITIATOR
> 	config SCSI_OSD_ULD
> 	config SCSI_OSD_DPRINT_SENSE
> 	config SCSI_OSD_DEBUG
> 
> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
> Reviewed-by: Benny Halevy <bhalevy@panasas.com>
> ---
>  drivers/scsi/osd/Kconfig |   53 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 53 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/scsi/osd/Kconfig
> 
> diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
> new file mode 100644
> index 0000000..861b5ce
> --- /dev/null
> +++ b/drivers/scsi/osd/Kconfig
> @@ -0,0 +1,53 @@
> +#
> +# Kernel configuration file for the OSD scsi protocol
> +#
> +# Copyright (C) 2008 Panasas Inc.  All rights reserved.
> +#
> +# Authors:
> +#   Boaz Harrosh <bharrosh@panasas.com>
> +#   Benny Halevy <bhalevy@panasas.com>
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public version 2 License as
> +# published by the Free Software Foundation
> +#
> +# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
> +#        How is it done properly?

Probably similar to how net/sctp/Kconfig does it:

	select CRYPTO
	select CRYPTO_HMAC
	select CRYPTO_SHA1

> +#
> +
> +config SCSI_OSD_INITIATOR
> +	tristate "OSD-Initiator library"
> +	depends on SCSI
> +	help
> +		Enable the OSD-Initiator library (libosd.ko).
> +		NOTE: You must also select CRYPTO_SHA1 + CRYPTO_HMAC and their
> +		dependencies

All of the kconfig help text indentation is incorrect.  :(
It should all be tab + 2 spaces.

> +
> +config SCSI_OSD_ULD
> +	tristate "OSD Upper Level driver"
> +	depends on SCSI_OSD_INITIATOR
> +	help
> +		Build a SCSI upper layer driver that exports /dev/osdX devices
> +		to user-mode for testing and controlling OSD devices. It is also
> +		needed by exofs, for mounting an OSD based file system.

		                                 OSD-based

> +
> +config SCSI_OSD_DPRINT_SENSE
> +    int "(0-2) When sense is returned, DEBUG print all sense descriptors"
> +    default 1
> +    depends on SCSI_OSD_INITIATOR
> +    help
> +        When a CHECK_CONDITION status is returned from a target, and a
> +        sense-buffer is retrieved, turning this on will dump a full
> +        sense-decoding message. Setting to 2 will also print recoverable
> +        errors that might be regularly returned for some filesystem
> +        operations.
> +
> +config SCSI_OSD_DEBUG
> +	bool "Compile All OSD modules with lots of DEBUG prints"
> +	default n
> +	depends on SCSI_OSD_INITIATOR
> +	help
> +		OSD Code is populated with lots of OSD_DEBUG(..) printouts to
> +		dmesg. Enable this if you found a bug and you want to help us
> +		track the problem (see also MAINTAINERS). Setting this will also
> +		force SCSI_OSD_DPRINT_SENSE=2.


-- 
~Randy

^ permalink raw reply	[flat|nested] 183+ messages in thread

* Re: [PATCH 17/18] osd: Kconfig file for in-tree builds
  2009-01-06 17:40     ` Randy Dunlap
@ 2009-01-07  8:48       ` Boaz Harrosh
  2009-01-07 17:10         ` Randy Dunlap
  2009-01-07  8:53       ` [PATCH ver2 15/16] " Boaz Harrosh
  1 sibling, 1 reply; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-07  8:48 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: James Bottomley, linux-scsi, open-osd ml, Andrew Morton

Randy Dunlap wrote:
> Boaz Harrosh wrote:
>> Kconfig file for the drivers/scsi/osd subdirectory.
>> Adds the following config items:
>> 	config SCSI_OSD_INITIATOR
>> 	config SCSI_OSD_ULD
>> 	config SCSI_OSD_DPRINT_SENSE
>> 	config SCSI_OSD_DEBUG
>>
>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>> Reviewed-by: Benny Halevy <bhalevy@panasas.com>
>> ---
>>  drivers/scsi/osd/Kconfig |   53 ++++++++++++++++++++++++++++++++++++++++++++++
>>  1 files changed, 53 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/scsi/osd/Kconfig
>>
>> diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
>> new file mode 100644
>> index 0000000..861b5ce
>> --- /dev/null
>> +++ b/drivers/scsi/osd/Kconfig
>> @@ -0,0 +1,53 @@
>> +#
>> +# Kernel configuration file for the OSD scsi protocol
>> +#
>> +# Copyright (C) 2008 Panasas Inc.  All rights reserved.
>> +#
>> +# Authors:
>> +#   Boaz Harrosh <bharrosh@panasas.com>
>> +#   Benny Halevy <bhalevy@panasas.com>
>> +#
>> +# This program is free software; you can redistribute it and/or modify
>> +# it under the terms of the GNU General Public version 2 License as
>> +# published by the Free Software Foundation
>> +#
>> +# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
>> +#        How is it done properly?
> 
> Probably similar to how net/sctp/Kconfig does it:
> 
> 	select CRYPTO
> 	select CRYPTO_HMAC
> 	select CRYPTO_SHA1
> 

It is not yet relevant, I have not submitted the security code.
But thanks, that looks doable. I have a question?
When you do select, you must manually select the fixture you need plus
all it's dependencies and their dependencies recursively, parents first?

>> +#
>> +
>> +config SCSI_OSD_INITIATOR
>> +	tristate "OSD-Initiator library"
>> +	depends on SCSI
>> +	help
>> +		Enable the OSD-Initiator library (libosd.ko).
>> +		NOTE: You must also select CRYPTO_SHA1 + CRYPTO_HMAC and their
>> +		dependencies
> 
> All of the kconfig help text indentation is incorrect.  :(
> It should all be tab + 2 spaces.
> 
>> +
>> +config SCSI_OSD_ULD
>> +	tristate "OSD Upper Level driver"
>> +	depends on SCSI_OSD_INITIATOR
>> +	help
>> +		Build a SCSI upper layer driver that exports /dev/osdX devices
>> +		to user-mode for testing and controlling OSD devices. It is also
>> +		needed by exofs, for mounting an OSD based file system.
> 
> 		                                 OSD-based
> 
>> +
>> +config SCSI_OSD_DPRINT_SENSE
>> +    int "(0-2) When sense is returned, DEBUG print all sense descriptors"
>> +    default 1
>> +    depends on SCSI_OSD_INITIATOR
>> +    help
>> +        When a CHECK_CONDITION status is returned from a target, and a
>> +        sense-buffer is retrieved, turning this on will dump a full
>> +        sense-decoding message. Setting to 2 will also print recoverable
>> +        errors that might be regularly returned for some filesystem
>> +        operations.
>> +
>> +config SCSI_OSD_DEBUG
>> +	bool "Compile All OSD modules with lots of DEBUG prints"
>> +	default n
>> +	depends on SCSI_OSD_INITIATOR
>> +	help
>> +		OSD Code is populated with lots of OSD_DEBUG(..) printouts to
>> +		dmesg. Enable this if you found a bug and you want to help us
>> +		track the problem (see also MAINTAINERS). Setting this will also
>> +		force SCSI_OSD_DPRINT_SENSE=2.
> 
> 

Thanks Randy, my first Kconfig, sorry. Should have read Documentation.
I'll post a ver2 as reply to original patch.

Boaz

^ permalink raw reply	[flat|nested] 183+ messages in thread

* [PATCH ver2 15/16] osd: Kconfig file for in-tree builds
  2009-01-06 17:40     ` Randy Dunlap
  2009-01-07  8:48       ` Boaz Harrosh
@ 2009-01-07  8:53       ` Boaz Harrosh
  1 sibling, 0 replies; 183+ messages in thread
From: Boaz Harrosh @ 2009-01-07  8:53 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: James Bottomley, linux-scsi, open-osd ml, Andrew Morton


Kconfig file for the drivers/scsi/osd subdirectory.
Adds the following config items:
	config SCSI_OSD_INITIATOR
	config SCSI_OSD_ULD
	config SCSI_OSD_DPRINT_SENSE
	config SCSI_OSD_DEBUG

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
---
 drivers/scsi/osd/Kconfig |   53 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 53 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/osd/Kconfig

diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
new file mode 100644
index 0000000..861b5ce
--- /dev/null
+++ b/drivers/scsi/osd/Kconfig
@@ -0,0 +1,53 @@
+#
+# Kernel configuration file for the OSD scsi protocol
+#
+# Copyright (C) 2008 Panasas Inc.  All rights reserved.
+#
+# Authors:
+#   Boaz Harrosh <bharrosh@panasas.com>
+#   Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public version 2 License as
+# published by the Free Software Foundation
+#
+# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
+#        How is it done properly?
+#
+
+config SCSI_OSD_INITIATOR
+	tristate "OSD-Initiator library"
+	depends on SCSI
+	help
+	  Enable the OSD-Initiator library (libosd.ko).
+	  NOTE: You must also select CRYPTO_SHA1 + CRYPTO_HMAC and their
+	  dependencies
+
+config SCSI_OSD_ULD
+	tristate "OSD Upper Level driver"
+	depends on SCSI_OSD_INITIATOR
+	help
+	  Build a SCSI upper layer driver that exports /dev/osdX devices
+	  to user-mode for testing and controlling OSD devices. It is also
+	  needed by exofs, for mounting an OSD-based file system.
+
+config SCSI_OSD_DPRINT_SENSE
+	int "(0-2) When sense is returned, DEBUG print all sense descriptors"
+	default 1
+	depends on SCSI_OSD_INITIATOR
+	help
+	  When a CHECK_CONDITION status is returned from a target, and a
+	  sense-buffer is retrieved, turning this on will dump a full
+	  sense-decoding message. Setting to 2 will also print recoverable
+	  errors that might be regularly returned for some filesystem
+	  operations.
+
+config SCSI_OSD_DEBUG
+	bool "Compile All OSD modules with lots of DEBUG prints"
+	default n
+	depends on SCSI_OSD_INITIATOR
+	help
+	  OSD Code is populated with lots of OSD_DEBUG(..) printouts to
+	  dmesg. Enable this if you found a bug and you want to help us
+	  track the problem (see also MAINTAINERS). Setting this will also
+	  force SCSI_OSD_DPRINT_SENSE=2.
-- 
1.6.0.1



^ permalink raw reply related	[flat|nested] 183+ messages in thread

* Re: [PATCH 17/18] osd: Kconfig file for in-tree builds
  2009-01-07  8:48       ` Boaz Harrosh
@ 2009-01-07 17:10         ` Randy Dunlap
  0 siblings, 0 replies; 183+ messages in thread
From: Randy Dunlap @ 2009-01-07 17:10 UTC (permalink / raw)
  To: Boaz Harrosh; +Cc: James Bottomley, linux-scsi, open-osd ml, Andrew Morton

Boaz Harrosh wrote:
> Randy Dunlap wrote:
>> Boaz Harrosh wrote:
>>> Kconfig file for the drivers/scsi/osd subdirectory.
>>> Adds the following config items:
>>> 	config SCSI_OSD_INITIATOR
>>> 	config SCSI_OSD_ULD
>>> 	config SCSI_OSD_DPRINT_SENSE
>>> 	config SCSI_OSD_DEBUG
>>>
>>> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
>>> Reviewed-by: Benny Halevy <bhalevy@panasas.com>
>>> ---
>>>  drivers/scsi/osd/Kconfig |   53 ++++++++++++++++++++++++++++++++++++++++++++++
>>>  1 files changed, 53 insertions(+), 0 deletions(-)
>>>  create mode 100644 drivers/scsi/osd/Kconfig
>>>
>>> diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
>>> new file mode 100644
>>> index 0000000..861b5ce
>>> --- /dev/null
>>> +++ b/drivers/scsi/osd/Kconfig
>>> @@ -0,0 +1,53 @@
>>> +#
>>> +# Kernel configuration file for the OSD scsi protocol
>>> +#
>>> +# Copyright (C) 2008 Panasas Inc.  All rights reserved.
>>> +#
>>> +# Authors:
>>> +#   Boaz Harrosh <bharrosh@panasas.com>
>>> +#   Benny Halevy <bhalevy@panasas.com>
>>> +#
>>> +# This program is free software; you can redistribute it and/or modify
>>> +# it under the terms of the GNU General Public version 2 License as
>>> +# published by the Free Software Foundation
>>> +#
>>> +# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
>>> +#        How is it done properly?
>> Probably similar to how net/sctp/Kconfig does it:
>>
>> 	select CRYPTO
>> 	select CRYPTO_HMAC
>> 	select CRYPTO_SHA1
>>
> 
> It is not yet relevant, I have not submitted the security code.
> But thanks, that looks doable. I have a question?
> When you do select, you must manually select the fixture you need plus
> all it's dependencies and their dependencies recursively, parents first?

'select' does not follow any dependency chains, so you need to
select all of them yourself.  I don't know that "parents first"
is required.

-- 
~Randy

^ permalink raw reply	[flat|nested] 183+ messages in thread

end of thread, other threads:[~2009-01-07 17:11 UTC | newest]

Thread overview: 183+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <48876009.8010701@panasas.com>
2008-07-24 17:30 ` [RFC 00/14] open-osd: OSD Initiator library for Linux Boaz Harrosh
2008-07-24 17:40   ` [RFC 01/14] libosd: OSDv1 Headers Boaz Harrosh
2008-07-24 17:45   ` [RFC 02/14] libosd: OSDv1 preliminary implementation Boaz Harrosh
2008-07-24 17:47   ` [RFC 03/14] osd_uld: OSD scsi ULD Boaz Harrosh
2008-07-27 21:16     ` James Bottomley
2008-08-06 17:25       ` Boaz Harrosh
2008-07-24 17:49   ` [RFC 04/14] osd_ktests: Add basic OSD tests Boaz Harrosh
2008-07-24 17:51   ` [RFC 05/14] libosd: attributes Support Boaz Harrosh
2008-07-24 17:53   ` [RFC 06/14] osd_ktests: Test Attribute lists Boaz Harrosh
2008-07-24 17:54   ` [RFC 07/14] libosd: OSD Security processing stubs Boaz Harrosh
2008-07-24 17:55   ` [RFC 08/14] libosd: Add Flush and List-objects support Boaz Harrosh
2008-07-24 17:57   ` [RFC 09/14] libosd: Not implemented commands Boaz Harrosh
2008-07-24 17:58   ` [RFC 10/14] libosd: OSD version 2 Support Boaz Harrosh
2008-07-24 17:59   ` [RFC 11/14] osd_ktests: OSDv2 auto detection Boaz Harrosh
2008-07-24 18:00   ` [RFC 12/14] osd: Kconfig file for in-tree builds Boaz Harrosh
2008-07-24 18:02   ` [RFC 13/14] osd: Documentation for OSD library Boaz Harrosh
2008-07-24 18:03   ` [RFC 14/14] scsi: Add osd library to build system Boaz Harrosh
2008-11-04 16:09 ` [PATCHSET 00/18] open-osd: OSD Initiator library for Linux Boaz Harrosh
2008-11-04 16:09   ` Boaz Harrosh
2008-11-04 16:17   ` [PATCH 01/18] major.h: char-major number for OSD device driver Boaz Harrosh
2008-11-04 16:17     ` Boaz Harrosh
2008-11-26 17:33     ` [osd-dev] " Boaz Harrosh
2008-11-26 18:07       ` Randy Dunlap
2008-11-26 18:07         ` Randy Dunlap
2008-11-04 16:42   ` [PATCH 02/18] scsi: OSD_TYPE Boaz Harrosh
2008-11-04 16:42   ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 03/18] libosd: OSDv1 Headers Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 19:10     ` Andrew Morton
2008-11-04 19:42       ` Jörn Engel
2008-11-04 19:42         ` Jörn Engel
2008-11-04 20:29         ` Jörn Engel
2008-11-05 13:00         ` Boaz Harrosh
2008-11-05 13:00           ` Boaz Harrosh
2008-11-05 12:54       ` Boaz Harrosh
2008-11-05 12:54         ` Boaz Harrosh
2008-11-05 13:09         ` James Bottomley
2008-11-05 13:29           ` Boaz Harrosh
2008-11-09 14:52     ` [PATCH 03/18 ver2] " Boaz Harrosh
2008-11-09 14:52       ` Boaz Harrosh
2008-11-09 17:45       ` Jörn Engel
2008-11-09 17:45         ` Jörn Engel
2008-11-10  8:47         ` Boaz Harrosh
2008-11-10  8:47           ` Boaz Harrosh
2008-11-10 15:17           ` Jörn Engel
2008-11-10 15:17             ` Jörn Engel
2008-11-10 17:29       ` Randy Dunlap
2008-11-12 13:10         ` Boaz Harrosh
2008-11-12 13:10           ` Boaz Harrosh
2008-11-12 16:48           ` Randy Dunlap
2008-11-12 17:09             ` Boaz Harrosh
2008-11-12 17:15             ` Johannes Berg
2008-11-12 13:13         ` [PATCH 03/18 ver3] " Boaz Harrosh
2008-11-12 13:13           ` Boaz Harrosh
2008-11-12 18:59           ` Randy Dunlap
2008-11-13  9:38             ` Boaz Harrosh
2008-11-13 12:25             ` [PATCH 03/18 ver4] " Boaz Harrosh
2008-11-13 12:25               ` Boaz Harrosh
2008-11-13 18:16               ` Randy Dunlap
2008-11-13 15:41                 ` [osd-dev] " Benny Halevy
2008-11-04 16:44   ` [PATCH 04/18] libosd: OSDv1 preliminary implementation Boaz Harrosh
2008-11-04 18:03     ` Sam Ravnborg
2008-11-05 13:12       ` Boaz Harrosh
2008-11-09 14:55         ` [osd-dev] " Boaz Harrosh
2008-11-10  5:37           ` Randy Dunlap
2008-11-10  9:00             ` Boaz Harrosh
2008-11-05 16:39       ` [Patch] Always include <linux/types.h> Jörn Engel
2008-11-05 17:23         ` Alexey Dobriyan
2008-11-05 19:16           ` Jörn Engel
2008-11-05 19:48             ` Andreas Schwab
2008-11-05 20:02             ` Jörn Engel
2008-11-05 20:32               ` Alexey Dobriyan
2008-11-07  8:02                 ` Jörn Engel
2008-11-05 20:20             ` Alexey Dobriyan
2008-11-05 17:48         ` Boaz Harrosh
2008-11-04 19:16     ` [PATCH 04/18] libosd: OSDv1 preliminary implementation Andrew Morton
2008-11-05 13:44       ` Boaz Harrosh
2008-11-09 14:50     ` [PATCH 04/18 ver2] " Boaz Harrosh
2008-11-04 16:44   ` [PATCH 04/18] " Boaz Harrosh
2008-11-04 16:44   ` [PATCH 05/18] osd_uld: OSD scsi ULD Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 07/18] osd_test: User-mode application to run the OSD tests Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 08/18] osd_ktests: Add basic " Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 09/18] libosd: attributes Support Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 10/18] osd_ktests: Test Attribute lists Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 11/18] libosd: OSD Security processing stubs Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 12/18] libosd: Add Flush and List-objects support Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 13/18] libosd: Not implemented commands Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 14/18] libosd: OSD version 2 Support Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 15/18] libosd: OSDv2 auto detection Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 16/18] osd: Documentation for OSD library Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 17/18] osd: Kconfig file for in-tree builds Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 16:44   ` [PATCH 18/18] scsi: Add osd library to build system Boaz Harrosh
2008-11-04 16:44     ` Boaz Harrosh
2008-11-04 19:19   ` [PATCHSET 00/18] open-osd: OSD Initiator library for Linux Andrew Morton
2008-11-05 13:56     ` Boaz Harrosh
2008-11-09 14:58     ` Boaz Harrosh
2008-11-09 23:26       ` Stephen Rothwell
2008-11-10 12:52         ` Boaz Harrosh
2008-11-10 13:04           ` Stephen Rothwell
2008-12-22 12:32 ` Boaz Harrosh
2008-12-22 12:32   ` Boaz Harrosh
2008-12-22 12:37   ` [PATCH 01/18] major.h: char-major number for OSD device driver Boaz Harrosh
2008-12-22 12:37     ` Boaz Harrosh
2008-12-22 12:39   ` [PATCH 02/18] scsi: OSD_TYPE Boaz Harrosh
2008-12-22 12:39     ` Boaz Harrosh
2008-12-22 12:41   ` [PATCH 03/18] libosd: OSDv1 Headers Boaz Harrosh
2008-12-22 12:41     ` Boaz Harrosh
2008-12-22 12:43   ` [PATCH 04/18] libosd: OSDv1 preliminary implementation Boaz Harrosh
2008-12-22 12:43     ` Boaz Harrosh
2008-12-22 12:46   ` [PATCH 05/18] osd_uld: OSD scsi ULD Boaz Harrosh
2008-12-22 12:46     ` Boaz Harrosh
2008-12-22 12:49   ` [PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel Boaz Harrosh
2008-12-22 12:49     ` Boaz Harrosh
2008-12-22 12:51   ` [PATCH 07/18] osd_ktests: Add basic OSD tests Boaz Harrosh
2008-12-22 12:51     ` Boaz Harrosh
2008-12-22 12:55   ` [PATCH 08/18] libosd: attributes Support Boaz Harrosh
2008-12-22 12:55     ` Boaz Harrosh
2008-12-22 12:57   ` [PATCH 09/18] osd_ktests: Test Attribute lists Boaz Harrosh
2008-12-22 12:57     ` Boaz Harrosh
2008-12-22 13:00   ` [PATCH 10/18] libosd: OSD Security processing stubs Boaz Harrosh
2008-12-22 13:00     ` Boaz Harrosh
2008-12-22 13:02   ` [PATCH 11/18] libosd: Add Flush and List-objects support Boaz Harrosh
2008-12-22 13:02     ` Boaz Harrosh
2008-12-22 13:04   ` [PATCH 12/18] libosd: Not implemented commands Boaz Harrosh
2008-12-22 13:04     ` Boaz Harrosh
2008-12-22 13:07   ` [PATCH 13/18] libosd: OSD version 2 Support Boaz Harrosh
2008-12-22 13:07     ` Boaz Harrosh
2008-12-22 13:09   ` [PATCH 14/18] libosd: OSDv2 auto detection Boaz Harrosh
2008-12-22 13:09     ` Boaz Harrosh
2008-12-22 13:13   ` [PATCH 15/18] libosd: SCSI/OSD Sense decoding support Boaz Harrosh
2008-12-22 13:13     ` Boaz Harrosh
2008-12-22 13:16   ` [PATCH 16/18] osd: Documentation for OSD library Boaz Harrosh
2008-12-22 13:16     ` Boaz Harrosh
2008-12-22 13:18   ` [PATCH 17/18] osd: Kconfig file for in-tree builds Boaz Harrosh
2008-12-22 13:18     ` Boaz Harrosh
2008-12-22 13:20   ` [PATCH 18/18] scsi: Add osd library to build system Boaz Harrosh
2008-12-22 13:20     ` Boaz Harrosh
2009-01-06 14:04 ` [PATCHSET 00/18] open-osd: OSD Initiator library for 2.6.29 Boaz Harrosh
2009-01-06 14:07   ` [PATCH 01/18] major.h: char-major number for OSD device driver Boaz Harrosh
2009-01-06 14:10   ` [PATCH 02/18] scsi: OSD_TYPE Boaz Harrosh
2009-01-06 14:11   ` [PATCH 03/18] libosd: OSDv1 Headers Boaz Harrosh
2009-01-06 14:13   ` [PATCH 04/18] libosd: OSDv1 preliminary implementation Boaz Harrosh
2009-01-06 14:14   ` [PATCH 05/18] osd_uld: OSD scsi ULD Boaz Harrosh
2009-01-06 16:47     ` [PATCH ver2 05/16] " Boaz Harrosh
2009-01-06 14:16   ` [PATCH 06/18] osd_uld: API for retrieving osd devices from Kernel Boaz Harrosh
2009-01-06 14:17   ` [PATCH 07/18] osd_ktests: Add basic OSD tests Boaz Harrosh
2009-01-06 14:42     ` FUJITA Tomonori
2009-01-06 14:56       ` Boaz Harrosh
2009-01-06 15:12         ` FUJITA Tomonori
2009-01-06 15:49           ` Boaz Harrosh
2009-01-06 16:58             ` FUJITA Tomonori
2009-01-06 17:04               ` Boaz Harrosh
2009-01-06 16:49     ` Boaz Harrosh
2009-01-06 14:19   ` [PATCH 08/18] libosd: attributes Support Boaz Harrosh
2009-01-06 14:20   ` [PATCH 09/18] osd_ktests: Test Attribute lists Boaz Harrosh
2009-01-06 16:50     ` Boaz Harrosh
2009-01-06 14:21   ` [PATCH 10/18] libosd: OSD Security processing stubs Boaz Harrosh
2009-01-06 14:23   ` [PATCH 11/18] libosd: Add Flush and List-objects support Boaz Harrosh
2009-01-06 14:24   ` [PATCH 12/18] libosd: Not implemented commands Boaz Harrosh
2009-01-06 14:25   ` [PATCH 13/18] libosd: OSD version 2 Support Boaz Harrosh
2009-01-06 14:27   ` [PATCH 14/18] libosd: OSDv2 auto detection Boaz Harrosh
2009-01-06 14:29   ` [PATCH 15/18] libosd: SCSI/OSD Sense decoding support Boaz Harrosh
2009-01-06 14:31   ` [PATCH 16/18] osd: Documentation for OSD library Boaz Harrosh
2009-01-06 14:32   ` [PATCH 17/18] osd: Kconfig file for in-tree builds Boaz Harrosh
2009-01-06 17:40     ` Randy Dunlap
2009-01-07  8:48       ` Boaz Harrosh
2009-01-07 17:10         ` Randy Dunlap
2009-01-07  8:53       ` [PATCH ver2 15/16] " Boaz Harrosh
2009-01-06 14:34   ` [PATCH 18/18] scsi: Add osd library to build system Boaz Harrosh

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.