Whamcloud - gitweb
Send last_rcvd values around when talking to the MDS. The MDC gets the
[fs/lustre-release.git] / lustre / mdc / mdc_request.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.sf.net/projects/lustre/
7  *
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.
11  *
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.
16  *
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.
20  *
21  */
22
23 #define EXPORT_SYMTAB
24
25 #include <linux/module.h>
26 #include <linux/miscdevice.h>
27
28 #define DEBUG_SUBSYSTEM S_MDC
29
30 #include <linux/lustre_mds.h>
31 #include <linux/lustre_lite.h>
32
33 #define REQUEST_MINOR 244
34
35 extern int mds_queue_req(struct ptlrpc_request *);
36
37 int mdc_connect(struct ptlrpc_client *cl, struct ptlrpc_connection *conn,
38                 struct ll_fid *rootfid, __u64 *last_committed, __u64 *last_rcvd,
39                 __u32 *last_xid, struct ptlrpc_request **request)
40 {
41         struct ptlrpc_request *req;
42         struct mds_body *body;
43         int rc, size = sizeof(*body);
44         ENTRY;
45
46         req = ptlrpc_prep_req(cl, conn, MDS_CONNECT, 1, &size, NULL);
47         if (!req)
48                 GOTO(out, rc = -ENOMEM);
49
50         body = lustre_msg_buf(req->rq_reqmsg, 0);
51         req->rq_replen = lustre_msg_size(1, &size);
52
53         mds_pack_req_body(req);
54         rc = ptlrpc_queue_wait(req);
55         rc = ptlrpc_check_status(req, rc);
56
57         if (!rc) {
58                 mds_unpack_rep_body(req);
59                 body = lustre_msg_buf(req->rq_repmsg, 0);
60                 memcpy(rootfid, &body->fid1, sizeof(*rootfid));
61                 *last_committed = body->last_committed;
62                 *last_rcvd = body->last_rcvd;
63                 *last_xid = body->last_xid;
64
65                 CDEBUG(D_NET, "root ino=%ld, last_committed=%ld, last_rcvd=%ld,"
66                        " last_xid=%d\n",
67                        (unsigned long)rootfid->id,
68                        (unsigned long)body->last_committed,
69                        (unsigned long)body->last_rcvd,
70                        body->last_xid);
71         }
72
73         EXIT;
74  out:
75         ptlrpc_free_req(req); 
76         return rc;
77 }
78
79
80 int mdc_getattr(struct ptlrpc_client *cl, struct ptlrpc_connection *conn,
81                 ino_t ino, int type, unsigned long valid,
82                 struct ptlrpc_request **request)
83 {
84         struct ptlrpc_request *req;
85         struct mds_body *body;
86         int rc, size = sizeof(*body);
87         ENTRY;
88
89         req = ptlrpc_prep_req(cl, conn, MDS_GETATTR, 1, &size, NULL);
90         if (!req)
91                 GOTO(out, rc = -ENOMEM);
92
93         body = lustre_msg_buf(req->rq_reqmsg, 0);
94         ll_ino2fid(&body->fid1, ino, 0, type);
95         body->valid = valid;
96
97         req->rq_replen = lustre_msg_size(1, &size);
98
99         rc = ptlrpc_queue_wait(req);
100         rc = ptlrpc_check_status(req, rc);
101
102         if (!rc) {
103                 mds_unpack_rep_body(req);
104                 body = lustre_msg_buf(req->rq_repmsg, 0);
105                 CDEBUG(D_NET, "mode: %o\n", body->mode);
106         }
107
108         EXIT;
109  out:
110         *request = req;
111         return rc;
112 }
113
114 int mdc_open(struct ptlrpc_client *cl, struct ptlrpc_connection *conn,
115              ino_t ino, int type, int flags, __u64 *fh,
116              struct ptlrpc_request **request)
117 {
118         struct mds_body *body;
119         int rc, size = sizeof(*body);
120         struct ptlrpc_request *req;
121
122         req = ptlrpc_prep_req(cl, conn, MDS_OPEN, 1, &size, NULL);
123         if (!req)
124                 GOTO(out, rc = -ENOMEM);
125
126         body = lustre_msg_buf(req->rq_reqmsg, 0);
127         ll_ino2fid(&body->fid1, ino, 0, type);
128         body->flags = HTON__u32(flags);
129
130         req->rq_replen = lustre_msg_size(1, &size);
131
132         rc = ptlrpc_queue_wait(req);
133         rc = ptlrpc_check_status(req, rc);
134
135         if (!rc) {
136                 mds_unpack_rep_body(req);
137                 body = lustre_msg_buf(req->rq_repmsg, 0);
138                 *fh = body->objid;
139         }
140
141         EXIT;
142  out:
143         *request = req;
144         return rc;
145 }
146
147 int mdc_close(struct ptlrpc_client *cl, struct ptlrpc_connection *conn,
148               ino_t ino, int type, __u64 fh, struct ptlrpc_request **request)
149 {
150         struct mds_body *body;
151         int rc, size = sizeof(*body);
152         struct ptlrpc_request *req;
153
154         req = ptlrpc_prep_req(cl, conn, MDS_CLOSE, 1, &size, NULL);
155         if (!req)
156                 GOTO(out, rc = -ENOMEM);
157
158         body = lustre_msg_buf(req->rq_reqmsg, 0);
159         ll_ino2fid(&body->fid1, ino, 0, type);
160         body->objid = fh;
161
162         req->rq_replen = lustre_msg_size(1, &size);
163
164         rc = ptlrpc_queue_wait(req);
165         rc = ptlrpc_check_status(req, rc);
166
167         EXIT;
168  out:
169         *request = req;
170         return rc;
171 }
172
173 int mdc_readpage(struct ptlrpc_client *cl, struct ptlrpc_connection *conn,
174                  ino_t ino, int type, __u64 offset, char *addr,
175                  struct ptlrpc_request **request)
176 {
177         struct ptlrpc_request *req = NULL;
178         struct ptlrpc_bulk_desc *bulk = NULL;
179         struct niobuf niobuf;
180         struct mds_body *body;
181         int rc, size[2] = {sizeof(*body), sizeof(struct niobuf)};
182         char *bufs[2] = {NULL, (char *)&niobuf};
183
184         niobuf.addr = (__u64) (long) addr;
185
186         CDEBUG(D_INODE, "inode: %ld\n", (long)ino);
187
188         bulk = ptlrpc_prep_bulk(conn);
189         if (bulk == NULL) {
190                 CERROR("%s: cannot init bulk desc\n", __FUNCTION__);
191                 rc = -ENOMEM;
192                 goto out;
193         }
194
195         req = ptlrpc_prep_req(cl, conn, MDS_READPAGE, 2, size, bufs);
196         if (!req)
197                 GOTO(out, rc = -ENOMEM);
198
199         bulk->b_buflen = PAGE_SIZE;
200         bulk->b_buf = (void *)(long)niobuf.addr;
201         bulk->b_portal = MDS_BULK_PORTAL;
202         bulk->b_xid = req->rq_reqmsg->xid;
203
204         rc = ptlrpc_register_bulk(bulk);
205         if (rc) {
206                 CERROR("couldn't setup bulk sink: error %d.\n", rc);
207                 GOTO(out, rc);
208         }
209
210         body = lustre_msg_buf(req->rq_reqmsg, 0);
211         body->fid1.id = ino;
212         body->fid1.f_type = type;
213         body->size = offset;
214
215         req->rq_replen = lustre_msg_size(1, size);
216
217         rc = ptlrpc_queue_wait(req);
218         if (rc) {
219                 CERROR("error in handling %d\n", rc);
220                 ptlrpc_abort_bulk(bulk);
221                 GOTO(out, rc);
222         }
223
224         mds_unpack_rep_body(req);
225         EXIT;
226
227  out:
228         *request = req;
229         ptlrpc_free_bulk(bulk);
230         return rc;
231 }
232
233 static int request_ioctl(struct inode *inode, struct file *file,
234                          unsigned int cmd, unsigned long arg)
235 {
236         int err = 0;
237         struct ptlrpc_client cl;
238         struct ptlrpc_connection *conn;
239         struct ptlrpc_request *request;
240
241         ENTRY;
242
243         if (MINOR(inode->i_rdev) != REQUEST_MINOR)
244                 RETURN(-EINVAL);
245
246         if (_IOC_TYPE(cmd) != IOC_REQUEST_TYPE ||
247             _IOC_NR(cmd) < IOC_REQUEST_MIN_NR  ||
248             _IOC_NR(cmd) > IOC_REQUEST_MAX_NR ) {
249                 CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
250                        _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
251                 RETURN(-EINVAL);
252         }
253
254         ptlrpc_init_client(NULL, MDS_REQUEST_PORTAL, MDC_REPLY_PORTAL, &cl);
255         conn = ptlrpc_uuid_to_connection("mds");
256         if (!conn) {
257                 CERROR("cannot create client\n");
258                 RETURN(-EINVAL);
259         }
260
261         switch (cmd) {
262         case IOC_REQUEST_GETATTR: {
263                 CERROR("-- getting attr for ino %lu\n", arg);
264                 err = mdc_getattr(&cl, conn, arg, S_IFDIR, ~0, &request);
265                 CERROR("-- done err %d\n", err);
266
267                 GOTO(out, err);
268         }
269
270         case IOC_REQUEST_READPAGE: {
271                 char *buf;
272                 OBD_ALLOC(buf, PAGE_SIZE);
273                 if (!buf) {
274                         err = -ENOMEM;
275                         GOTO(out, err);
276                 }
277                 CERROR("-- readpage 0 for ino %lu\n", arg);
278                 err = mdc_readpage(&cl, conn, arg, S_IFDIR, 0, buf, &request);
279                 CERROR("-- done err %d\n", err);
280                 OBD_FREE(buf, PAGE_SIZE);
281
282                 GOTO(out, err);
283         }
284
285         case IOC_REQUEST_SETATTR: {
286                 struct inode inode;
287                 struct iattr iattr;
288
289                 inode.i_ino = arg;
290                 inode.i_generation = 0;
291                 iattr.ia_mode = 040777;
292                 iattr.ia_atime = 0;
293                 iattr.ia_valid = ATTR_MODE | ATTR_ATIME;
294
295                 err = mdc_setattr(&cl, conn, &inode, &iattr, &request);
296                 CERROR("-- done err %d\n", err);
297
298                 GOTO(out, err);
299         }
300
301         case IOC_REQUEST_CREATE: {
302                 struct inode inode;
303                 struct iattr iattr;
304
305                 inode.i_ino = arg;
306                 inode.i_generation = 0;
307                 iattr.ia_mode = 040777;
308                 iattr.ia_atime = 0;
309                 iattr.ia_valid = ATTR_MODE | ATTR_ATIME;
310
311                 err = mdc_create(&cl, conn, &inode,
312                                  "foofile", strlen("foofile"),
313                                  NULL, 0, 0100707, 47114711,
314                                  11, 47, 0, &request);
315                 CERROR("-- done err %d\n", err);
316
317                 GOTO(out, err);
318         }
319
320         case IOC_REQUEST_OPEN: {
321                 __u64 fh, ino;
322                 copy_from_user(&ino, (__u64 *)arg, sizeof(ino));
323                 CERROR("-- opening ino %llu\n", (unsigned long long)ino);
324                 err = mdc_open(&cl, conn, ino, S_IFDIR, O_RDONLY, &fh,
325                                &request);
326                 copy_to_user((__u64 *)arg, &fh, sizeof(fh));
327                 CERROR("-- done err %d (fh=%Lu)\n", err,
328                        (unsigned long long)fh);
329
330                 GOTO(out, err);
331         }
332
333         case IOC_REQUEST_CLOSE: {
334                 CERROR("-- closing ino 2, filehandle %lu\n", arg);
335                 err = mdc_close(&cl, conn, 2, S_IFDIR, arg, &request);
336                 CERROR("-- done err %d\n", err);
337
338                 GOTO(out, err);
339         }
340
341         default:
342                 GOTO(out, err = -EINVAL);
343         }
344
345  out:
346         ptlrpc_free_req(request);
347         ptlrpc_put_connection(conn);
348
349         RETURN(err);
350 }
351
352
353 static struct file_operations requestdev_fops = {
354         ioctl: request_ioctl,
355 };
356
357 static struct miscdevice request_dev = {
358         REQUEST_MINOR,
359         "request",
360         &requestdev_fops
361 };
362
363 static int __init ptlrpc_request_init(void)
364 {
365         misc_register(&request_dev);
366         return 0;
367 }
368
369 static void __exit ptlrpc_request_exit(void)
370 {
371         misc_deregister(&request_dev);
372 }
373
374 MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
375 MODULE_DESCRIPTION("Lustre MDS Request Tester v1.0");
376 MODULE_LICENSE("GPL");
377
378 EXPORT_SYMBOL(mdc_connect);
379 EXPORT_SYMBOL(mdc_getattr);
380 EXPORT_SYMBOL(mdc_create);
381 EXPORT_SYMBOL(mdc_unlink);
382 EXPORT_SYMBOL(mdc_rename);
383 EXPORT_SYMBOL(mdc_link);
384 EXPORT_SYMBOL(mdc_readpage);
385 EXPORT_SYMBOL(mdc_setattr);
386 EXPORT_SYMBOL(mdc_close);
387 EXPORT_SYMBOL(mdc_open);
388
389 module_init(ptlrpc_request_init);
390 module_exit(ptlrpc_request_exit);