1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (c) 2001, 2002 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
22 #include <linux/version.h>
23 #include <linux/module.h>
26 #define DEBUG_SUBSYSTEM S_ECHO
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>
34 static int echo_iocontrol(long cmd, struct lustre_handle *obdconn, int len,
35 void *karg, void *uarg)
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;
44 CERROR("ioctl: No device\n");
45 GOTO(out, rc = -EINVAL);
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);
57 rc = obd_getattr(&ec->conn, &data->ioc_obdo1, NULL);
61 rc = obd_setattr(&ec->conn, &data->ioc_obdo1, NULL);
64 case OBD_IOC_DESTROY: {
66 rc = obd_destroy(&ec->conn, &data->ioc_obdo1, NULL);
71 struct lov_stripe_md *lsm = NULL; // XXX fill in from create
73 rc = obd_open(&ec->conn, &data->ioc_obdo1, lsm);
78 struct lov_stripe_md *lsm = NULL; // XXX fill in from create
80 rc = obd_close(&ec->conn, &data->ioc_obdo1, lsm);
84 case OBD_IOC_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;
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);
98 set = obd_brw_set_new();
100 GOTO(out, rc = -ENOMEM);
102 pages = data->ioc_count / PAGE_SIZE;
103 off = data->ioc_offset;
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));
109 CERROR("no memory for %d BRW per-page data\n", pages);
110 GOTO(brw_free, rc = -ENOMEM);
113 memset(lsm, 0, sizeof(*lsm)); // XXX don't do this later
114 lsm->lsm_object_id = id; // ensure id == lsm->lsm_object_id
116 for (j = 0, pgp = pga; j < pages; j++, off += PAGE_SIZE, pgp++){
117 pgp->pg = alloc_pages(gfp_mask, 0);
119 CERROR("no memory for brw pages\n");
120 GOTO(brw_cleanup, rc = -ENOMEM);
122 pgp->count = PAGE_SIZE;
127 void *addr = kmap(pgp->pg);
129 if (rw == OBD_BRW_WRITE)
130 page_debug_setup(addr, pgp->count,
133 page_debug_setup(addr, pgp->count,
140 set->brw_callback = ll_brw_sync_wait;
141 rc = obd_brw(rw, &ec->conn, lsm, j, pga, set);
143 CERROR("test_brw: error from obd_brw: rc = %d\n", rc);
145 rc = ll_brw_sync_wait(set, CB_PHASE_START);
147 CERROR("test_brw: error from callback: rc = "
152 for (j = 0, pgp = pga; j < pages; j++, pgp++) {
157 void *addr = kmap(pgp->pg);
159 rc = page_debug_check("test_brw", addr,
160 PAGE_SIZE, pgp->off, id);
163 __free_pages(pgp->pg, 0);
166 obd_brw_set_free(set);
167 OBD_FREE(pga, pages * sizeof(*pga));
178 static int echo_setup(struct obd_device *obddev, obd_count len, void *buf)
180 struct obd_ioctl_data* data = buf;
181 struct echo_client_obd *ec = &obddev->u.echo_client;
182 struct obd_device *tgt;
186 if (data->ioc_inllen1 < 1) {
187 CERROR("requires a TARGET OBD UUID\n");
190 if (data->ioc_inllen1 > 37) {
191 CERROR("OBD UUID must be less than 38 characters\n");
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",
201 GOTO(error_dec, rc = -EINVAL);
204 rc = obd_connect(&ec->conn, tgt, NULL, NULL, NULL);
206 CERROR("fail to connect to device %d\n", data->ioc_dev);
207 GOTO(error_dec, rc = -EINVAL);
215 static int echo_cleanup(struct obd_device * obddev)
217 struct echo_client_obd *ec = &obddev->u.echo_client;
221 if (!list_empty(&obddev->obd_exports)) {
222 CERROR("still has clients!\n");
226 rc = obd_disconnect(&ec->conn);
228 CERROR("fail to disconnect device: %d\n", rc);
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)
240 return class_connect(conn, src, cluuid);
243 static struct obd_ops echo_obd_ops = {
245 o_cleanup: echo_cleanup,
246 o_iocontrol: echo_iocontrol,
247 o_connect: echo_connect,
248 o_disconnect: class_disconnect
251 int echo_client_init(void)
253 extern struct lprocfs_vars status_class_var[];
255 return class_register_type(&echo_obd_ops, status_class_var,
256 OBD_ECHO_CLIENT_DEVICENAME);
259 void echo_client_cleanup(void)
261 class_unregister_type(OBD_ECHO_CLIENT_DEVICENAME);