1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
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>
9 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
24 * Target-common OBD method implementations and utility functions.
28 #define DEBUG_SUBSYSTEM S_OST /* XXX WRONG */
30 #include <linux/module.h>
31 #include <linux/obd_ost.h>
32 #include <linux/lustre_net.h>
33 #include <linux/lustre_dlm.h>
35 int target_handle_connect(struct ptlrpc_request *req)
37 struct obd_device *target;
38 struct obd_export *export;
39 struct obd_import *dlmimp;
40 struct lustre_handle conn;
41 char *tgtuuid, *cluuid;
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);
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);
57 i = class_uuid2dev(tgtuuid);
59 CERROR("UUID '%s' not found for connect\n", tgtuuid);
60 GOTO(out, rc = -ENODEV);
65 GOTO(out, rc = -ENODEV);
67 conn.addr = req->rq_reqmsg->addr;
68 conn.cookie = req->rq_reqmsg->cookie;
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)
76 rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
79 req->rq_repmsg->addr = conn.addr;
80 req->rq_repmsg->cookie = conn.cookie;
82 export = class_conn2export(&conn);
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);
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);
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 dlmimp->imp_level = LUSTRE_CONN_FULL;
110 int target_handle_disconnect(struct ptlrpc_request *req)
112 struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
116 rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
120 req->rq_status = obd_disconnect(conn);
125 static int target_disconnect_client(struct ptlrpc_connection *conn)
127 struct list_head *expiter, *n;
128 struct lustre_handle hdl;
129 struct obd_export *exp;
133 list_for_each_safe(expiter, n, &conn->c_exports) {
134 exp = list_entry(expiter, struct obd_export, exp_conn_chain);
136 hdl.addr = (__u64)(unsigned long)exp;
137 hdl.cookie = exp->exp_cookie;
138 rc = obd_disconnect(&hdl);
140 CERROR("disconnecting export %p failed: %d\n", exp, rc);
143 /* XXX spank the connection (it's frozen in _RECOVD for now!) */
147 static int target_fence_failed_connection(struct ptlrpc_connection *conn)
151 conn->c_recovd_data.rd_phase = RD_PREPARED;
156 int target_revoke_connection(struct recovd_data *rd, int phase)
158 struct ptlrpc_connection *conn = class_rd2conn(rd);
164 case PTLRPC_RECOVD_PHASE_PREPARE:
165 RETURN(target_fence_failed_connection(conn));
166 case PTLRPC_RECOVD_PHASE_RECOVER:
167 RETURN(target_disconnect_client(conn));
168 case PTLRPC_RECOVD_PHASE_FAILURE: