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) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 28 * Use is subject to license terms. 29 * 30 * Copyright (c) 2012, 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/include/lustre_log.h 37 * 38 * Generic infrastructure for managing a collection of logs. 39 * These logs are used for: 40 * 41 * - orphan recovery: OST adds record on create 42 * - mtime/size consistency: the OST adds a record on first write 43 * - open/unlinked objects: OST adds a record on destroy 44 * 45 * - mds unlink log: the MDS adds an entry upon delete 46 * 47 * - raid1 replication log between OST's 48 * - MDS replication logs 49 */ 50 51#ifndef _LUSTRE_LOG_H 52#define _LUSTRE_LOG_H 53 54/** \defgroup log log 55 * 56 * @{ 57 */ 58 59#include "obd_class.h" 60#include "lustre/lustre_idl.h" 61#include "dt_object.h" 62 63#define LOG_NAME_LIMIT(logname, name) \ 64 snprintf(logname, sizeof(logname), "LOGS/%s", name) 65#define LLOG_EEMPTY 4711 66 67enum llog_open_param { 68 LLOG_OPEN_EXISTS = 0x0000, 69 LLOG_OPEN_NEW = 0x0001, 70}; 71 72struct plain_handle_data { 73 struct list_head phd_entry; 74 struct llog_handle *phd_cat_handle; 75 struct llog_cookie phd_cookie; /* cookie of this log in its cat */ 76}; 77 78struct cat_handle_data { 79 struct list_head chd_head; 80 struct llog_handle *chd_current_log; /* currently open log */ 81 struct llog_handle *chd_next_log; /* llog to be used next */ 82}; 83 84static inline void logid_to_fid(struct llog_logid *id, struct lu_fid *fid) 85{ 86 /* For compatibility purposes we identify pre-OSD (~< 2.3.51 MDS) 87 * logid's by non-zero ogen (inode generation) and convert them 88 * into IGIF */ 89 if (id->lgl_ogen == 0) { 90 fid->f_seq = id->lgl_oi.oi.oi_seq; 91 fid->f_oid = id->lgl_oi.oi.oi_id; 92 fid->f_ver = 0; 93 } else { 94 lu_igif_build(fid, id->lgl_oi.oi.oi_id, id->lgl_ogen); 95 } 96} 97 98static inline void fid_to_logid(struct lu_fid *fid, struct llog_logid *id) 99{ 100 id->lgl_oi.oi.oi_seq = fid->f_seq; 101 id->lgl_oi.oi.oi_id = fid->f_oid; 102 id->lgl_ogen = 0; 103} 104 105static inline void logid_set_id(struct llog_logid *log_id, __u64 id) 106{ 107 log_id->lgl_oi.oi.oi_id = id; 108} 109 110static inline __u64 logid_id(struct llog_logid *log_id) 111{ 112 return log_id->lgl_oi.oi.oi_id; 113} 114 115struct llog_handle; 116 117/* llog.c - general API */ 118int llog_init_handle(const struct lu_env *env, struct llog_handle *handle, 119 int flags, struct obd_uuid *uuid); 120int llog_copy_handler(const struct lu_env *env, struct llog_handle *llh, 121 struct llog_rec_hdr *rec, void *data); 122int llog_process(const struct lu_env *env, struct llog_handle *loghandle, 123 llog_cb_t cb, void *data, void *catdata); 124int llog_process_or_fork(const struct lu_env *env, 125 struct llog_handle *loghandle, 126 llog_cb_t cb, void *data, void *catdata, bool fork); 127int llog_reverse_process(const struct lu_env *env, 128 struct llog_handle *loghandle, llog_cb_t cb, 129 void *data, void *catdata); 130int llog_cancel_rec(const struct lu_env *env, struct llog_handle *loghandle, 131 int index); 132int llog_open(const struct lu_env *env, struct llog_ctxt *ctxt, 133 struct llog_handle **lgh, struct llog_logid *logid, 134 char *name, enum llog_open_param open_param); 135int llog_close(const struct lu_env *env, struct llog_handle *cathandle); 136int llog_is_empty(const struct lu_env *env, struct llog_ctxt *ctxt, 137 char *name); 138int llog_backup(const struct lu_env *env, struct obd_device *obd, 139 struct llog_ctxt *ctxt, struct llog_ctxt *bak_ctxt, 140 char *name, char *backup); 141 142/* llog_process flags */ 143#define LLOG_FLAG_NODEAMON 0x0001 144 145/* llog_cat.c - catalog api */ 146struct llog_process_data { 147 /** 148 * Any useful data needed while processing catalog. This is 149 * passed later to process callback. 150 */ 151 void *lpd_data; 152 /** 153 * Catalog process callback function, called for each record 154 * in catalog. 155 */ 156 llog_cb_t lpd_cb; 157 /** 158 * Start processing the catalog from startcat/startidx 159 */ 160 int lpd_startcat; 161 int lpd_startidx; 162}; 163 164struct llog_process_cat_data { 165 /** 166 * Temporary stored first_idx while scanning log. 167 */ 168 int lpcd_first_idx; 169 /** 170 * Temporary stored last_idx while scanning log. 171 */ 172 int lpcd_last_idx; 173}; 174 175int llog_cat_close(const struct lu_env *env, struct llog_handle *cathandle); 176int llog_cat_add_rec(const struct lu_env *env, struct llog_handle *cathandle, 177 struct llog_rec_hdr *rec, struct llog_cookie *reccookie, 178 void *buf, struct thandle *th); 179int llog_cat_declare_add_rec(const struct lu_env *env, 180 struct llog_handle *cathandle, 181 struct llog_rec_hdr *rec, struct thandle *th); 182int llog_cat_add(const struct lu_env *env, struct llog_handle *cathandle, 183 struct llog_rec_hdr *rec, struct llog_cookie *reccookie, 184 void *buf); 185int llog_cat_cancel_records(const struct lu_env *env, 186 struct llog_handle *cathandle, int count, 187 struct llog_cookie *cookies); 188int llog_cat_process_or_fork(const struct lu_env *env, 189 struct llog_handle *cat_llh, llog_cb_t cb, 190 void *data, int startcat, int startidx, bool fork); 191int llog_cat_process(const struct lu_env *env, struct llog_handle *cat_llh, 192 llog_cb_t cb, void *data, int startcat, int startidx); 193int llog_cat_reverse_process(const struct lu_env *env, 194 struct llog_handle *cat_llh, llog_cb_t cb, 195 void *data); 196int llog_cat_init_and_process(const struct lu_env *env, 197 struct llog_handle *llh); 198 199/* llog_obd.c */ 200int llog_setup(const struct lu_env *env, struct obd_device *obd, 201 struct obd_llog_group *olg, int index, 202 struct obd_device *disk_obd, struct llog_operations *op); 203int __llog_ctxt_put(const struct lu_env *env, struct llog_ctxt *ctxt); 204int llog_cleanup(const struct lu_env *env, struct llog_ctxt *); 205int llog_sync(struct llog_ctxt *ctxt, struct obd_export *exp, int flags); 206int llog_cancel(const struct lu_env *env, struct llog_ctxt *ctxt, 207 struct llog_cookie *cookies, int flags); 208 209/* llog_net.c */ 210int llog_initiator_connect(struct llog_ctxt *ctxt); 211 212struct llog_operations { 213 int (*lop_destroy)(const struct lu_env *env, 214 struct llog_handle *handle); 215 int (*lop_next_block)(const struct lu_env *env, struct llog_handle *h, 216 int *curr_idx, int next_idx, __u64 *offset, 217 void *buf, int len); 218 int (*lop_prev_block)(const struct lu_env *env, struct llog_handle *h, 219 int prev_idx, void *buf, int len); 220 int (*lop_read_header)(const struct lu_env *env, 221 struct llog_handle *handle); 222 int (*lop_setup)(const struct lu_env *env, struct obd_device *obd, 223 struct obd_llog_group *olg, int ctxt_idx, 224 struct obd_device *disk_obd); 225 int (*lop_sync)(struct llog_ctxt *ctxt, struct obd_export *exp, 226 int flags); 227 int (*lop_cleanup)(const struct lu_env *env, struct llog_ctxt *ctxt); 228 int (*lop_cancel)(const struct lu_env *env, struct llog_ctxt *ctxt, 229 struct llog_cookie *cookies, int flags); 230 int (*lop_connect)(struct llog_ctxt *ctxt, struct llog_logid *logid, 231 struct llog_gen *gen, struct obd_uuid *uuid); 232 /** 233 * Any llog file must be opened first using llog_open(). Llog can be 234 * opened by name, logid or without both, in last case the new logid 235 * will be generated. 236 */ 237 int (*lop_open)(const struct lu_env *env, struct llog_handle *lgh, 238 struct llog_logid *logid, char *name, 239 enum llog_open_param); 240 /** 241 * Opened llog may not exist and this must be checked where needed using 242 * the llog_exist() call. 243 */ 244 int (*lop_exist)(struct llog_handle *lgh); 245 /** 246 * Close llog file and calls llog_free_handle() implicitly. 247 * Any opened llog must be closed by llog_close() call. 248 */ 249 int (*lop_close)(const struct lu_env *env, struct llog_handle *handle); 250 /** 251 * Create new llog file. The llog must be opened. 252 * Must be used only for local llog operations. 253 */ 254 int (*lop_declare_create)(const struct lu_env *env, 255 struct llog_handle *handle, 256 struct thandle *th); 257 int (*lop_create)(const struct lu_env *env, struct llog_handle *handle, 258 struct thandle *th); 259 /** 260 * write new record in llog. It appends records usually but can edit 261 * existing records too. 262 */ 263 int (*lop_declare_write_rec)(const struct lu_env *env, 264 struct llog_handle *lgh, 265 struct llog_rec_hdr *rec, 266 int idx, struct thandle *th); 267 int (*lop_write_rec)(const struct lu_env *env, 268 struct llog_handle *loghandle, 269 struct llog_rec_hdr *rec, 270 struct llog_cookie *cookie, int cookiecount, 271 void *buf, int idx, struct thandle *th); 272 /** 273 * Add new record in llog catalog. Does the same as llog_write_rec() 274 * but using llog catalog. 275 */ 276 int (*lop_declare_add)(const struct lu_env *env, 277 struct llog_handle *lgh, 278 struct llog_rec_hdr *rec, struct thandle *th); 279 int (*lop_add)(const struct lu_env *env, struct llog_handle *lgh, 280 struct llog_rec_hdr *rec, struct llog_cookie *cookie, 281 void *buf, struct thandle *th); 282}; 283 284/* In-memory descriptor for a log object or log catalog */ 285struct llog_handle { 286 struct rw_semaphore lgh_lock; 287 spinlock_t lgh_hdr_lock; /* protect lgh_hdr data */ 288 struct llog_logid lgh_id; /* id of this log */ 289 struct llog_log_hdr *lgh_hdr; 290 struct file *lgh_file; 291 struct dt_object *lgh_obj; 292 int lgh_last_idx; 293 int lgh_cur_idx; /* used during llog_process */ 294 __u64 lgh_cur_offset; /* used during llog_process */ 295 struct llog_ctxt *lgh_ctxt; 296 union { 297 struct plain_handle_data phd; 298 struct cat_handle_data chd; 299 } u; 300 char *lgh_name; 301 void *private_data; 302 struct llog_operations *lgh_logops; 303 atomic_t lgh_refcount; 304}; 305 306#define LLOG_CTXT_FLAG_UNINITIALIZED 0x00000001 307#define LLOG_CTXT_FLAG_STOP 0x00000002 308 309struct llog_ctxt { 310 int loc_idx; /* my index the obd array of ctxt's */ 311 struct obd_device *loc_obd; /* points back to the containing obd*/ 312 struct obd_llog_group *loc_olg; /* group containing that ctxt */ 313 struct obd_export *loc_exp; /* parent "disk" export (e.g. MDS) */ 314 struct obd_import *loc_imp; /* to use in RPC's: can be backward 315 pointing import */ 316 struct llog_operations *loc_logops; 317 struct llog_handle *loc_handle; 318 struct mutex loc_mutex; /* protect loc_imp */ 319 atomic_t loc_refcount; 320 long loc_flags; /* flags, see above defines */ 321 struct dt_object *loc_dir; 322}; 323 324#define LLOG_PROC_BREAK 0x0001 325#define LLOG_DEL_RECORD 0x0002 326 327static inline int llog_obd2ops(struct llog_ctxt *ctxt, 328 struct llog_operations **lop) 329{ 330 if (ctxt == NULL) 331 return -ENOTCONN; 332 333 *lop = ctxt->loc_logops; 334 if (*lop == NULL) 335 return -EOPNOTSUPP; 336 337 return 0; 338} 339 340static inline int llog_handle2ops(struct llog_handle *loghandle, 341 struct llog_operations **lop) 342{ 343 if (loghandle == NULL || loghandle->lgh_logops == NULL) 344 return -EINVAL; 345 346 *lop = loghandle->lgh_logops; 347 return 0; 348} 349 350static inline int llog_data_len(int len) 351{ 352 return cfs_size_round(len); 353} 354 355static inline int llog_get_size(struct llog_handle *loghandle) 356{ 357 if (loghandle && loghandle->lgh_hdr) 358 return loghandle->lgh_hdr->llh_count; 359 return 0; 360} 361 362static inline struct llog_ctxt *llog_ctxt_get(struct llog_ctxt *ctxt) 363{ 364 atomic_inc(&ctxt->loc_refcount); 365 CDEBUG(D_INFO, "GETting ctxt %p : new refcount %d\n", ctxt, 366 atomic_read(&ctxt->loc_refcount)); 367 return ctxt; 368} 369 370static inline void llog_ctxt_put(struct llog_ctxt *ctxt) 371{ 372 if (ctxt == NULL) 373 return; 374 LASSERT_ATOMIC_GT_LT(&ctxt->loc_refcount, 0, LI_POISON); 375 CDEBUG(D_INFO, "PUTting ctxt %p : new refcount %d\n", ctxt, 376 atomic_read(&ctxt->loc_refcount) - 1); 377 __llog_ctxt_put(NULL, ctxt); 378} 379 380static inline void llog_group_init(struct obd_llog_group *olg, int group) 381{ 382 init_waitqueue_head(&olg->olg_waitq); 383 spin_lock_init(&olg->olg_lock); 384 mutex_init(&olg->olg_cat_processing); 385 olg->olg_seq = group; 386} 387 388static inline int llog_group_set_ctxt(struct obd_llog_group *olg, 389 struct llog_ctxt *ctxt, int index) 390{ 391 LASSERT(index >= 0 && index < LLOG_MAX_CTXTS); 392 393 spin_lock(&olg->olg_lock); 394 if (olg->olg_ctxts[index] != NULL) { 395 spin_unlock(&olg->olg_lock); 396 return -EEXIST; 397 } 398 olg->olg_ctxts[index] = ctxt; 399 spin_unlock(&olg->olg_lock); 400 return 0; 401} 402 403static inline struct llog_ctxt *llog_group_get_ctxt(struct obd_llog_group *olg, 404 int index) 405{ 406 struct llog_ctxt *ctxt; 407 408 LASSERT(index >= 0 && index < LLOG_MAX_CTXTS); 409 410 spin_lock(&olg->olg_lock); 411 if (olg->olg_ctxts[index] == NULL) 412 ctxt = NULL; 413 else 414 ctxt = llog_ctxt_get(olg->olg_ctxts[index]); 415 spin_unlock(&olg->olg_lock); 416 return ctxt; 417} 418 419static inline void llog_group_clear_ctxt(struct obd_llog_group *olg, int index) 420{ 421 LASSERT(index >= 0 && index < LLOG_MAX_CTXTS); 422 spin_lock(&olg->olg_lock); 423 olg->olg_ctxts[index] = NULL; 424 spin_unlock(&olg->olg_lock); 425} 426 427static inline struct llog_ctxt *llog_get_context(struct obd_device *obd, 428 int index) 429{ 430 return llog_group_get_ctxt(&obd->obd_olg, index); 431} 432 433static inline int llog_group_ctxt_null(struct obd_llog_group *olg, int index) 434{ 435 return (olg->olg_ctxts[index] == NULL); 436} 437 438static inline int llog_ctxt_null(struct obd_device *obd, int index) 439{ 440 return llog_group_ctxt_null(&obd->obd_olg, index); 441} 442 443static inline int llog_destroy(const struct lu_env *env, 444 struct llog_handle *handle) 445{ 446 struct llog_operations *lop; 447 int rc; 448 449 rc = llog_handle2ops(handle, &lop); 450 if (rc) 451 return rc; 452 if (lop->lop_destroy == NULL) 453 return -EOPNOTSUPP; 454 455 rc = lop->lop_destroy(env, handle); 456 return rc; 457} 458 459static inline int llog_next_block(const struct lu_env *env, 460 struct llog_handle *loghandle, int *cur_idx, 461 int next_idx, __u64 *cur_offset, void *buf, 462 int len) 463{ 464 struct llog_operations *lop; 465 int rc; 466 467 rc = llog_handle2ops(loghandle, &lop); 468 if (rc) 469 return rc; 470 if (lop->lop_next_block == NULL) 471 return -EOPNOTSUPP; 472 473 rc = lop->lop_next_block(env, loghandle, cur_idx, next_idx, 474 cur_offset, buf, len); 475 return rc; 476} 477 478static inline int llog_prev_block(const struct lu_env *env, 479 struct llog_handle *loghandle, 480 int prev_idx, void *buf, int len) 481{ 482 struct llog_operations *lop; 483 int rc; 484 485 rc = llog_handle2ops(loghandle, &lop); 486 if (rc) 487 return rc; 488 if (lop->lop_prev_block == NULL) 489 return -EOPNOTSUPP; 490 491 rc = lop->lop_prev_block(env, loghandle, prev_idx, buf, len); 492 return rc; 493} 494 495static inline int llog_connect(struct llog_ctxt *ctxt, 496 struct llog_logid *logid, struct llog_gen *gen, 497 struct obd_uuid *uuid) 498{ 499 struct llog_operations *lop; 500 int rc; 501 502 rc = llog_obd2ops(ctxt, &lop); 503 if (rc) 504 return rc; 505 if (lop->lop_connect == NULL) 506 return -EOPNOTSUPP; 507 508 rc = lop->lop_connect(ctxt, logid, gen, uuid); 509 return rc; 510} 511 512/* llog.c */ 513int llog_exist(struct llog_handle *loghandle); 514int llog_declare_create(const struct lu_env *env, 515 struct llog_handle *loghandle, struct thandle *th); 516int llog_create(const struct lu_env *env, struct llog_handle *handle, 517 struct thandle *th); 518int llog_declare_write_rec(const struct lu_env *env, 519 struct llog_handle *handle, 520 struct llog_rec_hdr *rec, int idx, 521 struct thandle *th); 522int llog_write_rec(const struct lu_env *env, struct llog_handle *handle, 523 struct llog_rec_hdr *rec, struct llog_cookie *logcookies, 524 int numcookies, void *buf, int idx, struct thandle *th); 525int llog_add(const struct lu_env *env, struct llog_handle *lgh, 526 struct llog_rec_hdr *rec, struct llog_cookie *logcookies, 527 void *buf, struct thandle *th); 528int llog_declare_add(const struct lu_env *env, struct llog_handle *lgh, 529 struct llog_rec_hdr *rec, struct thandle *th); 530int lustre_process_log(struct super_block *sb, char *logname, 531 struct config_llog_instance *cfg); 532int lustre_end_log(struct super_block *sb, char *logname, 533 struct config_llog_instance *cfg); 534int llog_open_create(const struct lu_env *env, struct llog_ctxt *ctxt, 535 struct llog_handle **res, struct llog_logid *logid, 536 char *name); 537int llog_erase(const struct lu_env *env, struct llog_ctxt *ctxt, 538 struct llog_logid *logid, char *name); 539int llog_write(const struct lu_env *env, struct llog_handle *loghandle, 540 struct llog_rec_hdr *rec, struct llog_cookie *reccookie, 541 int cookiecount, void *buf, int idx); 542 543/** @} log */ 544 545#endif 546