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(unsigned int 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;
41 struct lov_stripe_md *lsm = NULL;
45 CERROR("ioctl: No device\n");
46 GOTO(out, rc = -EINVAL);
49 if (data->ioc_inllen1 == sizeof(*lsm)) {
50 lsm = (struct lov_stripe_md *)data->ioc_inlbuf1;
51 } else if (data->ioc_inllen1 != 0) {
52 CERROR("nonzero ioc_inllen1 != sizeof(struct lov_stripe_md)\n");
53 GOTO(out, rc = -EINVAL);
57 case OBD_IOC_CREATE: {
58 struct lov_stripe_md *tmp_lsm = NULL;
59 rc = obd_create(&ec->conn, &data->ioc_obdo1, &tmp_lsm);
60 if (lsm && tmp_lsm ) {
61 memcpy(lsm, tmp_lsm, sizeof(*tmp_lsm));
69 rc = obd_getattr(&ec->conn, &data->ioc_obdo1, lsm);
73 rc = obd_setattr(&ec->conn, &data->ioc_obdo1, lsm);
77 rc = obd_destroy(&ec->conn, &data->ioc_obdo1, lsm);
81 rc = obd_open(&ec->conn, &data->ioc_obdo1, lsm);
85 rc = obd_close(&ec->conn, &data->ioc_obdo1, lsm);
88 case OBD_IOC_BRW_WRITE:
90 case OBD_IOC_BRW_READ: {
91 struct lov_stripe_md tmp_lsm;
92 struct obd_brw_set *set;
94 struct brw_page *pga, *pgp;
95 __u64 off, id = data->ioc_obdo1.o_id;
96 int gfp_mask = (id & 1) ? GFP_HIGHUSER : GFP_KERNEL;
97 int j, verify = (id != 0);
99 if (lsm && lsm->lsm_object_id != id) {
100 CERROR("LSM object ID ("LPU64") != id ("LPU64")\n",
101 lsm->lsm_object_id, id);
102 GOTO(out, rc = -EINVAL);
106 memset(&tmp_lsm, 0, sizeof(tmp_lsm));
108 lsm->lsm_object_id = id;
111 if (data->ioc_count < 0) {
112 CERROR("invalid buffer size: "LPD64"\n",
114 GOTO(out, rc = -EINVAL);
117 set = obd_brw_set_new();
119 GOTO(out, rc = -ENOMEM);
121 pages = data->ioc_count / PAGE_SIZE;
122 off = data->ioc_offset;
124 CDEBUG(D_INODE, "BRW %s with %d pages @ "LPX64"\n",
125 rw == OBD_BRW_READ ? "read" : "write", pages, off);
126 OBD_ALLOC(pga, pages * sizeof(*pga));
128 CERROR("no memory for %d BRW per-page data\n", pages);
129 GOTO(brw_free, rc = -ENOMEM);
132 for (j = 0, pgp = pga; j < pages; j++, off += PAGE_SIZE, pgp++){
133 pgp->pg = alloc_pages(gfp_mask, 0);
135 CERROR("no memory for brw pages\n");
136 GOTO(brw_cleanup, rc = -ENOMEM);
138 pgp->count = PAGE_SIZE;
143 void *addr = kmap(pgp->pg);
145 if (rw == OBD_BRW_WRITE)
146 page_debug_setup(addr, pgp->count,
149 page_debug_setup(addr, pgp->count,
156 set->brw_callback = ll_brw_sync_wait;
157 rc = obd_brw(rw, &ec->conn, lsm, j, pga, set);
159 CERROR("test_brw: error from obd_brw: rc = %d\n", rc);
161 rc = ll_brw_sync_wait(set, CB_PHASE_START);
163 CERROR("test_brw: error from callback: rc = "
168 for (j = 0, pgp = pga; j < pages; j++, pgp++) {
173 void *addr = kmap(pgp->pg);
175 rc = page_debug_check("test_brw", addr,
176 pgp->count, pgp->off, id);
179 __free_pages(pgp->pg, 0);
182 obd_brw_set_free(set);
183 OBD_FREE(pga, pages * sizeof(*pga));
187 CERROR ("echo_ioctl(): unrecognised ioctl %#x\n", cmd);
188 GOTO (out, rc = -ENOTTY);
195 static int echo_setup(struct obd_device *obddev, obd_count len, void *buf)
197 struct obd_ioctl_data* data = buf;
198 struct echo_client_obd *ec = &obddev->u.echo_client;
199 struct obd_device *tgt;
203 if (data->ioc_inllen1 < 1) {
204 CERROR("requires a TARGET OBD UUID\n");
207 if (data->ioc_inllen1 > 37) {
208 CERROR("OBD UUID must be less than 38 characters\n");
212 tgt = class_uuid2obd(data->ioc_inlbuf1);
213 if (!tgt || !(tgt->obd_flags & OBD_ATTACHED) ||
214 !(tgt->obd_flags & OBD_SET_UP)) {
215 CERROR("device not attached or not set up (%d)\n",
217 RETURN(rc = -EINVAL);
220 rc = obd_connect(&ec->conn, tgt, NULL, NULL, NULL);
222 CERROR("fail to connect to device %d\n", data->ioc_dev);
226 static int echo_cleanup(struct obd_device * obddev)
228 struct echo_client_obd *ec = &obddev->u.echo_client;
232 if (!list_empty(&obddev->obd_exports)) {
233 CERROR("still has clients!\n");
237 rc = obd_disconnect(&ec->conn);
239 CERROR("fail to disconnect device: %d\n", rc);
246 static int echo_connect(struct lustre_handle *conn, struct obd_device *src,
247 obd_uuid_t cluuid, struct recovd_obd *recovd,
248 ptlrpc_recovery_cb_t recover)
250 return class_connect(conn, src, cluuid);
253 static struct obd_ops echo_obd_ops = {
254 o_owner: THIS_MODULE,
256 o_cleanup: echo_cleanup,
257 o_iocontrol: echo_iocontrol,
258 o_connect: echo_connect,
259 o_disconnect: class_disconnect
262 int echo_client_init(void)
264 extern struct lprocfs_vars status_class_var[];
266 return class_register_type(&echo_obd_ops, status_class_var,
267 OBD_ECHO_CLIENT_DEVICENAME);
270 void echo_client_cleanup(void)
272 class_unregister_type(OBD_ECHO_CLIENT_DEVICENAME);