Whamcloud - gitweb
LU-5458: libcfs: protect kkuc_groups from write access
[fs/lustre-release.git] / lustre / ptlrpc / llog_server.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, 2013, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/ptlrpc/llog_server.c
37  *
38  * remote api for llog - server side
39  *
40  * Author: Andreas Dilger <adilger@clusterfs.com>
41  */
42
43 #define DEBUG_SUBSYSTEM S_LOG
44
45 #include <obd_class.h>
46 #include <lu_target.h>
47 #include <lustre_log.h>
48 #include <lustre_net.h>
49
50 static int llog_origin_close(const struct lu_env *env, struct llog_handle *lgh)
51 {
52         if (lgh->lgh_hdr != NULL && lgh->lgh_hdr->llh_flags & LLOG_F_IS_CAT)
53                 return llog_cat_close(env, lgh);
54         else
55                 return llog_close(env, lgh);
56 }
57
58 /* Only open is supported, no new llog can be created remotely */
59 int llog_origin_handle_open(struct ptlrpc_request *req)
60 {
61         struct obd_export       *exp = req->rq_export;
62         struct obd_device       *obd = exp->exp_obd;
63         struct llog_handle      *loghandle;
64         struct llogd_body       *body;
65         struct llog_logid       *logid = NULL;
66         struct llog_ctxt        *ctxt;
67         char                    *name = NULL;
68         int                      rc;
69
70         ENTRY;
71
72         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
73         if (body == NULL)
74                 RETURN(err_serious(-EFAULT));
75
76         rc = req_capsule_server_pack(&req->rq_pill);
77         if (rc)
78                 RETURN(err_serious(-ENOMEM));
79
80         if (ostid_id(&body->lgd_logid.lgl_oi) > 0)
81                 logid = &body->lgd_logid;
82
83         if (req_capsule_field_present(&req->rq_pill, &RMF_NAME, RCL_CLIENT)) {
84                 name = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
85                 if (name == NULL)
86                         RETURN(-EFAULT);
87                 CDEBUG(D_INFO, "%s: opening log %s\n", obd->obd_name, name);
88         }
89
90         if (body->lgd_ctxt_idx >= LLOG_MAX_CTXTS) {
91                 CDEBUG(D_WARNING, "%s: bad ctxt ID: idx=%d name=%s\n",
92                        obd->obd_name, body->lgd_ctxt_idx, name);
93                 RETURN(-EPROTO);
94         }
95
96         ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
97         if (ctxt == NULL) {
98                 CDEBUG(D_WARNING, "%s: no ctxt. group=%p idx=%d name=%s\n",
99                        obd->obd_name, &obd->obd_olg, body->lgd_ctxt_idx, name);
100                 RETURN(-ENODEV);
101         }
102
103         rc = llog_open(req->rq_svc_thread->t_env, ctxt, &loghandle, logid,
104                        name, LLOG_OPEN_EXISTS);
105         if (rc)
106                 GOTO(out_ctxt, rc);
107
108         body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
109         body->lgd_logid = loghandle->lgh_id;
110
111         llog_origin_close(req->rq_svc_thread->t_env, loghandle);
112         EXIT;
113 out_ctxt:
114         llog_ctxt_put(ctxt);
115         return rc;
116 }
117 EXPORT_SYMBOL(llog_origin_handle_open);
118
119 int llog_origin_handle_destroy(struct ptlrpc_request *req)
120 {
121         struct llogd_body       *body;
122         struct llog_logid       *logid = NULL;
123         struct llog_ctxt        *ctxt;
124         int                      rc;
125
126         ENTRY;
127
128         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
129         if (body == NULL)
130                 RETURN(err_serious(-EFAULT));
131
132         rc = req_capsule_server_pack(&req->rq_pill);
133         if (rc < 0)
134                 RETURN(err_serious(-ENOMEM));
135
136         if (ostid_id(&body->lgd_logid.lgl_oi) > 0)
137                 logid = &body->lgd_logid;
138
139         if (!(body->lgd_llh_flags & LLOG_F_IS_PLAIN))
140                 CERROR("%s: wrong llog flags %x\n",
141                        req->rq_export->exp_obd->obd_name, body->lgd_llh_flags);
142
143         if (body->lgd_ctxt_idx >= LLOG_MAX_CTXTS) {
144                 CDEBUG(D_WARNING, "%s: bad ctxt ID: idx=%d\n",
145                        req->rq_export->exp_obd->obd_name, body->lgd_ctxt_idx);
146                 RETURN(-EPROTO);
147         }
148
149         ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx);
150         if (ctxt == NULL)
151                 RETURN(-ENODEV);
152
153         rc = llog_erase(req->rq_svc_thread->t_env, ctxt, logid, NULL);
154         llog_ctxt_put(ctxt);
155         RETURN(rc);
156 }
157 EXPORT_SYMBOL(llog_origin_handle_destroy);
158
159 int llog_origin_handle_next_block(struct ptlrpc_request *req)
160 {
161         struct llog_handle      *loghandle;
162         struct llogd_body       *body;
163         struct llogd_body       *repbody;
164         struct llog_ctxt        *ctxt;
165         __u32                    flags;
166         void                    *ptr;
167         int                      rc;
168
169         ENTRY;
170
171         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
172         if (body == NULL)
173                 RETURN(err_serious(-EFAULT));
174
175         req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER,
176                              LLOG_CHUNK_SIZE);
177         rc = req_capsule_server_pack(&req->rq_pill);
178         if (rc)
179                 RETURN(err_serious(-ENOMEM));
180
181         if (body->lgd_ctxt_idx >= LLOG_MAX_CTXTS) {
182                 CDEBUG(D_WARNING, "%s: bad ctxt ID: idx=%d\n",
183                        req->rq_export->exp_obd->obd_name, body->lgd_ctxt_idx);
184                 RETURN(-EPROTO);
185         }
186
187         ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx);
188         if (ctxt == NULL)
189                 RETURN(-ENODEV);
190
191         rc = llog_open(req->rq_svc_thread->t_env, ctxt, &loghandle,
192                        &body->lgd_logid, NULL, LLOG_OPEN_EXISTS);
193         if (rc)
194                 GOTO(out_ctxt, rc);
195
196         flags = body->lgd_llh_flags;
197         rc = llog_init_handle(req->rq_svc_thread->t_env, loghandle, flags,
198                               NULL);
199         if (rc)
200                 GOTO(out_close, rc);
201
202         repbody = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
203         *repbody = *body;
204
205         ptr = req_capsule_server_get(&req->rq_pill, &RMF_EADATA);
206         rc = llog_next_block(req->rq_svc_thread->t_env, loghandle,
207                              &repbody->lgd_saved_index, repbody->lgd_index,
208                              &repbody->lgd_cur_offset, ptr, LLOG_CHUNK_SIZE);
209         if (rc)
210                 GOTO(out_close, rc);
211         EXIT;
212 out_close:
213         llog_origin_close(req->rq_svc_thread->t_env, loghandle);
214 out_ctxt:
215         llog_ctxt_put(ctxt);
216         return rc;
217 }
218 EXPORT_SYMBOL(llog_origin_handle_next_block);
219
220 int llog_origin_handle_prev_block(struct ptlrpc_request *req)
221 {
222         struct llog_handle      *loghandle;
223         struct llogd_body       *body;
224         struct llogd_body       *repbody;
225         struct llog_ctxt        *ctxt;
226         __u32                    flags;
227         void                    *ptr;
228         int                      rc;
229
230         ENTRY;
231
232         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
233         if (body == NULL)
234                 RETURN(err_serious(-EFAULT));
235
236         req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER,
237                              LLOG_CHUNK_SIZE);
238         rc = req_capsule_server_pack(&req->rq_pill);
239         if (rc)
240                 RETURN(err_serious(-ENOMEM));
241
242         if (body->lgd_ctxt_idx >= LLOG_MAX_CTXTS) {
243                 CDEBUG(D_WARNING, "%s: bad ctxt ID: idx=%d\n",
244                        req->rq_export->exp_obd->obd_name, body->lgd_ctxt_idx);
245                 RETURN(-EPROTO);
246         }
247
248         ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx);
249         if (ctxt == NULL)
250                 RETURN(-ENODEV);
251
252         rc = llog_open(req->rq_svc_thread->t_env, ctxt, &loghandle,
253                          &body->lgd_logid, NULL, LLOG_OPEN_EXISTS);
254         if (rc)
255                 GOTO(out_ctxt, rc);
256
257         flags = body->lgd_llh_flags;
258         rc = llog_init_handle(req->rq_svc_thread->t_env, loghandle, flags,
259                               NULL);
260         if (rc)
261                 GOTO(out_close, rc);
262
263         repbody = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
264         *repbody = *body;
265
266         ptr = req_capsule_server_get(&req->rq_pill, &RMF_EADATA);
267         rc = llog_prev_block(req->rq_svc_thread->t_env, loghandle,
268                              body->lgd_index, ptr, LLOG_CHUNK_SIZE);
269         if (rc)
270                 GOTO(out_close, rc);
271
272         EXIT;
273 out_close:
274         llog_origin_close(req->rq_svc_thread->t_env, loghandle);
275 out_ctxt:
276         llog_ctxt_put(ctxt);
277         return rc;
278 }
279 EXPORT_SYMBOL(llog_origin_handle_prev_block);
280
281 int llog_origin_handle_read_header(struct ptlrpc_request *req)
282 {
283         struct llog_handle      *loghandle;
284         struct llogd_body       *body;
285         struct llog_log_hdr     *hdr;
286         struct llog_ctxt        *ctxt;
287         __u32                    flags;
288         int                      rc;
289
290         ENTRY;
291
292         body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
293         if (body == NULL)
294                 RETURN(err_serious(-EFAULT));
295
296         rc = req_capsule_server_pack(&req->rq_pill);
297         if (rc)
298                 RETURN(err_serious(-ENOMEM));
299
300         if (body->lgd_ctxt_idx >= LLOG_MAX_CTXTS) {
301                 CDEBUG(D_WARNING, "%s: bad ctxt ID: idx=%d\n",
302                        req->rq_export->exp_obd->obd_name, body->lgd_ctxt_idx);
303                 RETURN(-EPROTO);
304         }
305
306         ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx);
307         if (ctxt == NULL)
308                 RETURN(-ENODEV);
309
310         rc = llog_open(req->rq_svc_thread->t_env, ctxt, &loghandle,
311                        &body->lgd_logid, NULL, LLOG_OPEN_EXISTS);
312         if (rc)
313                 GOTO(out_ctxt, rc);
314
315         /*
316          * llog_init_handle() reads the llog header
317          */
318         flags = body->lgd_llh_flags;
319         rc = llog_init_handle(req->rq_svc_thread->t_env, loghandle, flags,
320                               NULL);
321         if (rc)
322                 GOTO(out_close, rc);
323         flags = loghandle->lgh_hdr->llh_flags;
324
325         hdr = req_capsule_server_get(&req->rq_pill, &RMF_LLOG_LOG_HDR);
326         *hdr = *loghandle->lgh_hdr;
327         EXIT;
328 out_close:
329         llog_origin_close(req->rq_svc_thread->t_env, loghandle);
330 out_ctxt:
331         llog_ctxt_put(ctxt);
332         return rc;
333 }
334 EXPORT_SYMBOL(llog_origin_handle_read_header);
335
336 int llog_origin_handle_close(struct ptlrpc_request *req)
337 {
338         int      rc;
339
340         ENTRY;
341
342         rc = req_capsule_server_pack(&req->rq_pill);
343         if (rc)
344                 RETURN(err_serious(-ENOMEM));
345         RETURN(0);
346 }
347 EXPORT_SYMBOL(llog_origin_handle_close);