1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2001-2004 Cluster File Systems, Inc.
5 * Author: Andreas Dilger <adilger@clusterfs.com>
7 * This file is part of the Lustre file system, http://www.lustre.org
8 * Lustre is a trademark of Cluster File Systems, Inc.
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.
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.
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.
25 * remote api for llog - client side
29 #define DEBUG_SUBSYSTEM S_LOG
36 #include <libcfs/libcfs.h>
38 #include <liblustre.h>
41 #include <obd_class.h>
42 #include <lustre_log.h>
43 #include <lustre_net.h>
44 #include <libcfs/list.h>
46 #define LLOG_CLIENT_ENTRY(ctxt, imp) do { \
47 mutex_down(&ctxt->loc_sem); \
48 if (ctxt->loc_imp) { \
49 imp = class_import_get(ctxt->loc_imp); \
51 CERROR("ctxt->loc_imp == NULL for context idx %d." \
52 "Unable to complete MDS/OSS recovery," \
53 "but I'll try again next time. Not fatal.\n", \
56 mutex_up(&ctxt->loc_sem); \
59 mutex_up(&ctxt->loc_sem); \
62 #define LLOG_CLIENT_EXIT(ctxt, imp) do { \
63 mutex_down(&ctxt->loc_sem); \
64 if (ctxt->loc_imp != imp) \
65 CWARN("loc_imp has changed from %p to %p", \
66 ctxt->loc_imp, imp); \
67 class_import_put(imp); \
68 mutex_up(&ctxt->loc_sem); \
71 /* This is a callback from the llog_* functions.
72 * Assumes caller has already pushed us into the kernel context. */
73 static int llog_client_create(struct llog_ctxt *ctxt, struct llog_handle **res,
74 struct llog_logid *logid, char *name)
76 struct obd_import *imp;
77 struct llogd_body *body;
78 struct llog_handle *handle;
79 struct ptlrpc_request *req = NULL;
83 LLOG_CLIENT_ENTRY(ctxt, imp);
85 handle = llog_alloc_handle();
90 req = ptlrpc_request_alloc(imp, &RQF_LLOG_ORIGIN_HANDLE_CREATE);
92 GOTO(err_free, rc = -ENOMEM);
95 req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
98 rc = ptlrpc_request_pack(req, LUSTRE_LOG_VERSION,
99 LLOG_ORIGIN_HANDLE_CREATE);
101 ptlrpc_request_free(req);
104 ptlrpc_request_set_replen(req);
106 body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
108 body->lgd_logid = *logid;
109 body->lgd_ctxt_idx = ctxt->loc_idx - 1;
113 tmp = req_capsule_client_sized_get(&req->rq_pill, &RMF_NAME,
119 rc = ptlrpc_queue_wait(req);
123 body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
125 GOTO(err_free, rc =-EFAULT);
127 handle->lgh_id = body->lgd_logid;
128 handle->lgh_ctxt = ctxt;
131 LLOG_CLIENT_EXIT(ctxt, imp);
132 ptlrpc_req_finished(req);
135 llog_free_handle(handle);
139 static int llog_client_destroy(struct llog_handle *loghandle)
141 struct obd_import *imp;
142 struct ptlrpc_request *req = NULL;
143 struct llogd_body *body;
147 LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp);
148 req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_DESTROY,
150 LLOG_ORIGIN_HANDLE_DESTROY);
152 GOTO(err_exit, rc =-ENOMEM);
154 body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
155 body->lgd_logid = loghandle->lgh_id;
156 body->lgd_llh_flags = loghandle->lgh_hdr->llh_flags;
158 ptlrpc_request_set_replen(req);
159 rc = ptlrpc_queue_wait(req);
161 ptlrpc_req_finished(req);
163 LLOG_CLIENT_EXIT(loghandle->lgh_ctxt, imp);
168 static int llog_client_next_block(struct llog_handle *loghandle,
169 int *cur_idx, int next_idx,
170 __u64 *cur_offset, void *buf, int len)
172 struct obd_import *imp;
173 struct ptlrpc_request *req = NULL;
174 struct llogd_body *body;
179 LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp);
180 req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK,
182 LLOG_ORIGIN_HANDLE_NEXT_BLOCK);
184 GOTO(err_exit, rc =-ENOMEM);
186 body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
187 body->lgd_logid = loghandle->lgh_id;
188 body->lgd_ctxt_idx = loghandle->lgh_ctxt->loc_idx - 1;
189 body->lgd_llh_flags = loghandle->lgh_hdr->llh_flags;
190 body->lgd_index = next_idx;
191 body->lgd_saved_index = *cur_idx;
193 body->lgd_cur_offset = *cur_offset;
195 req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER, len);
196 ptlrpc_request_set_replen(req);
197 rc = ptlrpc_queue_wait(req);
201 body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
203 GOTO(out, rc =-EFAULT);
205 /* The log records are swabbed as they are processed */
206 ptr = req_capsule_server_get(&req->rq_pill, &RMF_EADATA);
208 GOTO(out, rc =-EFAULT);
210 *cur_idx = body->lgd_saved_index;
211 *cur_offset = body->lgd_cur_offset;
213 memcpy(buf, ptr, len);
216 ptlrpc_req_finished(req);
218 LLOG_CLIENT_EXIT(loghandle->lgh_ctxt, imp);
222 static int llog_client_prev_block(struct llog_handle *loghandle,
223 int prev_idx, void *buf, int len)
225 struct obd_import *imp;
226 struct ptlrpc_request *req = NULL;
227 struct llogd_body *body;
232 LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp);
233 req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_PREV_BLOCK,
235 LLOG_ORIGIN_HANDLE_PREV_BLOCK);
237 GOTO(err_exit, rc = -ENOMEM);
239 body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
240 body->lgd_logid = loghandle->lgh_id;
241 body->lgd_ctxt_idx = loghandle->lgh_ctxt->loc_idx - 1;
242 body->lgd_llh_flags = loghandle->lgh_hdr->llh_flags;
243 body->lgd_index = prev_idx;
246 req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER, len);
247 ptlrpc_request_set_replen(req);
249 rc = ptlrpc_queue_wait(req);
253 body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
255 GOTO(out, rc =-EFAULT);
257 ptr = req_capsule_server_get(&req->rq_pill, &RMF_EADATA);
259 GOTO(out, rc =-EFAULT);
261 memcpy(buf, ptr, len);
264 ptlrpc_req_finished(req);
266 LLOG_CLIENT_EXIT(loghandle->lgh_ctxt, imp);
270 static int llog_client_read_header(struct llog_handle *handle)
272 struct obd_import *imp;
273 struct ptlrpc_request *req = NULL;
274 struct llogd_body *body;
275 struct llog_log_hdr *hdr;
276 struct llog_rec_hdr *llh_hdr;
280 LLOG_CLIENT_ENTRY(handle->lgh_ctxt, imp);
281 req = ptlrpc_request_alloc_pack(imp,&RQF_LLOG_ORIGIN_HANDLE_READ_HEADER,
283 LLOG_ORIGIN_HANDLE_READ_HEADER);
285 GOTO(err_exit, rc = -ENOMEM);
287 body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
288 body->lgd_logid = handle->lgh_id;
289 body->lgd_ctxt_idx = handle->lgh_ctxt->loc_idx - 1;
290 body->lgd_llh_flags = handle->lgh_hdr->llh_flags;
292 ptlrpc_request_set_replen(req);
293 rc = ptlrpc_queue_wait(req);
297 hdr = req_capsule_server_get(&req->rq_pill, &RMF_LLOG_LOG_HDR);
299 GOTO(out, rc =-EFAULT);
301 memcpy(handle->lgh_hdr, hdr, sizeof (*hdr));
302 handle->lgh_last_idx = handle->lgh_hdr->llh_tail.lrt_index;
305 llh_hdr = &handle->lgh_hdr->llh_hdr;
306 if (llh_hdr->lrh_type != LLOG_HDR_MAGIC) {
307 CERROR("bad log header magic: %#x (expecting %#x)\n",
308 llh_hdr->lrh_type, LLOG_HDR_MAGIC);
310 } else if (llh_hdr->lrh_len != LLOG_CHUNK_SIZE) {
311 CERROR("incorrectly sized log header: %#x "
313 llh_hdr->lrh_len, LLOG_CHUNK_SIZE);
314 CERROR("you may need to re-run lconf --write_conf.\n");
319 ptlrpc_req_finished(req);
321 LLOG_CLIENT_EXIT(handle->lgh_ctxt, imp);
325 static int llog_client_close(struct llog_handle *handle)
327 /* this doesn't call LLOG_ORIGIN_HANDLE_CLOSE because
328 the servers all close the file at the end of every
334 struct llog_operations llog_client_ops = {
335 lop_next_block: llog_client_next_block,
336 lop_prev_block: llog_client_prev_block,
337 lop_read_header: llog_client_read_header,
338 lop_create: llog_client_create,
339 lop_destroy: llog_client_destroy,
340 lop_close: llog_client_close,