linux/drivers/staging/lustre/lustre/include/lustre_log.h
<<
>>
Prefs
   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.gnu.org/licenses/gpl-2.0.html
  19 *
  20 * GPL HEADER END
  21 */
  22/*
  23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24 * Use is subject to license terms.
  25 *
  26 * Copyright (c) 2012, 2015, Intel Corporation.
  27 */
  28/*
  29 * This file is part of Lustre, http://www.lustre.org/
  30 * Lustre is a trademark of Sun Microsystems, Inc.
  31 *
  32 * lustre/include/lustre_log.h
  33 *
  34 * Generic infrastructure for managing a collection of logs.
  35 * These logs are used for:
  36 *
  37 * - orphan recovery: OST adds record on create
  38 * - mtime/size consistency: the OST adds a record on first write
  39 * - open/unlinked objects: OST adds a record on destroy
  40 *
  41 * - mds unlink log: the MDS adds an entry upon delete
  42 *
  43 * - raid1 replication log between OST's
  44 * - MDS replication logs
  45 */
  46
  47#ifndef _LUSTRE_LOG_H
  48#define _LUSTRE_LOG_H
  49
  50/** \defgroup log log
  51 *
  52 * @{
  53 */
  54
  55#include "obd_class.h"
  56#include "lustre/lustre_idl.h"
  57
  58#define LOG_NAME_LIMIT(logname, name)              \
  59        snprintf(logname, sizeof(logname), "LOGS/%s", name)
  60#define LLOG_EEMPTY 4711
  61
  62enum llog_open_param {
  63        LLOG_OPEN_EXISTS        = 0x0000,
  64        LLOG_OPEN_NEW           = 0x0001,
  65};
  66
  67struct plain_handle_data {
  68        struct list_head          phd_entry;
  69        struct llog_handle *phd_cat_handle;
  70        struct llog_cookie  phd_cookie; /* cookie of this log in its cat */
  71};
  72
  73struct cat_handle_data {
  74        struct list_head              chd_head;
  75        struct llog_handle     *chd_current_log; /* currently open log */
  76        struct llog_handle      *chd_next_log; /* llog to be used next */
  77};
  78
  79struct llog_handle;
  80
  81/* llog.c  -  general API */
  82int llog_init_handle(const struct lu_env *env, struct llog_handle *handle,
  83                     int flags, struct obd_uuid *uuid);
  84int llog_process(const struct lu_env *env, struct llog_handle *loghandle,
  85                 llog_cb_t cb, void *data, void *catdata);
  86int llog_process_or_fork(const struct lu_env *env,
  87                         struct llog_handle *loghandle,
  88                         llog_cb_t cb, void *data, void *catdata, bool fork);
  89int llog_open(const struct lu_env *env, struct llog_ctxt *ctxt,
  90              struct llog_handle **lgh, struct llog_logid *logid,
  91              char *name, enum llog_open_param open_param);
  92int llog_close(const struct lu_env *env, struct llog_handle *cathandle);
  93
  94/* llog_process flags */
  95#define LLOG_FLAG_NODEAMON 0x0001
  96
  97/* llog_cat.c - catalog api */
  98struct llog_process_data {
  99        /**
 100         * Any useful data needed while processing catalog. This is
 101         * passed later to process callback.
 102         */
 103        void            *lpd_data;
 104        /**
 105         * Catalog process callback function, called for each record
 106         * in catalog.
 107         */
 108        llog_cb_t           lpd_cb;
 109        /**
 110         * Start processing the catalog from startcat/startidx
 111         */
 112        int               lpd_startcat;
 113        int               lpd_startidx;
 114};
 115
 116struct llog_process_cat_data {
 117        /**
 118         * Temporary stored first_idx while scanning log.
 119         */
 120        int               lpcd_first_idx;
 121        /**
 122         * Temporary stored last_idx while scanning log.
 123         */
 124        int               lpcd_last_idx;
 125};
 126
 127struct thandle;
 128
 129int llog_cat_close(const struct lu_env *env, struct llog_handle *cathandle);
 130int llog_cat_process(const struct lu_env *env, struct llog_handle *cat_llh,
 131                     llog_cb_t cb, void *data, int startcat, int startidx);
 132
 133/* llog_obd.c */
 134int llog_setup(const struct lu_env *env, struct obd_device *obd,
 135               struct obd_llog_group *olg, int index,
 136               struct obd_device *disk_obd, struct llog_operations *op);
 137int __llog_ctxt_put(const struct lu_env *env, struct llog_ctxt *ctxt);
 138int llog_cleanup(const struct lu_env *env, struct llog_ctxt *);
 139
 140/* llog_net.c */
 141int llog_initiator_connect(struct llog_ctxt *ctxt);
 142
 143struct llog_operations {
 144        int (*lop_next_block)(const struct lu_env *env, struct llog_handle *h,
 145                              int *curr_idx, int next_idx, __u64 *offset,
 146                              void *buf, int len);
 147        int (*lop_prev_block)(const struct lu_env *env, struct llog_handle *h,
 148                              int prev_idx, void *buf, int len);
 149        int (*lop_read_header)(const struct lu_env *env,
 150                               struct llog_handle *handle);
 151        int (*lop_setup)(const struct lu_env *env, struct obd_device *obd,
 152                         struct obd_llog_group *olg, int ctxt_idx,
 153                         struct obd_device *disk_obd);
 154        int (*lop_sync)(struct llog_ctxt *ctxt, struct obd_export *exp,
 155                        int flags);
 156        int (*lop_cleanup)(const struct lu_env *env, struct llog_ctxt *ctxt);
 157        int (*lop_cancel)(const struct lu_env *env, struct llog_ctxt *ctxt,
 158                          struct llog_cookie *cookies, int flags);
 159        int (*lop_connect)(struct llog_ctxt *ctxt, struct llog_logid *logid,
 160                           struct llog_gen *gen, struct obd_uuid *uuid);
 161        /**
 162         * Any llog file must be opened first using llog_open().  Llog can be
 163         * opened by name, logid or without both, in last case the new logid
 164         * will be generated.
 165         */
 166        int (*lop_open)(const struct lu_env *env, struct llog_handle *lgh,
 167                        struct llog_logid *logid, char *name,
 168                        enum llog_open_param);
 169        /**
 170         * Opened llog may not exist and this must be checked where needed using
 171         * the llog_exist() call.
 172         */
 173        int (*lop_exist)(struct llog_handle *lgh);
 174        /**
 175         * Close llog file and calls llog_free_handle() implicitly.
 176         * Any opened llog must be closed by llog_close() call.
 177         */
 178        int (*lop_close)(const struct lu_env *env, struct llog_handle *handle);
 179        /**
 180         * Create new llog file. The llog must be opened.
 181         * Must be used only for local llog operations.
 182         */
 183        int (*lop_declare_create)(const struct lu_env *env,
 184                                  struct llog_handle *handle,
 185                                  struct thandle *th);
 186        /**
 187         * write new record in llog. It appends records usually but can edit
 188         * existing records too.
 189         */
 190        int (*lop_declare_write_rec)(const struct lu_env *env,
 191                                     struct llog_handle *lgh,
 192                                     struct llog_rec_hdr *rec,
 193                                     int idx, struct thandle *th);
 194        int (*lop_write_rec)(const struct lu_env *env,
 195                             struct llog_handle *loghandle,
 196                             struct llog_rec_hdr *rec,
 197                             struct llog_cookie *cookie, int cookiecount,
 198                             void *buf, int idx, struct thandle *th);
 199        /**
 200         * Add new record in llog catalog. Does the same as llog_write_rec()
 201         * but using llog catalog.
 202         */
 203        int (*lop_declare_add)(const struct lu_env *env,
 204                               struct llog_handle *lgh,
 205                               struct llog_rec_hdr *rec, struct thandle *th);
 206        int (*lop_add)(const struct lu_env *env, struct llog_handle *lgh,
 207                       struct llog_rec_hdr *rec, struct llog_cookie *cookie,
 208                       void *buf, struct thandle *th);
 209};
 210
 211/* In-memory descriptor for a log object or log catalog */
 212struct llog_handle {
 213        struct rw_semaphore      lgh_lock;
 214        spinlock_t               lgh_hdr_lock; /* protect lgh_hdr data */
 215        struct llog_logid        lgh_id; /* id of this log */
 216        struct llog_log_hdr     *lgh_hdr;
 217        size_t                   lgh_hdr_size;
 218        int                      lgh_last_idx;
 219        int                      lgh_cur_idx; /* used during llog_process */
 220        __u64                    lgh_cur_offset; /* used during llog_process */
 221        struct llog_ctxt        *lgh_ctxt;
 222        union {
 223                struct plain_handle_data         phd;
 224                struct cat_handle_data           chd;
 225        } u;
 226        char                    *lgh_name;
 227        void                    *private_data;
 228        struct llog_operations  *lgh_logops;
 229        atomic_t                 lgh_refcount;
 230};
 231
 232#define LLOG_CTXT_FLAG_UNINITIALIZED     0x00000001
 233#define LLOG_CTXT_FLAG_STOP              0x00000002
 234
 235struct llog_ctxt {
 236        int                   loc_idx; /* my index the obd array of ctxt's */
 237        struct obd_device       *loc_obd; /* points back to the containing obd*/
 238        struct obd_llog_group   *loc_olg; /* group containing that ctxt */
 239        struct obd_export       *loc_exp; /* parent "disk" export (e.g. MDS) */
 240        struct obd_import       *loc_imp; /* to use in RPC's: can be backward
 241                                           * pointing import
 242                                           */
 243        struct llog_operations  *loc_logops;
 244        struct llog_handle      *loc_handle;
 245        struct mutex             loc_mutex; /* protect loc_imp */
 246        atomic_t             loc_refcount;
 247        long                 loc_flags; /* flags, see above defines */
 248        /*
 249         * llog chunk size, and llog record size can not be bigger than
 250         * loc_chunk_size
 251         */
 252        __u32                   loc_chunk_size;
 253};
 254
 255#define LLOG_PROC_BREAK 0x0001
 256#define LLOG_DEL_RECORD 0x0002
 257
 258static inline int llog_handle2ops(struct llog_handle *loghandle,
 259                                  struct llog_operations **lop)
 260{
 261        if (!loghandle || !loghandle->lgh_logops)
 262                return -EINVAL;
 263
 264        *lop = loghandle->lgh_logops;
 265        return 0;
 266}
 267
 268static inline struct llog_ctxt *llog_ctxt_get(struct llog_ctxt *ctxt)
 269{
 270        atomic_inc(&ctxt->loc_refcount);
 271        CDEBUG(D_INFO, "GETting ctxt %p : new refcount %d\n", ctxt,
 272               atomic_read(&ctxt->loc_refcount));
 273        return ctxt;
 274}
 275
 276static inline void llog_ctxt_put(struct llog_ctxt *ctxt)
 277{
 278        if (!ctxt)
 279                return;
 280        LASSERT_ATOMIC_GT_LT(&ctxt->loc_refcount, 0, LI_POISON);
 281        CDEBUG(D_INFO, "PUTting ctxt %p : new refcount %d\n", ctxt,
 282               atomic_read(&ctxt->loc_refcount) - 1);
 283        __llog_ctxt_put(NULL, ctxt);
 284}
 285
 286static inline void llog_group_init(struct obd_llog_group *olg)
 287{
 288        init_waitqueue_head(&olg->olg_waitq);
 289        spin_lock_init(&olg->olg_lock);
 290        mutex_init(&olg->olg_cat_processing);
 291}
 292
 293static inline int llog_group_set_ctxt(struct obd_llog_group *olg,
 294                                      struct llog_ctxt *ctxt, int index)
 295{
 296        LASSERT(index >= 0 && index < LLOG_MAX_CTXTS);
 297
 298        spin_lock(&olg->olg_lock);
 299        if (olg->olg_ctxts[index]) {
 300                spin_unlock(&olg->olg_lock);
 301                return -EEXIST;
 302        }
 303        olg->olg_ctxts[index] = ctxt;
 304        spin_unlock(&olg->olg_lock);
 305        return 0;
 306}
 307
 308static inline struct llog_ctxt *llog_group_get_ctxt(struct obd_llog_group *olg,
 309                                                    int index)
 310{
 311        struct llog_ctxt *ctxt;
 312
 313        LASSERT(index >= 0 && index < LLOG_MAX_CTXTS);
 314
 315        spin_lock(&olg->olg_lock);
 316        if (!olg->olg_ctxts[index])
 317                ctxt = NULL;
 318        else
 319                ctxt = llog_ctxt_get(olg->olg_ctxts[index]);
 320        spin_unlock(&olg->olg_lock);
 321        return ctxt;
 322}
 323
 324static inline void llog_group_clear_ctxt(struct obd_llog_group *olg, int index)
 325{
 326        LASSERT(index >= 0 && index < LLOG_MAX_CTXTS);
 327        spin_lock(&olg->olg_lock);
 328        olg->olg_ctxts[index] = NULL;
 329        spin_unlock(&olg->olg_lock);
 330}
 331
 332static inline struct llog_ctxt *llog_get_context(struct obd_device *obd,
 333                                                 int index)
 334{
 335        return llog_group_get_ctxt(&obd->obd_olg, index);
 336}
 337
 338static inline int llog_group_ctxt_null(struct obd_llog_group *olg, int index)
 339{
 340        return (!olg->olg_ctxts[index]);
 341}
 342
 343static inline int llog_ctxt_null(struct obd_device *obd, int index)
 344{
 345        return llog_group_ctxt_null(&obd->obd_olg, index);
 346}
 347
 348static inline int llog_next_block(const struct lu_env *env,
 349                                  struct llog_handle *loghandle, int *cur_idx,
 350                                  int next_idx, __u64 *cur_offset, void *buf,
 351                                  int len)
 352{
 353        struct llog_operations *lop;
 354        int rc;
 355
 356        rc = llog_handle2ops(loghandle, &lop);
 357        if (rc)
 358                return rc;
 359        if (!lop->lop_next_block)
 360                return -EOPNOTSUPP;
 361
 362        rc = lop->lop_next_block(env, loghandle, cur_idx, next_idx,
 363                                 cur_offset, buf, len);
 364        return rc;
 365}
 366
 367/* llog.c */
 368int llog_declare_write_rec(const struct lu_env *env,
 369                           struct llog_handle *handle,
 370                           struct llog_rec_hdr *rec, int idx,
 371                           struct thandle *th);
 372int llog_write_rec(const struct lu_env *env, struct llog_handle *handle,
 373                   struct llog_rec_hdr *rec, struct llog_cookie *logcookies,
 374                   int numcookies, void *buf, int idx, struct thandle *th);
 375int lustre_process_log(struct super_block *sb, char *logname,
 376                       struct config_llog_instance *cfg);
 377int lustre_end_log(struct super_block *sb, char *logname,
 378                   struct config_llog_instance *cfg);
 379/** @} log */
 380
 381#endif
 382