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