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;
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);
61 memcpy(lsm, tmp_lsm, sizeof(*tmp_lsm));
67 rc = obd_getattr(&ec->conn, &data->ioc_obdo1, lsm);
71 rc = obd_setattr(&ec->conn, &data->ioc_obdo1, lsm);
75 rc = obd_destroy(&ec->conn, &data->ioc_obdo1, lsm);
79 rc = obd_open(&ec->conn, &data->ioc_obdo1, lsm);
83 rc = obd_close(&ec->conn, &data->ioc_obdo1, lsm);
86 case OBD_IOC_BRW_WRITE:
88 case OBD_IOC_BRW_READ: {
89 struct lov_stripe_md tmp_lsm;
90 struct obd_brw_set *set;
92 struct brw_page *pga, *pgp;
93 __u64 off, id = data->ioc_obdo1.o_id;
94 int gfp_mask = (id & 1) ? GFP_HIGHUSER : GFP_KERNEL;
95 int j, verify = (id != 0);
97 if (lsm && lsm->lsm_object_id != id) {
98 CERROR("LSM object ID ("LPU64") != id ("LPU64")\n",
99 lsm->lsm_object_id, id);
100 GOTO(out, rc = -EINVAL);
104 memset(&tmp_lsm, 0, sizeof(tmp_lsm));
106 lsm->lsm_object_id = id;
109 if (data->ioc_count < 0) {
110 CERROR("invalid buffer size: "LPD64"\n",
112 GOTO(out, rc = -EINVAL);
115 set = obd_brw_set_new();
117 GOTO(out, rc = -ENOMEM);
119 pages = data->ioc_count / PAGE_SIZE;
120 off = data->ioc_offset;
122 CDEBUG(D_INODE, "BRW %s with %d pages @ "LPX64"\n",
123 rw == OBD_BRW_READ ? "read" : "write", pages, off);
124 OBD_ALLOC(pga, pages * sizeof(*pga));
126 CERROR("no memory for %d BRW per-page data\n", pages);
127 GOTO(brw_free, rc = -ENOMEM);
130 for (j = 0, pgp = pga; j < pages; j++, off += PAGE_SIZE, pgp++){
131 pgp->pg = alloc_pages(gfp_mask, 0);
133 CERROR("no memory for brw pages\n");
134 GOTO(brw_cleanup, rc = -ENOMEM);
136 pgp->count = PAGE_SIZE;
141 void *addr = kmap(pgp->pg);
143 if (rw == OBD_BRW_WRITE)
144 page_debug_setup(addr, pgp->count,
147 page_debug_setup(addr, pgp->count,
154 set->brw_callback = ll_brw_sync_wait;
155 rc = obd_brw(rw, &ec->conn, lsm, j, pga, set);
157 CERROR("test_brw: error from obd_brw: rc = %d\n", rc);
159 rc = ll_brw_sync_wait(set, CB_PHASE_START);
161 CERROR("test_brw: error from callback: rc = "
166 for (j = 0, pgp = pga; j < pages; j++, pgp++) {
171 void *addr = kmap(pgp->pg);
173 rc = page_debug_check("test_brw", addr,
174 PAGE_SIZE, pgp->off, id);
177 __free_pages(pgp->pg, 0);
180 obd_brw_set_free(set);
181 OBD_FREE(pga, pages * sizeof(*pga));
192 static int echo_setup(struct obd_device *obddev, obd_count len, void *buf)
194 struct obd_ioctl_data* data = buf;
195 struct echo_client_obd *ec = &obddev->u.echo_client;
196 struct obd_device *tgt;
200 if (data->ioc_inllen1 < 1) {
201 CERROR("requires a TARGET OBD UUID\n");
204 if (data->ioc_inllen1 > 37) {
205 CERROR("OBD UUID must be less than 38 characters\n");
210 tgt = class_uuid2obd(data->ioc_inlbuf1);
211 if (!tgt || !(tgt->obd_flags & OBD_ATTACHED) ||
212 !(tgt->obd_flags & OBD_SET_UP)) {
213 CERROR("device not attached or not set up (%d)\n",
215 GOTO(error_dec, rc = -EINVAL);
218 rc = obd_connect(&ec->conn, tgt, NULL, NULL, NULL);
220 CERROR("fail to connect to device %d\n", data->ioc_dev);
221 GOTO(error_dec, rc = -EINVAL);
229 static int echo_cleanup(struct obd_device * obddev)
231 struct echo_client_obd *ec = &obddev->u.echo_client;
235 if (!list_empty(&obddev->obd_exports)) {
236 CERROR("still has clients!\n");
240 rc = obd_disconnect(&ec->conn);
242 CERROR("fail to disconnect device: %d\n", rc);
250 static int echo_connect(struct lustre_handle *conn, struct obd_device *src,
251 obd_uuid_t cluuid, struct recovd_obd *recovd,
252 ptlrpc_recovery_cb_t recover)
254 return class_connect(conn, src, cluuid);
257 static struct obd_ops echo_obd_ops = {
259 o_cleanup: echo_cleanup,
260 o_iocontrol: echo_iocontrol,
261 o_connect: echo_connect,
262 o_disconnect: class_disconnect
265 int echo_client_init(void)
267 extern struct lprocfs_vars status_class_var[];
269 return class_register_type(&echo_obd_ops, status_class_var,
270 OBD_ECHO_CLIENT_DEVICENAME);
273 void echo_client_cleanup(void)
275 class_unregister_type(OBD_ECHO_CLIENT_DEVICENAME);