4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.gnu.org/licenses/gpl-2.0.html
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright (c) 2011, 2014, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
30 * Lustre is a trademark of Sun Microsystems, Inc.
33 #define DEBUG_SUBSYSTEM S_LOG
35 #include <obd_class.h>
36 #include <uapi/linux/lustre_ioctl.h>
37 #include <lustre_log.h>
38 #include "llog_internal.h"
40 static int str2logid(struct llog_logid *logid, char *str, int len)
42 char *start, *end, *endp;
47 if (start[0] == '[') {
48 struct lu_fid *fid = &logid->lgl_oi.oi_fid;
53 num = sscanf(start + 1, SFID, RFID(fid));
54 CDEBUG(D_INFO, DFID":%x\n", PFID(fid), logid->lgl_ogen);
55 RETURN(num == 3 && fid_is_sane(fid) ? 0 : -EINVAL);
58 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 1, 53, 0)
59 /* logids used to be input in the form "#id#seq:ogen" before they
60 * were changed over to accept the FID [seq:oid:ver] format.
61 * This is accepted for compatibility reasons, though I doubt
62 * anyone is actually using this for anything. */
67 if (start - str >= len - 1)
69 end = strchr(start, '#');
70 if (end == NULL || end == start)
74 id = simple_strtoull(start, &endp, 0);
79 if (start - str >= len - 1)
81 end = strchr(start, '#');
82 if (end == NULL || end == start)
86 seq = simple_strtoull(start, &endp, 0);
90 ostid_set_seq(&logid->lgl_oi, seq);
91 ostid_set_id(&logid->lgl_oi, id);
94 if (start - str >= len - 1)
96 logid->lgl_ogen = simple_strtoul(start, &endp, 16);
106 static int llog_check_cb(const struct lu_env *env, struct llog_handle *handle,
107 struct llog_rec_hdr *rec, void *data)
109 struct obd_ioctl_data *ioc_data = (struct obd_ioctl_data *)data;
110 static int l, remains;
111 static long from, to;
114 int cur_index, rc = 0;
118 if (ioc_data && ioc_data->ioc_inllen1 > 0) {
120 remains = ioc_data->ioc_inllen4 +
121 cfs_size_round(ioc_data->ioc_inllen1) +
122 cfs_size_round(ioc_data->ioc_inllen2) +
123 cfs_size_round(ioc_data->ioc_inllen3);
124 from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0);
127 to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0);
130 ioc_data->ioc_inllen1 = 0;
131 out = ioc_data->ioc_bulk;
134 cur_index = rec->lrh_index;
135 if (cur_index < from)
137 if (to > 0 && cur_index > to)
138 RETURN(-LLOG_EEMPTY);
140 if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) {
141 struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
142 struct llog_handle *loghandle;
144 if (rec->lrh_type != LLOG_LOGID_MAGIC) {
145 l = snprintf(out, remains, "[index]: %05d [type]: "
146 "%02x [len]: %04d failed\n",
147 cur_index, rec->lrh_type,
150 if (handle->lgh_ctxt == NULL)
152 rc = llog_cat_id2handle(env, handle, &loghandle, &lir->lid_id);
154 CDEBUG(D_IOCTL, "cannot find log "DFID":%x\n",
155 PFID(&lir->lid_id.lgl_oi.oi_fid),
156 lir->lid_id.lgl_ogen);
159 rc = llog_process(env, loghandle, llog_check_cb, NULL, NULL);
160 llog_handle_put(loghandle);
164 switch (rec->lrh_type) {
167 case MDS_UNLINK64_REC:
168 case MDS_SETATTR64_REC:
178 l = snprintf(out, remains, "[index]: %05d [type]: "
179 "%02x [len]: %04d %s\n",
180 cur_index, rec->lrh_type, rec->lrh_len,
181 ok ? "ok" : "failed");
185 CERROR("%s: no space to print log records\n",
186 handle->lgh_ctxt->loc_obd->obd_name);
187 RETURN(-LLOG_EEMPTY);
193 static int llog_print_cb(const struct lu_env *env, struct llog_handle *handle,
194 struct llog_rec_hdr *rec, void *data)
196 struct obd_ioctl_data *ioc_data = (struct obd_ioctl_data *)data;
197 static int l, remains;
198 static long from, to;
204 if (ioc_data != NULL && ioc_data->ioc_inllen1 > 0) {
206 remains = ioc_data->ioc_inllen4 +
207 cfs_size_round(ioc_data->ioc_inllen1) +
208 cfs_size_round(ioc_data->ioc_inllen2) +
209 cfs_size_round(ioc_data->ioc_inllen3);
210 from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0);
213 to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0);
216 out = ioc_data->ioc_bulk;
217 ioc_data->ioc_inllen1 = 0;
220 cur_index = rec->lrh_index;
221 if (cur_index < from)
223 if (to > 0 && cur_index > to)
224 RETURN(-LLOG_EEMPTY);
226 if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) {
227 struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
229 if (rec->lrh_type != LLOG_LOGID_MAGIC) {
230 CERROR("invalid record in catalog\n");
234 l = snprintf(out, remains,
235 "[index]: %05d [logid]: "DFID":%x\n",
236 cur_index, PFID(&lir->lid_id.lgl_oi.oi_fid),
237 lir->lid_id.lgl_ogen);
238 } else if (rec->lrh_type == OBD_CFG_REC) {
241 rc = class_config_yaml_output(rec, out, remains);
246 l = snprintf(out, remains,
247 "[index]: %05d [type]: %02x [len]: %04d\n",
248 cur_index, rec->lrh_type, rec->lrh_len);
253 CERROR("not enough space for print log records\n");
254 RETURN(-LLOG_EEMPTY);
259 static int llog_remove_log(const struct lu_env *env, struct llog_handle *cat,
260 struct llog_logid *logid)
262 struct llog_handle *log;
267 rc = llog_cat_id2handle(env, cat, &log, logid);
269 CDEBUG(D_IOCTL, "cannot find log "DFID":%x\n",
270 PFID(&logid->lgl_oi.oi_fid), logid->lgl_ogen);
274 rc = llog_destroy(env, log);
276 CDEBUG(D_IOCTL, "cannot destroy log "DFID":%x\n",
277 PFID(&logid->lgl_oi.oi_fid), logid->lgl_ogen);
280 llog_cat_cleanup(env, cat, log, log->u.phd.phd_cookie.lgc_index);
282 llog_handle_put(log);
287 static int llog_delete_cb(const struct lu_env *env, struct llog_handle *handle,
288 struct llog_rec_hdr *rec, void *data)
290 struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
294 if (rec->lrh_type != LLOG_LOGID_MAGIC)
296 rc = llog_remove_log(env, handle, &lir->lid_id);
302 int llog_ioctl(const struct lu_env *env, struct llog_ctxt *ctxt, int cmd,
303 struct obd_ioctl_data *data)
305 struct llog_logid logid;
307 struct llog_handle *handle = NULL;
312 logname = data->ioc_inlbuf1;
313 if (logname[0] == '#' || logname[0] == '[') {
314 rc = str2logid(&logid, logname, data->ioc_inllen1);
317 rc = llog_open(env, ctxt, &handle, &logid, NULL,
321 } else if (logname[0] == '$' || isalpha(logname[0])) {
322 if (logname[0] == '$')
325 rc = llog_open(env, ctxt, &handle, NULL, logname,
333 rc = llog_init_handle(env, handle, 0, NULL);
335 GOTO(out_close, rc = -ENOENT);
338 case OBD_IOC_LLOG_INFO: {
340 int remains = data->ioc_inllen2 +
341 cfs_size_round(data->ioc_inllen1);
342 char *out = data->ioc_bulk;
344 l = snprintf(out, remains,
347 "records_count: %d\n"
349 PFID(&handle->lgh_id.lgl_oi.oi_fid),
350 handle->lgh_id.lgl_ogen,
351 handle->lgh_hdr->llh_flags,
352 handle->lgh_hdr->llh_flags &
353 LLOG_F_IS_CAT ? "cat" : "plain",
354 handle->lgh_hdr->llh_count,
355 handle->lgh_last_idx);
359 CERROR("%s: not enough space for log header info\n",
360 ctxt->loc_obd->obd_name);
365 case OBD_IOC_LLOG_CHECK:
366 LASSERT(data->ioc_inllen1 > 0);
367 rc = llog_process(env, handle, llog_check_cb, data, NULL);
368 if (rc == -LLOG_EEMPTY)
373 case OBD_IOC_LLOG_PRINT:
374 LASSERT(data->ioc_inllen1 > 0);
375 rc = llog_process(env, handle, llog_print_cb, data, NULL);
376 if (rc == -LLOG_EEMPTY)
381 case OBD_IOC_LLOG_CANCEL: {
382 struct llog_cookie cookie;
383 struct llog_logid plain;
386 cookie.lgc_index = simple_strtoul(data->ioc_inlbuf3, &endp, 0);
388 GOTO(out_close, rc = -EINVAL);
390 if (handle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN) {
391 rc = llog_cancel_rec(env, handle, cookie.lgc_index);
393 } else if (!(handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) {
394 GOTO(out_close, rc = -EINVAL);
397 if (data->ioc_inlbuf2 == NULL) /* catalog but no logid */
398 GOTO(out_close, rc = -ENOTTY);
400 rc = str2logid(&plain, data->ioc_inlbuf2, data->ioc_inllen2);
403 cookie.lgc_lgl = plain;
404 rc = llog_cat_cancel_records(env, handle, 1, &cookie);
409 case OBD_IOC_LLOG_REMOVE: {
410 struct llog_logid plain;
412 if (handle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN) {
413 rc = llog_destroy(env, handle);
415 } else if (!(handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) {
416 GOTO(out_close, rc = -EINVAL);
419 if (data->ioc_inlbuf2 > 0) {
420 /* remove indicate log from the catalog */
421 rc = str2logid(&plain, data->ioc_inlbuf2,
425 rc = llog_remove_log(env, handle, &plain);
427 /* remove all the log of the catalog */
428 rc = llog_process(env, handle, llog_delete_cb, NULL,
436 CERROR("%s: Unknown ioctl cmd %#x\n",
437 ctxt->loc_obd->obd_name, cmd);
438 GOTO(out_close, rc = -ENOTTY);
442 if (handle->lgh_hdr &&
443 handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)
444 llog_cat_close(env, handle);
446 llog_close(env, handle);
449 EXPORT_SYMBOL(llog_ioctl);
451 int llog_catalog_list(const struct lu_env *env, struct dt_device *d,
452 int count, struct obd_ioctl_data *data,
453 const struct lu_fid *fid)
456 struct llog_catid *idarray;
457 struct llog_logid *id;
459 int l, remains, rc = 0;
463 if (count == 0) { /* get total number of logs */
464 rc = llog_osd_get_cat_list(env, d, 0, 0, NULL, fid);
470 size = sizeof(*idarray) * count;
472 OBD_ALLOC_LARGE(idarray, size);
476 rc = llog_osd_get_cat_list(env, d, 0, count, idarray, fid);
480 out = data->ioc_bulk;
481 remains = data->ioc_inllen1;
482 for (i = 0; i < count; i++) {
483 id = &idarray[i].lci_logid;
484 l = snprintf(out, remains, "catalog_log: "DFID":%x\n",
485 PFID(&id->lgl_oi.oi_fid), id->lgl_ogen);
492 OBD_FREE_LARGE(idarray, size);
495 EXPORT_SYMBOL(llog_catalog_list);