Whamcloud - gitweb
Branch: HEAD
[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_attach(struct obd_device *obd, obd_count len, void *buf)
36 {
37         struct lprocfs_static_vars lvars;
38
39         lprocfs_init_vars(ptlbd_cl, &lvars);
40         return lprocfs_obd_attach(obd, lvars.obd_vars);
41 }
42
43 static int ptlbd_cl_detach(struct obd_device *obd)
44 {
45         return lprocfs_obd_detach(obd);
46 }
47
48 static int ptlbd_cl_setup(struct obd_device *obd, obd_count len, void *buf)
49 {
50         struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
51         struct lustre_cfg* lcfg = buf;
52         struct obd_import *imp;
53         ENTRY;
54
55         if (ptlbd->bd_import != NULL)
56                 RETURN(-EALREADY);
57
58         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1) {
59                 CERROR("requires a PTLBD server UUID\n");
60                 RETURN(-EINVAL);
61         }
62
63         if (LUSTRE_CFG_BUFLEN(lcfg, 1) > 37) {
64                 CERROR("PTLBD server UUID must be less than 38 characters\n");
65                 RETURN(-EINVAL);
66         }
67
68         obd_str2uuid(&ptlbd->bd_server_uuid, lustre_cfg_string(lcfg, 1));
69
70         /*
71          * from client_obd_connect.. *shrug*
72          */
73         imp = ptlbd->bd_import = class_new_import();
74         imp->imp_connection = ptlrpc_uuid_to_connection(&ptlbd->bd_server_uuid);
75         if (!imp->imp_connection) {
76                 class_destroy_import(imp);
77                 class_import_put(imp);
78                 RETURN(-ENOENT);
79         }
80         imp->imp_state = LUSTRE_IMP_FULL;
81
82         ptlrpc_init_client(PTLBD_REQUEST_PORTAL, PTLBD_REPLY_PORTAL,
83                         "ptlbd", &ptlbd->bd_client);
84         imp->imp_client = &ptlbd->bd_client;
85         imp->imp_obd = obd;
86         memcpy(imp->imp_target_uuid.uuid, lustre_cfg_string(lcfg, 1),
87                LUSTRE_CFG_BUFLEN(lcfg, 1));
88         ptlbd_blk_register(ptlbd);
89
90         RETURN(0);
91 }
92
93 static int ptlbd_cl_cleanup(struct obd_device *obd, int flags)
94 {
95         struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
96         struct obd_import *imp;
97         ENTRY;
98
99         if ((!ptlbd) || (!(imp = ptlbd->bd_import)))
100                 RETURN(-ENOENT);
101
102         if (!imp->imp_connection)
103                 RETURN(-ENOENT);
104
105         ptlrpc_cleanup_client(imp);
106         ptlrpc_put_connection(imp->imp_connection);
107
108         class_destroy_import(imp);
109         class_import_put(imp);
110
111         RETURN(0);
112 }
113
114 /* modelled after ptlrpc_import_connect() */
115 int ptlbd_cl_connect(struct lustre_handle *conn, struct obd_device *obd,
116                      struct obd_uuid *target_uuid, unsigned long connect_flags)
117 {
118         struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
119         struct obd_import *imp = ptlbd->bd_import;
120         struct obd_export *exp;
121         struct ptlrpc_request *request;
122         int     rc, size[] = {sizeof(imp->imp_target_uuid),
123                               sizeof(obd->obd_uuid),
124                               sizeof(*conn)};
125         char *tmp[] = {imp->imp_target_uuid.uuid,
126                        obd->obd_uuid.uuid,
127                        (char*)conn};
128         ENTRY;
129
130         if (!conn || !obd || !target_uuid)
131                 RETURN(-EINVAL);
132
133         rc = class_connect(conn, obd, target_uuid);
134         if (rc)
135                 RETURN(rc);
136         exp = class_conn2export(conn);
137
138         request = ptlrpc_prep_req(imp, LUSTRE_PBD_VERSION, PTLBD_CONNECT,
139                                   3, size, tmp);
140         if (!request)
141                 GOTO(out_disco, rc = -ENOMEM);
142
143         request->rq_send_state = LUSTRE_IMP_NEW;
144         request->rq_replen = lustre_msg_size(0, NULL);
145
146         imp->imp_dlm_handle = *conn;
147
148         imp->imp_state = LUSTRE_IMP_NEW;
149         rc = ptlrpc_queue_wait(request);
150         if (rc)
151                 GOTO(out_req, rc);
152
153         exp->exp_connection = ptlrpc_connection_addref(imp->imp_connection);
154
155         imp->imp_state = LUSTRE_IMP_FULL;
156         imp->imp_remote_handle = request->rq_repmsg->handle;
157
158 out_req:
159         ptlrpc_req_finished(request);
160 out_disco:
161         if (rc)
162                 class_disconnect(exp, 0);
163         class_export_put(exp);
164         RETURN(rc);
165 }
166
167
168 /* modelled after ptlrpc_import_disconnect() */
169 int ptlbd_cl_disconnect(struct obd_export *exp, unsigned long flags)
170 {
171         struct obd_device *obd = exp->exp_obd;
172         struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
173         struct obd_import *imp = ptlbd->bd_import;
174         struct ptlrpc_request *request;
175         int     rc, err;
176         ENTRY;
177
178         if (!obd)
179                 RETURN(-EINVAL);
180
181         request = ptlrpc_prep_req(imp, LUSTRE_PBD_VERSION, 
182                                   PTLBD_DISCONNECT,
183                                   0, NULL, NULL);
184         if (!request)
185                 GOTO(out_req, rc = -ENOMEM);
186
187         request->rq_replen = lustre_msg_size(0, NULL);
188         request->rq_send_state = LUSTRE_IMP_FULL;
189
190         rc = ptlrpc_queue_wait(request);
191
192 out_req:
193         if (request)
194                 ptlrpc_req_finished(request);
195         err = class_disconnect(exp, 0);
196         memset(&imp->imp_remote_handle, 0, sizeof(imp->imp_remote_handle));
197         if (!rc && err)
198                 rc = err;
199         RETURN(rc);
200 }
201
202
203 static struct obd_ops ptlbd_cl_obd_ops = {
204         .o_owner        = THIS_MODULE,
205         .o_attach       = ptlbd_cl_attach,
206         .o_detach       = ptlbd_cl_detach,
207         .o_setup        = ptlbd_cl_setup,
208         .o_cleanup      = ptlbd_cl_cleanup,
209         .o_connect      = ptlbd_cl_connect,
210         .o_disconnect   = ptlbd_cl_disconnect,
211 };
212
213 static struct lprocfs_vars lprocfs_obd_vars[] = { {0} };
214 static struct lprocfs_vars lprocfs_module_vars[] = { {0} };
215 LPROCFS_INIT_VARS(ptlbd_cl, lprocfs_module_vars, lprocfs_obd_vars)
216
217 int ptlbd_cl_init(void)
218 {
219         struct lprocfs_static_vars lvars;
220
221         lprocfs_init_vars(ptlbd_cl,&lvars);
222         return class_register_type(&ptlbd_cl_obd_ops, NULL, lvars.module_vars,
223                                    OBD_PTLBD_CL_DEVICENAME);
224 }
225
226 void ptlbd_cl_exit(void)
227 {
228         class_unregister_type(OBD_PTLBD_CL_DEVICENAME);
229 }
230
231 int ptlbd_do_connect(struct ptlbd_obd *ptlbd)
232 {
233         int     rc;
234         struct obd_device       *obd = ptlbd->bd_import->imp_obd;
235         struct lustre_handle conn;
236         ENTRY;
237
238         memset(&conn, 0, sizeof(conn));
239         rc = obd_connect(&conn, obd, &ptlbd->bd_server_uuid, NULL, 0);
240         if (rc < 0)
241                 RETURN(rc);
242         ptlbd->bd_exp = class_conn2export(&conn);
243         RETURN(rc);
244 }
245
246
247 int ptlbd_do_disconnect(struct ptlbd_obd *ptlbd)
248 {
249         int     rc;
250         ENTRY;
251
252         rc = obd_disconnect(ptlbd->bd_exp, 0);
253         RETURN(rc);
254 }
255