Whamcloud - gitweb
merge b_devel into HEAD, which will become 0.7.3
[fs/lustre-release.git] / lustre / ptlbd / client.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2002, 2003 Cluster File Systems, Inc.
5  *   Author: Zach Brown <zab@clusterfs.com>
6  *
7  *   This file is part of Lustre, http://www.lustre.org.
8  *
9  *   Lustre is free software; you can redistribute it and/or
10  *   modify it under the terms of version 2 of the GNU General Public
11  *   License as published by the Free Software Foundation.
12  *
13  *   Lustre is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with Lustre; if not, write to the Free Software
20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include <linux/version.h>
24 #include <linux/module.h>
25 #include <linux/fs.h>
26
27 #define DEBUG_SUBSYSTEM S_PTLBD
28
29 #include <linux/obd_support.h>
30 #include <linux/obd_class.h>
31 #include <linux/lustre_debug.h>
32 #include <linux/lprocfs_status.h>
33 #include <linux/obd_ptlbd.h>
34
35 static int ptlbd_cl_setup(struct obd_device *obd, obd_count len, void *buf)
36 {
37         struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
38         struct obd_import *imp;
39         struct obd_ioctl_data* data = buf;
40         ENTRY;
41
42         if (ptlbd->bd_import != NULL)
43                 RETURN(-EALREADY);
44
45         if (data->ioc_inllen1 < 1) {
46                 CERROR("requires a PTLBD server UUID\n");
47                 RETURN(-EINVAL);
48         }
49
50         if (data->ioc_inllen1 > 37) {
51                 CERROR("PTLBD server UUID must be less than 38 characters\n");
52                 RETURN(-EINVAL);
53         }
54
55         obd_str2uuid(&ptlbd->bd_server_uuid, data->ioc_inlbuf1);
56
57         /*
58          * from client_obd_connect.. *shrug*
59          */
60         imp = ptlbd->bd_import = class_new_import();
61         imp->imp_connection = ptlrpc_uuid_to_connection(&ptlbd->bd_server_uuid);
62         if (!imp->imp_connection) {
63                 class_destroy_import(imp);
64                 class_import_put(imp);
65                 RETURN(-ENOENT);
66         }
67         imp->imp_level = LUSTRE_CONN_FULL;
68
69         ptlrpc_init_client(PTLBD_REQUEST_PORTAL, PTLBD_REPLY_PORTAL, 
70                         "ptlbd", &ptlbd->bd_client);
71         imp->imp_client = &ptlbd->bd_client;
72         imp->imp_obd = obd;
73         memcpy(imp->imp_target_uuid.uuid, data->ioc_inlbuf1, data->ioc_inllen1);
74         ptlbd_blk_register(ptlbd);
75
76         RETURN(0);
77 }
78
79 static int ptlbd_cl_cleanup(struct obd_device *obd, int flags)
80 {
81         struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
82         struct obd_import *imp;
83         ENTRY;
84
85         if ((!ptlbd) || (!(imp = ptlbd->bd_import)))
86                 RETURN(-ENOENT);
87
88         if (!imp->imp_connection)
89                 RETURN(-ENOENT);
90
91         ptlrpc_cleanup_client(imp);
92         ptlrpc_put_connection(imp->imp_connection);
93
94         class_destroy_import(imp);
95         class_import_put(imp);
96
97         RETURN(0);
98 }
99
100
101 /* modelled after ptlrpc_import_connect() */
102 int ptlbd_cl_connect(struct lustre_handle *conn, struct obd_device *obd,
103                      struct obd_uuid *target_uuid)
104 {
105         struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
106         struct obd_import *imp = ptlbd->bd_import;
107         struct obd_export *exp;
108         struct ptlrpc_request *request;
109         int     rc, size[] = {sizeof(imp->imp_target_uuid),
110                               sizeof(obd->obd_uuid),
111                               sizeof(*conn)};
112         char *tmp[] = {imp->imp_target_uuid.uuid, 
113                        obd->obd_uuid.uuid,
114                        (char*)conn};
115         ENTRY;
116
117         if (!conn || !obd || !target_uuid)
118                 RETURN(-EINVAL);
119
120         rc = class_connect(conn, obd, target_uuid);
121         if (rc)
122                 RETURN(rc);
123
124         request = ptlrpc_prep_req(imp, PTLBD_CONNECT, 3, size, tmp);
125         if (!request)
126                 GOTO(out_disco, rc = -ENOMEM);
127         request->rq_level = LUSTRE_CONN_NEW;
128         request->rq_replen = lustre_msg_size(0, NULL);
129
130         imp->imp_dlm_handle = *conn;
131
132         imp->imp_level = LUSTRE_CONN_CON;
133         rc = ptlrpc_queue_wait(request);
134         if (rc)
135                 GOTO(out_req, rc);
136
137         exp = class_conn2export(conn);
138         exp->exp_connection = ptlrpc_connection_addref(request->rq_connection);
139         class_export_put(exp);
140
141         imp->imp_level = LUSTRE_CONN_FULL;
142         imp->imp_remote_handle = request->rq_repmsg->handle;
143         
144 out_req:
145         ptlrpc_req_finished(request);
146 out_disco:
147         if (rc)
148                 class_disconnect(conn, 0);
149         RETURN(rc);
150 }
151
152
153 /* modelled after ptlrpc_import_disconnect() */
154 int ptlbd_cl_disconnect(struct lustre_handle *conn, int failover)
155 {
156         struct obd_device *obd = class_conn2obd(conn);
157         struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
158         struct obd_import *imp = ptlbd->bd_import;
159         struct ptlrpc_request *request;
160         int     rc, err;
161         ENTRY;
162
163         if (!obd)
164                 RETURN(-EINVAL);
165
166         request = ptlrpc_prep_req(imp, PTLBD_DISCONNECT, 0, NULL, NULL);
167         if (!request)
168                 GOTO(out_req, rc = -ENOMEM);
169
170         request->rq_replen = lustre_msg_size(0, NULL);
171         request->rq_level = LUSTRE_CONN_RECOVER;
172
173         rc = ptlrpc_queue_wait(request);
174
175 out_req:
176         if (request)
177                 ptlrpc_req_finished(request);
178         err = class_disconnect(conn, 0);
179         memset(&imp->imp_remote_handle, 0, sizeof(imp->imp_remote_handle));
180         if (!rc && err)
181                 rc = err;
182         RETURN(rc);
183 }
184
185
186 static struct obd_ops ptlbd_cl_obd_ops = {
187         o_owner:        THIS_MODULE,
188         o_setup:        ptlbd_cl_setup,
189         o_cleanup:      ptlbd_cl_cleanup,
190         o_connect:      ptlbd_cl_connect,
191         o_disconnect:   ptlbd_cl_disconnect,
192 };
193
194 int ptlbd_cl_init(void)
195 {
196         struct lprocfs_static_vars lvars;
197
198         lprocfs_init_vars(ptlbd,&lvars);
199         return class_register_type(&ptlbd_cl_obd_ops, lvars.module_vars,
200                                    OBD_PTLBD_CL_DEVICENAME);
201 }
202
203 void ptlbd_cl_exit(void)
204 {
205         class_unregister_type(OBD_PTLBD_CL_DEVICENAME);
206 }
207
208
209
210 int ptlbd_do_connect(struct ptlbd_obd *ptlbd)
211 {
212         int     rc;
213         struct obd_device       *obd = ptlbd->bd_import->imp_obd;
214         ENTRY;
215
216         memset(&ptlbd->bd_connect_handle, 0, sizeof(ptlbd->bd_connect_handle));
217         rc = obd_connect(&ptlbd->bd_connect_handle, obd, 
218                          &ptlbd->bd_server_uuid);
219         RETURN(rc);
220 }
221
222
223 int ptlbd_do_disconnect(struct ptlbd_obd *ptlbd)
224 {
225         int     rc;
226         ENTRY;
227
228         rc = obd_disconnect(&ptlbd->bd_connect_handle, 0);
229         RETURN(rc);
230 }
231