Whamcloud - gitweb
524e779d624985395e3daa7ebf6e4bfad90dac59
[fs/lustre-release.git] / lustre / obdecho / echo_client.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2001, 2002 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include <linux/version.h>
23 #include <linux/module.h>
24 #include <linux/fs.h>
25
26 #define DEBUG_SUBSYSTEM S_ECHO
27
28 #include <linux/obd_support.h>
29 #include <linux/obd_class.h>
30 #include <linux/obd_echo.h>
31 #include <linux/lustre_debug.h>
32 #include <linux/lprocfs_status.h>
33
34 static int echo_iocontrol(long cmd, struct lustre_handle *obdconn, int len,
35                           void *karg, void *uarg)
36 {
37         struct obd_device *obd = class_conn2obd(obdconn);
38         struct echo_client_obd *ec = &obd->u.echo_client;
39         struct obd_ioctl_data *data = karg;
40         int rw = OBD_BRW_READ, rc = 0;
41         ENTRY;
42
43         if (obd == NULL) {
44                 CERROR("ioctl: No device\n");
45                 GOTO(out, rc = -EINVAL);
46         }
47
48         switch (cmd) {
49         case OBD_IOC_CREATE: {
50                 struct lov_stripe_md *lsm = NULL;
51 #warning FIXME: save lsm into file handle for other ops, release on close
52                 rc = obd_create(&ec->conn, &data->ioc_obdo1, &lsm);
53                 GOTO(out, rc);
54         }
55
56         case OBD_IOC_GETATTR:
57                 rc = obd_getattr(&ec->conn, &data->ioc_obdo1, NULL);
58                 GOTO(out, rc);
59
60         case OBD_IOC_SETATTR:
61                 rc = obd_setattr(&ec->conn, &data->ioc_obdo1, NULL);
62                 GOTO(out, rc);
63
64         case OBD_IOC_DESTROY: {
65                 //void *ea;
66                 rc = obd_destroy(&ec->conn, &data->ioc_obdo1, NULL);
67                 GOTO(out, rc);
68         }
69
70         case OBD_IOC_OPEN: {
71                 struct lov_stripe_md *lsm = NULL; // XXX fill in from create
72
73                 rc = obd_open(&ec->conn, &data->ioc_obdo1, lsm);
74                 GOTO(out, rc);
75         }
76
77         case OBD_IOC_CLOSE: {
78                 struct lov_stripe_md *lsm = NULL; // XXX fill in from create
79
80                 rc = obd_close(&ec->conn, &data->ioc_obdo1, lsm);
81                 GOTO(out, rc);
82         }
83
84         case OBD_IOC_BRW_WRITE:
85                 rw = OBD_BRW_WRITE;
86         case OBD_IOC_BRW_READ: {
87                 struct lov_stripe_md tmp_lsm; // XXX fill in from create
88                 struct lov_stripe_md *lsm = &tmp_lsm; // XXX fill in from create
89                 struct obd_brw_set *set;
90                 obd_count pages = 0;
91                 struct brw_page *pga, *pgp;
92                 __u64 id = data->ioc_obdo1.o_id;
93                 int gfp_mask = (id & 1) ? GFP_HIGHUSER : GFP_KERNEL;
94                 int verify = (id != 0);
95                 __u64 off;
96                 int j;
97
98                 set = obd_brw_set_new();
99                 if (set == NULL)
100                         GOTO(out, rc = -ENOMEM);
101
102                 pages = data->ioc_count / PAGE_SIZE;
103                 off = data->ioc_offset;
104
105                 CDEBUG(D_INODE, "BRW %s with %d pages @ "LPX64"\n",
106                        rw == OBD_BRW_READ ? "read" : "write", pages, off);
107                 OBD_ALLOC(pga, pages * sizeof(*pga));
108                 if (!pga) {
109                         CERROR("no memory for %d BRW per-page data\n", pages);
110                         GOTO(brw_free, rc = -ENOMEM);
111                 }
112
113                 memset(lsm, 0, sizeof(*lsm)); // XXX don't do this later
114                 lsm->lsm_object_id = id; // ensure id == lsm->lsm_object_id
115
116                 for (j = 0, pgp = pga; j < pages; j++, off += PAGE_SIZE, pgp++){
117                         pgp->pg = alloc_pages(gfp_mask, 0);
118                         if (!pgp->pg) {
119                                 CERROR("no memory for brw pages\n");
120                                 GOTO(brw_cleanup, rc = -ENOMEM);
121                         }
122                         pgp->count = PAGE_SIZE;
123                         pgp->off = off;
124                         pgp->flag = 0;
125
126                         if (verify) {
127                                 void *addr = kmap(pgp->pg);
128
129                                 if (rw == OBD_BRW_WRITE)
130                                         page_debug_setup(addr, pgp->count,
131                                                          pgp->off, id);
132                                 else
133                                         page_debug_setup(addr, pgp->count,
134                                                          0xdeadbeef00c0ffee,
135                                                          0xdeadbeef00c0ffee);
136                                 kunmap(pgp->pg);
137                         }
138                 }
139
140                 set->brw_callback = ll_brw_sync_wait;
141                 rc = obd_brw(rw, &ec->conn, lsm, j, pga, set);
142                 if (rc)
143                         CERROR("test_brw: error from obd_brw: rc = %d\n", rc);
144                 else {
145                         rc = ll_brw_sync_wait(set, CB_PHASE_START);
146                         if (rc)
147                                 CERROR("test_brw: error from callback: rc = "
148                                        "%d\n", rc);
149                 }
150                 EXIT;
151         brw_cleanup:
152                 for (j = 0, pgp = pga; j < pages; j++, pgp++) {
153                         if (pgp->pg == NULL)
154                                 continue;
155
156                         if (verify && !rc) {
157                                 void *addr = kmap(pgp->pg);
158
159                                 rc = page_debug_check("test_brw", addr,
160                                                        PAGE_SIZE, pgp->off, id);
161                                 kunmap(pgp->pg);
162                         }
163                         __free_pages(pgp->pg, 0);
164                 }
165         brw_free:
166                 obd_brw_set_free(set);
167                 OBD_FREE(pga, pages * sizeof(*pga));
168                 GOTO(out, rc);
169         }
170         default:
171                 return -ENOTTY;
172         }
173
174  out:
175         RETURN(rc);
176 }
177
178 static int echo_setup(struct obd_device *obddev, obd_count len, void *buf)
179 {
180         struct obd_ioctl_data* data = buf;
181         struct echo_client_obd *ec = &obddev->u.echo_client;
182         struct obd_device *tgt;
183         int rc;
184         ENTRY;
185
186         if (data->ioc_inllen1 < 1) {
187                 CERROR("requires a TARGET OBD UUID\n");
188                 RETURN(-EINVAL);
189         }
190         if (data->ioc_inllen1 > 37) {
191                 CERROR("OBD UUID must be less than 38 characters\n");
192                 RETURN(-EINVAL);
193         }
194
195         MOD_INC_USE_COUNT;
196         tgt = class_uuid2obd(data->ioc_inlbuf1);
197         if (!tgt || !(tgt->obd_flags & OBD_ATTACHED) ||
198             !(tgt->obd_flags & OBD_SET_UP)) {
199                 CERROR("device not attached or not set up (%d)\n",
200                        data->ioc_dev);
201                 GOTO(error_dec, rc = -EINVAL);
202         }
203
204         rc = obd_connect(&ec->conn, tgt, NULL, NULL, NULL);
205         if (rc) {
206                 CERROR("fail to connect to device %d\n", data->ioc_dev);
207                 GOTO(error_dec, rc = -EINVAL);
208         }
209         RETURN(rc);
210 error_dec:
211         MOD_DEC_USE_COUNT;
212         RETURN(rc);
213 }
214
215 static int echo_cleanup(struct obd_device * obddev)
216 {
217         struct echo_client_obd *ec = &obddev->u.echo_client;
218         int rc;
219         ENTRY;
220
221         if (!list_empty(&obddev->obd_exports)) {
222                 CERROR("still has clients!\n");
223                 RETURN(-EBUSY);
224         }
225
226         rc = obd_disconnect(&ec->conn);
227         if (rc) {
228                 CERROR("fail to disconnect device: %d\n", rc);
229                 RETURN(-EINVAL);
230         }
231
232         MOD_DEC_USE_COUNT;
233         RETURN(0);
234 }
235
236 static int echo_connect(struct lustre_handle *conn, struct obd_device *src,
237                         obd_uuid_t cluuid, struct recovd_obd *recovd,
238                         ptlrpc_recovery_cb_t recover)
239 {
240         return class_connect(conn, src, cluuid);
241 }
242
243 static struct obd_ops echo_obd_ops = {
244         o_setup:       echo_setup,
245         o_cleanup:     echo_cleanup,
246         o_iocontrol:   echo_iocontrol,
247         o_connect:     echo_connect,
248         o_disconnect:  class_disconnect
249 };
250
251 int echo_client_init(void)
252 {
253         extern struct lprocfs_vars status_class_var[];
254
255         return class_register_type(&echo_obd_ops, status_class_var,
256                                    OBD_ECHO_CLIENT_DEVICENAME);
257 }
258
259 void echo_client_cleanup(void)
260 {
261         class_unregister_type(OBD_ECHO_CLIENT_DEVICENAME);
262 }