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);
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));
185 CERROR ("echo_ioctl(): unrecognised ioctl %#lx\n", cmd);
186 GOTO (out, rc = -ENOTTY);
193 static int echo_setup(struct obd_device *obddev, obd_count len, void *buf)
195 struct obd_ioctl_data* data = buf;
196 struct echo_client_obd *ec = &obddev->u.echo_client;
197 struct obd_device *tgt;
201 if (data->ioc_inllen1 < 1) {
202 CERROR("requires a TARGET OBD UUID\n");
205 if (data->ioc_inllen1 > 37) {
206 CERROR("OBD UUID must be less than 38 characters\n");
211 tgt = class_uuid2obd(data->ioc_inlbuf1);
212 if (!tgt || !(tgt->obd_flags & OBD_ATTACHED) ||
213 !(tgt->obd_flags & OBD_SET_UP)) {
214 CERROR("device not attached or not set up (%d)\n",
216 GOTO(error_dec, rc = -EINVAL);
219 rc = obd_connect(&ec->conn, tgt, NULL, NULL, NULL);
221 CERROR("fail to connect to device %d\n", data->ioc_dev);
222 GOTO(error_dec, rc = -EINVAL);
230 static int echo_cleanup(struct obd_device * obddev)
232 struct echo_client_obd *ec = &obddev->u.echo_client;
236 if (!list_empty(&obddev->obd_exports)) {
237 CERROR("still has clients!\n");
241 rc = obd_disconnect(&ec->conn);
243 CERROR("fail to disconnect device: %d\n", rc);
251 static int echo_connect(struct lustre_handle *conn, struct obd_device *src,
252 obd_uuid_t cluuid, struct recovd_obd *recovd,
253 ptlrpc_recovery_cb_t recover)
255 return class_connect(conn, src, cluuid);
258 static struct obd_ops echo_obd_ops = {
260 o_cleanup: echo_cleanup,
261 o_iocontrol: echo_iocontrol,
262 o_connect: echo_connect,
263 o_disconnect: class_disconnect
266 int echo_client_init(void)
268 extern struct lprocfs_vars status_class_var[];
270 return class_register_type(&echo_obd_ops, status_class_var,
271 OBD_ECHO_CLIENT_DEVICENAME);
274 void echo_client_cleanup(void)
276 class_unregister_type(OBD_ECHO_CLIENT_DEVICENAME);