1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * Copyright (C) 2002 Cluster File Systems, Inc.
7 * Author: Phil Schwan <phil@off.net>
9 * This code is issued under the GNU General Public License.
10 * See the file COPYING in this distribution
14 #define DEBUG_SUBSYSTEM S_LOV
16 #include <linux/module.h>
17 #include <linux/obd_class.h>
19 extern struct obd_device obd_dev[MAX_OBD_DEVICES];
22 static int lov_connect(struct obd_conn *conn)
27 rc = gen_connect(conn);
35 static int lov_disconnect(struct obd_conn *conn)
39 rc = gen_disconnect(conn);
43 /* XXX cleanup preallocated inodes */
47 static int lov_getattr(struct obd_conn *conn, struct obdo *oa)
52 if (!gen_client(conn))
55 rc = obd_getattr(&conn->oc_dev->obd_multi_conn[0], oa);
59 static int lov_setattr(struct obd_conn *conn, struct obdo *oa)
64 if (!gen_client(conn))
67 for (i = 0; i < conn->oc_dev->obd_multi_count; i++) {
68 rc = obd_setattr(&conn->oc_dev->obd_multi_conn[i], oa);
71 else if (retval != rc)
72 CERROR("different results on multiple OBDs!\n");
78 static int lov_open(struct obd_conn *conn, struct obdo *oa)
83 if (!gen_client(conn))
86 for (i = 0; i < conn->oc_dev->obd_multi_count; i++) {
87 rc = obd_open(&conn->oc_dev->obd_multi_conn[i], oa);
90 else if (retval != rc)
91 CERROR("different results on multiple OBDs!\n");
97 static int lov_close(struct obd_conn *conn, struct obdo *oa)
102 if (!gen_client(conn))
105 for (i = 0; i < conn->oc_dev->obd_multi_count; i++) {
106 rc = obd_close(&conn->oc_dev->obd_multi_conn[i], oa);
109 else if (retval != rc)
110 CERROR("different results on multiple OBDs!\n");
116 static int lov_create(struct obd_conn *conn, struct obdo *oa)
121 if (!gen_client(conn))
124 for (i = 0; i < conn->oc_dev->obd_multi_count; i++)
125 rc = obd_create(&conn->oc_dev->obd_multi_conn[i], oa);
130 static int filter_destroy(struct obd_conn *conn, struct obdo *oa)
133 struct obd_device * obddev;
134 struct obd_client * cli;
135 struct inode * inode;
139 struct obd_run_ctxt saved;
141 if (!(cli = gen_client(conn))) {
142 CERROR("invalid client %u\n", conn->oc_id);
147 obddev = conn->oc_dev;
148 object = filter_obj_open(obddev, oa->o_id, oa->o_mode);
149 if (!object || IS_ERR(object)) {
154 inode = object->f_dentry->d_inode;
156 inode->i_mode = 010000;
158 push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
159 dir = filter_parent(oa->o_id, oa->o_mode);
166 dget(object->f_dentry);
167 rc = vfs_unlink(dir->f_dentry->d_inode, object->f_dentry);
170 filp_close(object, 0);
179 /* FIXME: maybe we'll just make one node the authoritative attribute node, then
180 * we can send this 'punch' to just the authoritative node and the nodes
181 * that the punch will affect. */
182 static int lov_punch(struct obd_conn *conn, struct obdo *oa,
183 obd_size count, obd_off offset)
188 if (!gen_client(conn))
191 for (i = 0; i < conn->oc_dev->obd_multi_count; i++) {
192 rc = obd_punch(&conn->oc_dev->obd_multi_conn[i], oa, count,
196 else if (retval != rc)
197 CERROR("different results on multiple OBDs!\n");
203 /* buffer must lie in user memory here */
204 static int lov_read(struct obd_conn *conn, struct obdo *oa, char *buf,
205 obd_size *count, obd_off offset)
208 obd_off off = offset;
212 if (!gen_client(conn))
215 while (off < offset + count) {
219 stripe = off / conn->oc_dev->u.lov.lov_stripe_size;
220 size = (stripe + 1) * conn->oc_dev->u.lov.lov_strip_size - off;
225 conn = stripe % conn->oc_dev->obd_multi_count;
228 rc = obd_read(&conn->oc_dev->obd_multi_conn[conn], oa, buf,
233 CERROR("read(off=%Lu, count=%Lu): %d\n",
234 (unsigned long long)off,
235 (unsigned long long)size, rc);
247 /* buffer must lie in user memory here */
248 static int filter_write(struct obd_conn *conn, struct obdo *oa, char *buf,
249 obd_size *count, obd_off offset)
253 unsigned long retval;
256 if (!gen_client(conn)) {
257 CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
262 file = filter_obj_open(conn->oc_dev, oa->o_id, oa->o_mode);
263 if (!file || IS_ERR(file)) {
265 return -PTR_ERR(file);
268 /* count doubles as retval */
269 retval = file->f_op->write(file, buf, *count, (loff_t *)&offset);
285 static int lov_enqueue(struct obd_conn *conn, struct ldlm_namespace *ns,
286 struct ldlm_handle *parent_lock, __u64 *res_id,
287 __u32 type, struct ldlm_extent *extent, __u32 mode,
288 int *flags, void *data, int datalen,
289 struct ldlm_handle *lockh)
294 if (!gen_client(conn))
297 rc = obd_enqueue(&conn->oc_dev->obd_multi_conn[0], ns, parent_lock,
298 res_id, type, extent, mode, flags, data, datalen,
303 static int lov_cancel(struct obd_conn *conn, __u32 mode,
304 struct ldlm_handle *lockh)
309 if (!gen_client(conn))
312 rc = obd_cancel(&conn->oc_dev->obd_multi_conn[0], oa);
316 struct obd_ops lov_obd_ops = {
317 o_setup: gen_multi_setup,
318 o_cleanup: gen_multi_cleanup,
319 o_create: lov_create,
320 o_destroy: lov_destroy,
321 o_getattr: lov_getattr,
322 o_setattr: lov_setattr,
325 o_connect: lov_connect,
326 o_disconnect: lov_disconnect,
327 o_brw: lov_pgcache_brw,
329 o_enqueue: lov_enqueue,
334 #define LOV_VERSION "v0.1"
336 static int __init lov_init(void)
338 printk(KERN_INFO "Lustre Logical Object Volume driver " LOV_VERSION
339 ", phil@clusterfs.com\n");
340 return obd_register_type(&lov_obd_ops, OBD_LOV_DEVICENAME);
343 static void __exit lov_exit(void)
345 obd_unregister_type(OBD_LOV_DEVICENAME);
348 MODULE_AUTHOR("Phil Schwan <phil@clusterfs.com>");
349 MODULE_DESCRIPTION("Lustre Logical Object Volume OBD driver v0.1");
350 MODULE_LICENSE("GPL");
352 module_init(lov_init);
353 module_exit(lov_exit);