summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/osd
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2009-05-22 20:25:34 +0200
committerJens Axboe <jens.axboe@oracle.com>2009-05-22 20:25:34 +0200
commite4b636366c00738b9609cda307014d71b1225b7f (patch)
tree760b67b3624eda62e943e48ce93635c30a5b47bf /drivers/scsi/osd
parentxen-blkfront: beyond ARRAY_SIZE of info->shadow (diff)
parentMerge branch 'fixes-for-linus' of git://git.monstr.eu/linux-2.6-microblaze (diff)
downloadlinux-e4b636366c00738b9609cda307014d71b1225b7f.tar.xz
linux-e4b636366c00738b9609cda307014d71b1225b7f.zip
Merge branch 'master' into for-2.6.31
Conflicts: drivers/block/hd.c drivers/block/mg_disk.c Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/scsi/osd')
-rw-r--r--drivers/scsi/osd/osd_initiator.c125
-rw-r--r--drivers/scsi/osd/osd_uld.c20
2 files changed, 109 insertions, 36 deletions
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 865ec0f4aa80..5776b2ab6b12 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -205,6 +205,74 @@ static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
osdv2_attr_list_elem_size(len);
}
+static void _osd_req_alist_elem_encode(struct osd_request *or,
+ void *attr_last, const struct osd_attr *oa)
+{
+ if (osd_req_is_ver1(or)) {
+ struct osdv1_attributes_list_element *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);
+ } else {
+ struct osdv2_attributes_list_element *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);
+ }
+}
+
+static int _osd_req_alist_elem_decode(struct osd_request *or,
+ void *cur_p, struct osd_attr *oa, unsigned max_bytes)
+{
+ unsigned inc;
+ if (osd_req_is_ver1(or)) {
+ struct osdv1_attributes_list_element *attr = cur_p;
+
+ if (max_bytes < sizeof(*attr))
+ return -1;
+
+ oa->len = be16_to_cpu(attr->attr_bytes);
+ inc = _osd_req_alist_elem_size(or, oa->len);
+ if (inc > max_bytes)
+ return -1;
+
+ oa->attr_page = be32_to_cpu(attr->attr_page);
+ oa->attr_id = be32_to_cpu(attr->attr_id);
+
+ /* OSD1: On empty attributes we return a pointer to 2 bytes
+ * of zeros. This keeps similar behaviour with OSD2.
+ * (See below)
+ */
+ oa->val_ptr = likely(oa->len) ? attr->attr_val :
+ (u8 *)&attr->attr_bytes;
+ } else {
+ struct osdv2_attributes_list_element *attr = cur_p;
+
+ if (max_bytes < sizeof(*attr))
+ return -1;
+
+ oa->len = be16_to_cpu(attr->attr_bytes);
+ inc = _osd_req_alist_elem_size(or, oa->len);
+ if (inc > max_bytes)
+ return -1;
+
+ oa->attr_page = be32_to_cpu(attr->attr_page);
+ oa->attr_id = be32_to_cpu(attr->attr_id);
+
+ /* OSD2: For convenience, on empty attributes, we return 8 bytes
+ * of zeros here. This keeps the same behaviour with OSD2r04,
+ * and is nice with null terminating ASCII fields.
+ * oa->val_ptr == NULL marks the end-of-list, or error.
+ */
+ oa->val_ptr = likely(oa->len) ? attr->attr_val : attr->reserved;
+ }
+ return inc;
+}
+
static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
{
return osd_req_is_ver1(or) ?
@@ -282,9 +350,9 @@ _osd_req_sec_params(struct osd_request *or)
struct osd_cdb *ocdb = &or->cdb;
if (osd_req_is_ver1(or))
- return &ocdb->v1.sec_params;
+ return (struct osd_security_parameters *)&ocdb->v1.sec_params;
else
- return &ocdb->v2.sec_params;
+ return (struct osd_security_parameters *)&ocdb->v2.sec_params;
}
void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
@@ -612,9 +680,9 @@ static int _osd_req_list_objects(struct osd_request *or,
WARN_ON(or->in.bio);
bio = bio_map_kern(q, list, len, or->alloc_flags);
- if (!bio) {
+ if (IS_ERR(bio)) {
OSD_ERR("!!! Failed to allocate list_objects BIO\n");
- return -ENOMEM;
+ return PTR_ERR(bio);
}
bio->bi_rw &= ~(1 << BIO_RW);
@@ -798,7 +866,6 @@ int osd_req_add_set_attr_list(struct osd_request *or,
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;
@@ -811,11 +878,7 @@ int osd_req_add_set_attr_list(struct osd_request *or,
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);
+ _osd_req_alist_elem_encode(or, attr_last, oa);
attr_last += elem_size;
++oa;
@@ -1050,15 +1113,10 @@ int osd_req_decode_get_attr_list(struct osd_request *or,
}
for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
- struct osd_attributes_list_element *attr = cur_p;
- unsigned inc;
+ int inc = _osd_req_alist_elem_decode(or, cur_p, oa,
+ returned_bytes - cur_bytes);
- 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) {
+ if (inc < 0) {
OSD_ERR("BAD FOOD from target. list not valid!"
"c=%d r=%d n=%d\n",
cur_bytes, returned_bytes, n);
@@ -1066,10 +1124,7 @@ int osd_req_decode_get_attr_list(struct osd_request *or,
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_bytes += inc;
cur_p += inc;
++oa;
}
@@ -1139,6 +1194,24 @@ static int _osd_req_finalize_attr_page(struct osd_request *or)
return ret;
}
+static inline void osd_sec_parms_set_out_offset(bool is_v1,
+ struct osd_security_parameters *sec_parms, osd_cdb_offset offset)
+{
+ if (is_v1)
+ sec_parms->v1.data_out_integrity_check_offset = offset;
+ else
+ sec_parms->v2.data_out_integrity_check_offset = offset;
+}
+
+static inline void osd_sec_parms_set_in_offset(bool is_v1,
+ struct osd_security_parameters *sec_parms, osd_cdb_offset offset)
+{
+ if (is_v1)
+ sec_parms->v1.data_in_integrity_check_offset = offset;
+ else
+ sec_parms->v2.data_in_integrity_check_offset = offset;
+}
+
static int _osd_req_finalize_data_integrity(struct osd_request *or,
bool has_in, bool has_out, const u8 *cap_key)
{
@@ -1162,8 +1235,8 @@ static int _osd_req_finalize_data_integrity(struct osd_request *or,
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);
+ osd_sec_parms_set_out_offset(osd_req_is_ver1(or), sec_parms,
+ osd_req_encode_offset(or, or->out.total_bytes, &pad));
ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
&or->out);
@@ -1183,8 +1256,8 @@ static int _osd_req_finalize_data_integrity(struct osd_request *or,
};
unsigned pad;
- sec_parms->data_in_integrity_check_offset =
- osd_req_encode_offset(or, or->in.total_bytes, &pad);
+ osd_sec_parms_set_in_offset(osd_req_is_ver1(or), sec_parms,
+ osd_req_encode_offset(or, or->in.total_bytes, &pad));
ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
&or->in);
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index f644c9571eab..22b59e13ba83 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -173,26 +173,26 @@ static const struct file_operations osd_fops = {
.unlocked_ioctl = osd_uld_ioctl,
};
-struct osd_dev *osduld_path_lookup(const char *path)
+struct osd_dev *osduld_path_lookup(const char *name)
{
- struct nameidata nd;
+ struct path path;
struct inode *inode;
struct cdev *cdev;
struct osd_uld_device *uninitialized_var(oud);
int error;
- if (!path || !*path) {
+ if (!name || !*name) {
OSD_ERR("Mount with !path || !*path\n");
return ERR_PTR(-EINVAL);
}
- error = path_lookup(path, LOOKUP_FOLLOW, &nd);
+ error = kern_path(name, LOOKUP_FOLLOW, &path);
if (error) {
- OSD_ERR("path_lookup of %s faild=>%d\n", path, error);
+ OSD_ERR("path_lookup of %s failed=>%d\n", name, error);
return ERR_PTR(error);
}
- inode = nd.path.dentry->d_inode;
+ inode = 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");
@@ -202,15 +202,15 @@ struct osd_dev *osduld_path_lookup(const char *path)
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);
+ OSD_ERR(" user-mode must open+close the %s device\n", name);
+ OSD_ERR(" Example: bash: echo < %s\n", name);
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);
+ OSD_ERR("Error mounting %s - is not an OSD device\n", name);
goto out;
}
@@ -220,7 +220,7 @@ struct osd_dev *osduld_path_lookup(const char *path)
error = 0;
out:
- path_put(&nd.path);
+ path_put(&path);
return error ? ERR_PTR(error) : &oud->od;
}
EXPORT_SYMBOL(osduld_path_lookup);