Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | /*
* Copyright (C) 2005, 2006
* Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com)
* Copyright (C) 2005, 2006
* International Business Machines
* Copyright (C) 2008, 2009
* Boaz Harrosh <bharrosh@panasas.com>
*
* This file is part of exofs.
*
* exofs is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation. Since it is based on ext2, and the only
* valid version of GPL for the Linux kernel is version 2, the only valid
* version of GPL for exofs is version 2.
*
* exofs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with exofs; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <scsi/scsi_device.h>
#include <scsi/osd_sense.h>
#include "exofs.h"
int exofs_check_ok_resid(struct osd_request *or, u64 *in_resid, u64 *out_resid)
{
struct osd_sense_info osi;
int ret = osd_req_decode_sense(or, &osi);
if (ret) { /* translate to Linux codes */
if (osi.additional_code == scsi_invalid_field_in_cdb) {
if (osi.cdb_field_offset == OSD_CFO_STARTING_BYTE)
ret = -EFAULT;
if (osi.cdb_field_offset == OSD_CFO_OBJECT_ID)
ret = -ENOENT;
else
ret = -EINVAL;
} else if (osi.additional_code == osd_quota_error)
ret = -ENOSPC;
else
ret = -EIO;
}
/* FIXME: should be include in osd_sense_info */
if (in_resid)
*in_resid = or->in.req ? or->in.req->data_len : 0;
if (out_resid)
*out_resid = or->out.req ? or->out.req->data_len : 0;
return ret;
}
void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], const struct osd_obj_id *obj)
{
osd_sec_init_nosec_doall_caps(cred_a, obj, false, true);
}
/*
* Perform a synchronous OSD operation.
*/
int exofs_sync_op(struct osd_request *or, int timeout, uint8_t *credential)
{
int ret;
or->timeout = timeout;
ret = osd_finalize_request(or, 0, credential, NULL);
if (ret) {
EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n", ret);
return ret;
}
ret = osd_execute_request(or);
if (ret)
EXOFS_DBGMSG("osd_execute_request() => %d\n", ret);
/* osd_req_decode_sense(or, ret); */
return ret;
}
/*
* Perform an asynchronous OSD operation.
*/
int exofs_async_op(struct osd_request *or, osd_req_done_fn *async_done,
void *caller_context, u8 *cred)
{
int ret;
ret = osd_finalize_request(or, 0, cred, NULL);
if (ret) {
EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n", ret);
return ret;
}
ret = osd_execute_request_async(or, async_done, caller_context);
if (ret)
EXOFS_DBGMSG("osd_execute_request_async() => %d\n", ret);
return ret;
}
int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr)
{
struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */
void *iter = NULL;
int nelem;
do {
nelem = 1;
osd_req_decode_get_attr_list(or, &cur_attr, &nelem, &iter);
if ((cur_attr.attr_page == attr->attr_page) &&
(cur_attr.attr_id == attr->attr_id)) {
attr->len = cur_attr.len;
attr->val_ptr = cur_attr.val_ptr;
return 0;
}
} while (iter);
return -EIO;
}
int osd_req_read_kern(struct osd_request *or,
const struct osd_obj_id *obj, u64 offset, void* buff, u64 len)
{
struct request_queue *req_q = or->osd_dev->scsi_device->request_queue;
struct bio *bio = bio_map_kern(req_q, buff, len, GFP_KERNEL);
if (!bio)
return -ENOMEM;
osd_req_read(or, obj, bio, offset);
return 0;
}
int osd_req_write_kern(struct osd_request *or,
const struct osd_obj_id *obj, u64 offset, void* buff, u64 len)
{
struct request_queue *req_q = or->osd_dev->scsi_device->request_queue;
struct bio *bio = bio_map_kern(req_q, buff, len, GFP_KERNEL);
if (!bio)
return -ENOMEM;
osd_req_write(or, obj, bio, offset);
return 0;
}
|