Whamcloud - gitweb
Landing of b_recovery (at last).
[fs/lustre-release.git] / lustre / lib / target.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  *   Author: Peter J. Braam <braam@clusterfs.com>
6  *   Author: Phil Schwan <phil@clusterfs.com>
7  *   Author: Mike Shaver <shaver@clusterfs.com>
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
11  *   Lustre is free software; you can redistribute it and/or
12  *   modify it under the terms of version 2 of the GNU General Public
13  *   License as published by the Free Software Foundation.
14  *
15  *   Lustre is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with Lustre; if not, write to the Free Software
22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  * Target-common OBD method implementations and utility functions.
25  */
26
27 #define EXPORT_SYMTAB
28 #define DEBUG_SUBSYSTEM S_OST /* XXX WRONG */
29
30 #include <linux/module.h>
31 #include <linux/obd_ost.h>
32 #include <linux/lustre_net.h>
33 #include <linux/lustre_dlm.h>
34
35 int target_handle_connect(struct ptlrpc_request *req)
36 {
37         struct obd_device *target;
38         struct obd_export *export;
39         struct obd_import *dlmimp;
40         struct lustre_handle conn;
41         char *tgtuuid, *cluuid;
42         int rc, i;
43         ENTRY;
44
45         tgtuuid = lustre_msg_buf(req->rq_reqmsg, 0);
46         if (req->rq_reqmsg->buflens[0] > 37) {
47                 CERROR("bad target UUID for connect\n");
48                 GOTO(out, rc = -EINVAL);
49         }
50
51         cluuid = lustre_msg_buf(req->rq_reqmsg, 1);
52         if (req->rq_reqmsg->buflens[1] > 37) {
53                 CERROR("bad client UUID for connect\n");
54                 GOTO(out, rc = -EINVAL);
55         }
56
57         i = class_uuid2dev(tgtuuid);
58         if (i == -1) {
59                 CERROR("UUID '%s' not found for connect\n", tgtuuid);
60                 GOTO(out, rc = -ENODEV);
61         }
62
63         target = &obd_dev[i];
64         if (!target)
65                 GOTO(out, rc = -ENODEV);
66
67         conn.addr = req->rq_reqmsg->addr;
68         conn.cookie = req->rq_reqmsg->cookie;
69
70         rc = obd_connect(&conn, target, cluuid, ptlrpc_recovd,
71                          target_revoke_connection);
72         /* EALREADY indicates a reconnection, send the reply normally. */
73         if (rc && rc != EALREADY)
74                 GOTO(out, rc);
75
76         rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
77         if (rc)
78                 GOTO(out, rc);
79         req->rq_repmsg->addr = conn.addr;
80         req->rq_repmsg->cookie = conn.cookie;
81
82         export = class_conn2export(&conn);
83         LASSERT(export);
84
85         req->rq_export = export;
86         export->exp_connection = ptlrpc_get_connection(&req->rq_peer, cluuid);
87         if (req->rq_connection != NULL)
88                 ptlrpc_put_connection(req->rq_connection);
89         req->rq_connection = ptlrpc_connection_addref(export->exp_connection);
90
91         spin_lock(&export->exp_connection->c_lock);
92         list_add(&export->exp_conn_chain, &export->exp_connection->c_exports);
93         spin_unlock(&export->exp_connection->c_lock);
94         recovd_conn_manage(export->exp_connection, ptlrpc_recovd,
95                            target_revoke_connection);
96
97         dlmimp = &export->exp_ldlm_data.led_import;
98         dlmimp->imp_connection = req->rq_connection;
99         dlmimp->imp_client = &export->exp_obd->obd_ldlm_client;
100         dlmimp->imp_handle.addr = req->rq_reqmsg->addr;
101         dlmimp->imp_handle.cookie = req->rq_reqmsg->cookie;
102         dlmimp->imp_obd = /* LDLM! */ NULL;
103         spin_lock_init(&dlmimp->imp_lock);
104         
105         req->rq_connection->c_level = LUSTRE_CONN_FULL;
106 out:
107         req->rq_status = rc;
108         RETURN(rc);
109 }
110
111 int target_handle_disconnect(struct ptlrpc_request *req)
112 {
113         struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
114         int rc;
115         ENTRY;
116
117         rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
118         if (rc)
119                 RETURN(rc);
120
121         req->rq_status = obd_disconnect(conn);
122
123         RETURN(0);
124 }
125
126 static int target_disconnect_client(struct ptlrpc_connection *conn)
127 {
128         struct list_head *expiter, *n;
129         struct lustre_handle hdl;
130         struct obd_export *exp;
131         int rc;
132         ENTRY;
133
134         list_for_each_safe(expiter, n, &conn->c_exports) {
135                 exp = list_entry(expiter, struct obd_export, exp_conn_chain);
136
137                 hdl.addr = (__u64)(unsigned long)exp;
138                 hdl.cookie = exp->exp_cookie;
139                 rc = obd_disconnect(&hdl);
140                 if (rc)
141                         CERROR("disconnecting export %p failed: %d\n", exp, rc);
142         }
143
144         /* XXX spank the connection (it's frozen in _RECOVD for now!) */
145         RETURN(0);
146 }
147
148 static int target_fence_failed_connection(struct ptlrpc_connection *conn)
149 {
150         ENTRY;
151
152         conn->c_level = LUSTRE_CONN_RECOVD;
153         conn->c_recovd_data.rd_phase = RD_PREPARED;
154
155         RETURN(0);
156 }
157
158 int target_revoke_connection(struct recovd_data *rd, int phase)
159 {
160         struct ptlrpc_connection *conn = class_rd2conn(rd);
161         
162         LASSERT(conn);
163         ENTRY;
164
165         switch (phase) {
166             case PTLRPC_RECOVD_PHASE_PREPARE:
167                 RETURN(target_fence_failed_connection(conn));
168             case PTLRPC_RECOVD_PHASE_RECOVER:
169                 RETURN(target_disconnect_client(conn));
170             case PTLRPC_RECOVD_PHASE_FAILURE:
171                 LBUG();
172                 RETURN(0);
173         }
174
175         LBUG();
176         RETURN(-ENOSYS);
177 }