Whamcloud - gitweb
b=14149
[fs/lustre-release.git] / lustre / ptlrpc / llog_client.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2001-2004 Cluster File Systems, Inc.
5  *   Author: Andreas Dilger <adilger@clusterfs.com>
6  *
7  *   This file is part of the Lustre file system, http://www.lustre.org
8  *   Lustre is a trademark of Cluster File Systems, Inc.
9  *
10  *   You may have signed or agreed to another license before downloading
11  *   this software.  If so, you are bound by the terms and conditions
12  *   of that agreement, and the following does not apply to you.  See the
13  *   LICENSE file included with this distribution for more information.
14  *
15  *   If you did not agree to a different license, then this copy of Lustre
16  *   is open source software; you can redistribute it and/or modify it
17  *   under the terms of version 2 of the GNU General Public License as
18  *   published by the Free Software Foundation.
19  *
20  *   In either case, Lustre is distributed in the hope that it will be
21  *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
22  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  *   license text for more details.
24  *
25  *  remote api for llog - client side
26  *
27  */
28
29 #define DEBUG_SUBSYSTEM S_LOG
30
31 #ifndef EXPORT_SYMTAB
32 #define EXPORT_SYMTAB
33 #endif
34
35 #ifdef __KERNEL__
36 #include <libcfs/libcfs.h>
37 #else
38 #include <liblustre.h>
39 #endif
40
41 #include <obd_class.h>
42 #include <lustre_log.h>
43 #include <lustre_net.h>
44 #include <libcfs/list.h>
45
46 /* This is a callback from the llog_* functions.
47  * Assumes caller has already pushed us into the kernel context. */
48 static int llog_client_create(struct llog_ctxt *ctxt, struct llog_handle **res,
49                               struct llog_logid *logid, char *name)
50 {
51         struct obd_import     *imp;
52         struct llogd_body     *body;
53         struct llog_handle    *handle;
54         struct ptlrpc_request *req = NULL;
55         int                    rc;
56         ENTRY;
57
58         if (ctxt->loc_imp == NULL) {
59                 /* This used to be an assert; bug 6200 */
60                 CERROR("ctxt->loc_imp == NULL for context idx %d.  Unable to "
61                        "complete MDS/OSS recovery, but I'll try again next "
62                        "time.  Not fatal.\n", ctxt->loc_idx);
63                 RETURN(-EINVAL);
64         }
65         imp = ctxt->loc_imp;
66
67         handle = llog_alloc_handle();
68         if (handle == NULL)
69                 RETURN(-ENOMEM);
70         *res = handle;
71
72         req = ptlrpc_request_alloc(imp, &RQF_LLOG_ORIGIN_HANDLE_CREATE);
73         if (req == NULL)
74                 GOTO(err_free, rc = -ENOMEM);
75
76         if (name)
77                 req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
78                                      strlen(name) + 1);
79
80         rc = ptlrpc_request_pack(req, LUSTRE_LOG_VERSION,
81                                  LLOG_ORIGIN_HANDLE_CREATE);
82         if (rc) {
83                 ptlrpc_request_free(req);
84                 GOTO(err_free, rc);
85         }
86         ptlrpc_request_set_replen(req);
87
88         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
89         if (logid)
90                 body->lgd_logid = *logid;
91         body->lgd_ctxt_idx = ctxt->loc_idx - 1;
92
93         if (name) {
94                 char *tmp;
95                 tmp = req_capsule_client_sized_get(&req->rq_pill, &RMF_NAME,
96                                                    strlen(name) + 1);
97                 LASSERT(tmp);
98                 strcpy(tmp, name);
99         }
100
101         rc = ptlrpc_queue_wait(req);
102         if (rc)
103                 GOTO(err_free, rc);
104
105         body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
106         if (body == NULL)
107                 GOTO(err_free, rc =-EFAULT);
108
109         handle->lgh_id = body->lgd_logid;
110         handle->lgh_ctxt = ctxt;
111         EXIT;
112 out:
113         ptlrpc_req_finished(req);
114         return rc;
115 err_free:
116         llog_free_handle(handle);
117         goto out;
118 }
119
120 static int llog_client_destroy(struct llog_handle *loghandle)
121 {
122         struct ptlrpc_request *req = NULL;
123         struct llogd_body     *body;
124         int                    rc;
125         ENTRY;
126
127         req = ptlrpc_request_alloc_pack(loghandle->lgh_ctxt->loc_imp,
128                                         &RQF_LLOG_ORIGIN_HANDLE_DESTROY,
129                                         LUSTRE_LOG_VERSION,
130                                         LLOG_ORIGIN_HANDLE_DESTROY);
131         if (req == NULL)
132                 RETURN(-ENOMEM);
133
134         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
135         body->lgd_logid = loghandle->lgh_id;
136         body->lgd_llh_flags = loghandle->lgh_hdr->llh_flags;
137
138         ptlrpc_request_set_replen(req);
139         rc = ptlrpc_queue_wait(req);
140         
141         ptlrpc_req_finished(req);
142         RETURN(rc);
143 }
144
145
146 static int llog_client_next_block(struct llog_handle *loghandle,
147                                   int *cur_idx, int next_idx,
148                                   __u64 *cur_offset, void *buf, int len)
149 {
150         struct ptlrpc_request *req = NULL;
151         struct llogd_body     *body;
152         void                  *ptr;
153         int                    rc;
154         ENTRY;
155
156         req = ptlrpc_request_alloc_pack(loghandle->lgh_ctxt->loc_imp,
157                                         &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK,
158                                         LUSTRE_LOG_VERSION,
159                                         LLOG_ORIGIN_HANDLE_NEXT_BLOCK);
160         if (req == NULL)
161                 RETURN(-ENOMEM);
162
163         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
164         body->lgd_logid = loghandle->lgh_id;
165         body->lgd_ctxt_idx = loghandle->lgh_ctxt->loc_idx - 1;
166         body->lgd_llh_flags = loghandle->lgh_hdr->llh_flags;
167         body->lgd_index = next_idx;
168         body->lgd_saved_index = *cur_idx;
169         body->lgd_len = len;
170         body->lgd_cur_offset = *cur_offset;
171
172         req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER, len);
173         ptlrpc_request_set_replen(req);
174         rc = ptlrpc_queue_wait(req);
175         if (rc)
176                 GOTO(out, rc);
177
178         body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
179         if (body == NULL)
180                 GOTO(out, rc =-EFAULT);
181
182         /* The log records are swabbed as they are processed */
183         ptr = req_capsule_server_get(&req->rq_pill, &RMF_EADATA);
184         if (ptr == NULL)
185                 GOTO(out, rc =-EFAULT);
186
187         *cur_idx = body->lgd_saved_index;
188         *cur_offset = body->lgd_cur_offset;
189
190         memcpy(buf, ptr, len);
191         EXIT;
192 out:
193         ptlrpc_req_finished(req);
194         return rc;
195 }
196
197 static int llog_client_prev_block(struct llog_handle *loghandle,
198                                   int prev_idx, void *buf, int len)
199 {
200         struct ptlrpc_request *req = NULL;
201         struct llogd_body     *body;
202         void                  *ptr;
203         int                    rc;
204         ENTRY;
205
206         req = ptlrpc_request_alloc_pack(loghandle->lgh_ctxt->loc_imp,
207                                         &RQF_LLOG_ORIGIN_HANDLE_PREV_BLOCK,
208                                         LUSTRE_LOG_VERSION,
209                                         LLOG_ORIGIN_HANDLE_PREV_BLOCK);
210         if (req == NULL)
211                 RETURN(-ENOMEM);
212
213         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
214         body->lgd_logid = loghandle->lgh_id;
215         body->lgd_ctxt_idx = loghandle->lgh_ctxt->loc_idx - 1;
216         body->lgd_llh_flags = loghandle->lgh_hdr->llh_flags;
217         body->lgd_index = prev_idx;
218         body->lgd_len = len;
219
220         req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER, len);
221         ptlrpc_request_set_replen(req);
222
223         rc = ptlrpc_queue_wait(req);
224         if (rc)
225                 GOTO(out, rc);
226
227         body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
228         if (body == NULL)
229                 GOTO(out, rc =-EFAULT);
230
231         ptr = req_capsule_server_get(&req->rq_pill, &RMF_EADATA);
232         if (ptr == NULL)
233                 GOTO(out, rc =-EFAULT);
234
235         memcpy(buf, ptr, len);
236         EXIT;
237 out:
238         ptlrpc_req_finished(req);
239         return rc;
240 }
241
242 static int llog_client_read_header(struct llog_handle *handle)
243 {
244         struct ptlrpc_request *req = NULL;
245         struct llogd_body     *body;
246         struct llog_log_hdr   *hdr;
247         struct llog_rec_hdr   *llh_hdr;
248         int                    rc;
249         ENTRY;
250
251         req = ptlrpc_request_alloc_pack(handle->lgh_ctxt->loc_imp,
252                                         &RQF_LLOG_ORIGIN_HANDLE_READ_HEADER,
253                                         LUSTRE_LOG_VERSION,
254                                         LLOG_ORIGIN_HANDLE_READ_HEADER);
255         if (req == NULL)
256                 RETURN(-ENOMEM);
257
258         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
259         body->lgd_logid = handle->lgh_id;
260         body->lgd_ctxt_idx = handle->lgh_ctxt->loc_idx - 1;
261         body->lgd_llh_flags = handle->lgh_hdr->llh_flags;
262
263         ptlrpc_request_set_replen(req);
264         rc = ptlrpc_queue_wait(req);
265         if (rc)
266                 GOTO(out, rc);
267
268         hdr = req_capsule_server_get(&req->rq_pill, &RMF_LLOG_LOG_HDR);
269         if (hdr == NULL)
270                 GOTO(out, rc =-EFAULT);
271
272         memcpy(handle->lgh_hdr, hdr, sizeof (*hdr));
273         handle->lgh_last_idx = handle->lgh_hdr->llh_tail.lrt_index;
274
275         /* sanity checks */
276         llh_hdr = &handle->lgh_hdr->llh_hdr;
277         if (llh_hdr->lrh_type != LLOG_HDR_MAGIC) {
278                 CERROR("bad log header magic: %#x (expecting %#x)\n",
279                        llh_hdr->lrh_type, LLOG_HDR_MAGIC);
280                 rc = -EIO;
281         } else if (llh_hdr->lrh_len != LLOG_CHUNK_SIZE) {
282                 CERROR("incorrectly sized log header: %#x "
283                        "(expecting %#x)\n",
284                        llh_hdr->lrh_len, LLOG_CHUNK_SIZE);
285                 CERROR("you may need to re-run lconf --write_conf.\n");
286                 rc = -EIO;
287         }
288         EXIT;
289 out:
290         ptlrpc_req_finished(req);
291         return rc;
292 }
293
294 static int llog_client_close(struct llog_handle *handle)
295 {
296         /* this doesn't call LLOG_ORIGIN_HANDLE_CLOSE because
297            the servers all close the file at the end of every
298            other LLOG_ RPC. */
299         return(0);
300 }
301
302
303 struct llog_operations llog_client_ops = {
304         lop_next_block:  llog_client_next_block,
305         lop_prev_block:  llog_client_prev_block,
306         lop_read_header: llog_client_read_header,
307         lop_create:      llog_client_create,
308         lop_destroy:     llog_client_destroy,
309         lop_close:       llog_client_close,
310 };