Whamcloud - gitweb
Last week's LOV hackery
[fs/lustre-release.git] / lustre / lov / lov_obd.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lov/lov.c
5  *
6  * Copyright (C) 2002 Cluster File Systems, Inc.
7  * Author: Phil Schwan <phil@off.net>
8  *
9  * This code is issued under the GNU General Public License.
10  * See the file COPYING in this distribution
11  */
12
13 #define EXPORT_SYMTAB
14 #define DEBUG_SUBSYSTEM S_LOV
15
16 #include <linux/module.h>
17 #include <linux/obd_class.h>
18
19 extern struct obd_device obd_dev[MAX_OBD_DEVICES];
20
21 /* obd methods */
22 static int lov_connect(struct obd_conn *conn)
23 {
24         int rc;
25
26         MOD_INC_USE_COUNT;
27         rc = gen_connect(conn);
28
29         if (rc)
30                 MOD_DEC_USE_COUNT;
31
32         return rc;
33 }
34
35 static int lov_disconnect(struct obd_conn *conn)
36 {
37         int rc;
38
39         rc = gen_disconnect(conn);
40         if (!rc)
41                 MOD_DEC_USE_COUNT;
42
43         /* XXX cleanup preallocated inodes */
44         return rc;
45 }
46
47 static int lov_getattr(struct obd_conn *conn, struct obdo *oa)
48 {
49         int rc;
50         ENTRY;
51
52         if (!gen_client(conn))
53                 RETURN(-EINVAL);
54
55         rc = obd_getattr(&conn->oc_dev->obd_multi_conn[0], oa);
56         RETURN(rc);
57 }
58
59 static int lov_setattr(struct obd_conn *conn, struct obdo *oa)
60 {
61         int rc, retval, i;
62         ENTRY;
63
64         if (!gen_client(conn))
65                 RETURN(-EINVAL);
66
67         for (i = 0; i < conn->oc_dev->obd_multi_count; i++) {
68                 rc = obd_setattr(&conn->oc_dev->obd_multi_conn[i], oa);
69                 if (i == 0)
70                         retval = rc;
71                 else if (retval != rc)
72                         CERROR("different results on multiple OBDs!\n");
73         }
74
75         RETURN(rc);
76 }
77
78 static int lov_open(struct obd_conn *conn, struct obdo *oa)
79 {
80         int rc, retval, i;
81         ENTRY;
82
83         if (!gen_client(conn))
84                 RETURN(-EINVAL);
85
86         for (i = 0; i < conn->oc_dev->obd_multi_count; i++) {
87                 rc = obd_open(&conn->oc_dev->obd_multi_conn[i], oa);
88                 if (i == 0)
89                         retval = rc;
90                 else if (retval != rc)
91                         CERROR("different results on multiple OBDs!\n");
92         }
93
94         RETURN(rc);
95 }
96
97 static int lov_close(struct obd_conn *conn, struct obdo *oa)
98 {
99         int rc, retval, i;
100         ENTRY;
101
102         if (!gen_client(conn))
103                 RETURN(-EINVAL);
104
105         for (i = 0; i < conn->oc_dev->obd_multi_count; i++) {
106                 rc = obd_close(&conn->oc_dev->obd_multi_conn[i], oa);
107                 if (i == 0)
108                         retval = rc;
109                 else if (retval != rc)
110                         CERROR("different results on multiple OBDs!\n");
111         }
112
113         RETURN(rc);
114 }
115
116 static int lov_create(struct obd_conn *conn, struct obdo *oa)
117 {
118         int rc, i;
119         ENTRY;
120
121         if (!gen_client(conn))
122                 RETURN(-EINVAL);
123
124         for (i = 0; i < conn->oc_dev->obd_multi_count; i++)
125                 rc = obd_create(&conn->oc_dev->obd_multi_conn[i], oa);
126
127         return rc;
128 }
129
130 static int filter_destroy(struct obd_conn *conn, struct obdo *oa)
131 {
132 #if 0
133         struct obd_device * obddev;
134         struct obd_client * cli;
135         struct inode * inode;
136         struct file *dir;
137         struct file *object;
138         int rc;
139         struct obd_run_ctxt saved;
140
141         if (!(cli = gen_client(conn))) {
142                 CERROR("invalid client %u\n", conn->oc_id);
143                 EXIT;
144                 return -EINVAL;
145         }
146
147         obddev = conn->oc_dev;
148         object = filter_obj_open(obddev, oa->o_id, oa->o_mode);
149         if (!object || IS_ERR(object)) {
150                 EXIT;
151                 return -ENOENT;
152         }
153
154         inode = object->f_dentry->d_inode;
155         inode->i_nlink = 1;
156         inode->i_mode = 010000;
157
158         push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
159         dir = filter_parent(oa->o_id, oa->o_mode);
160         if (IS_ERR(dir)) {
161                 rc = PTR_ERR(dir);
162                 EXIT;
163                 goto out;
164         }
165         dget(dir->f_dentry);
166         dget(object->f_dentry);
167         rc = vfs_unlink(dir->f_dentry->d_inode, object->f_dentry);
168
169         filp_close(dir, 0);
170         filp_close(object, 0);
171 out:
172         pop_ctxt(&saved);
173         EXIT;
174         return rc;
175 #endif
176         return 0;
177 }
178
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)
184 {
185         int rc, retval, i;
186         ENTRY;
187
188         if (!gen_client(conn))
189                 RETURN(-EINVAL);
190
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,
193                                offset);
194                 if (i == 0)
195                         retval = rc;
196                 else if (retval != rc)
197                         CERROR("different results on multiple OBDs!\n");
198         }
199
200         RETURN(rc);
201 }
202
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)
206 {
207         int rc, i;
208         obd_off off = offset;
209         obd_size retval = 0;
210         ENTRY;
211
212         if (!gen_client(conn))
213                 RETURN(-EINVAL);
214
215         while (off < offset + count) {
216                 int stripe, conn;
217                 obd_size size, tmp;
218
219                 stripe = off / conn->oc_dev->u.lov.lov_stripe_size;
220                 size = (stripe + 1) * conn->oc_dev->u.lov.lov_strip_size - off;
221                 if (size > *count)
222                         size = *count;
223
224
225                 conn = stripe % conn->oc_dev->obd_multi_count;
226
227                 tmp = size;
228                 rc = obd_read(&conn->oc_dev->obd_multi_conn[conn], oa, buf,
229                               &size, off);
230                 if (rc == 0)
231                         retval += size;
232                 else {
233                         CERROR("read(off=%Lu, count=%Lu): %d\n",
234                                (unsigned long long)off,
235                                (unsigned long long)size, rc);
236                         break;
237                 }
238
239                 buf += size;
240         }
241
242         *count = retval;
243         RETURN(rc);
244 }
245
246
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)
250 {
251         int err;
252         struct file * file;
253         unsigned long retval;
254
255         ENTRY;
256         if (!gen_client(conn)) {
257                 CDEBUG(D_IOCTL, "invalid client %u\n", conn->oc_id);
258                 EXIT;
259                 return -EINVAL;
260         }
261
262         file = filter_obj_open(conn->oc_dev, oa->o_id, oa->o_mode);
263         if (!file || IS_ERR(file)) {
264                 EXIT;
265                 return -PTR_ERR(file);
266         }
267
268         /* count doubles as retval */
269         retval = file->f_op->write(file, buf, *count, (loff_t *)&offset);
270         filp_close(file, 0);
271
272         if ( retval >= 0 ) {
273                 err = 0;
274                 *count = retval;
275                 EXIT;
276         } else {
277                 err = retval;
278                 *count = 0;
279                 EXIT;
280         }
281
282         return err;
283 }
284
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)
290 {
291         int rc;
292         ENTRY;
293
294         if (!gen_client(conn))
295                 RETURN(-EINVAL);
296
297         rc = obd_enqueue(&conn->oc_dev->obd_multi_conn[0], ns, parent_lock,
298                          res_id, type, extent, mode, flags, data, datalen,
299                          lockh);
300         RETURN(rc);
301 }
302
303 static int lov_cancel(struct obd_conn *conn, __u32 mode,
304                       struct ldlm_handle *lockh)
305 {
306         int rc;
307         ENTRY;
308
309         if (!gen_client(conn))
310                 RETURN(-EINVAL);
311
312         rc = obd_cancel(&conn->oc_dev->obd_multi_conn[0], oa);
313         RETURN(rc);
314 }
315
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,
323         o_open:        lov_open,
324         o_close:       lov_close,
325         o_connect:     lov_connect,
326         o_disconnect:  lov_disconnect,
327         o_brw:         lov_pgcache_brw,
328         o_punch:       lov_punch,
329         o_enqueue:     lov_enqueue,
330         o_cancel:      lov_cancel
331 };
332
333
334 #define LOV_VERSION "v0.1"
335
336 static int __init lov_init(void)
337 {
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);
341 }
342
343 static void __exit lov_exit(void)
344 {
345         obd_unregister_type(OBD_LOV_DEVICENAME);
346 }
347
348 MODULE_AUTHOR("Phil Schwan <phil@clusterfs.com>");
349 MODULE_DESCRIPTION("Lustre Logical Object Volume OBD driver v0.1");
350 MODULE_LICENSE("GPL");
351
352 module_init(lov_init);
353 module_exit(lov_exit);