www.pudn.com > efs.rar > fs_pm_log.h


/**********************************************************************
 * fs_pm_log.h
 *
 * File System Log.
 * Copyright (C) 2002, 2003, 2004, 2005, 2006 Qualcomm, Inc.
 *
 * The Filesystem Log records changes made to the filesystem tables that
 * haven't necessarily been committed to the in-flash structures.  This
 * allows us to delay updates to these structures, with the assumption that
 * this delay will allow groups of these updates to be made together.
 *
 * This log is also read upon powerup and used to augment the in-flash
 * structures.
 */

/*===========================================================================

                        EDIT HISTORY FOR MODULE

  $Header: //depot/asic/MSMSHARED/services/efs/MSM_EFS.01.02/fs_pm_log.h#5 $ $DateTime: 2006/08/28 13:14:15 $ $Author: davidb $

when          who     what, where, why
--------      ---     ------------------------------------------------------
2006-08-17    dlb     Adjust API slightly to allow for log upgrades.
2005-12-14    dlb     Export log checking.
2005-11-04    dlb     Keep track of last written log.
2005-04-26    dlb     Add 2K page support.
2004-10-15    dlb     Update copyright header.
2003-05-07    dlb     Add log grouping.
2003-03-07    dlb     Increase the queue size.
2003-02-13    dlb     Replay logs for NAND operations.
2002-08-08    drh     Created by dlb.  Added history header.

===========================================================================*/


#ifndef __FS_NOR_LOG_H__
#define __FS_NOR_LOG_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "customer.h"
#include "comdef.h"


#include "fs_device.h"
#include "fs_pm_super.h"

struct fs_log_data;
typedef struct fs_log_data *fs_log_t;

/* The LOG is not specific about the kinds of data that are stored in the
 * LOG, that is the responsibility of the user of this module.
 *
 * However, we do encode in the log-codes, a few bits that indicates how
 * many arguments this particular code has.  All arguments are 32 bit
 * unsigned values.  The log-codes themselves can be constructed out of
 * these macros.
 *
 * Note that we support 0 to 3 arguments. */

typedef uint8   fs_log_code_t;

#define FS_LOG_CODE_MAKE(opcode, argc)   (((argc) << 6) | (opcode))
#define FS_LOG_CODE_ARGC(code)   ((code) >> 6)

/* We reserve a single special code for our use. */
#define LOG_CODE_GROUP_END      0xFE

/* Initialize the log structure.  Will use the given device to write out
 * log pages as needed. */
void fs_log_init (fs_log_t log, fs_device_t dev);

/* Set the sequence number used for the last page.  The sequence will be
 * incremented before writing out. */
void fs_log_set_sequence (fs_log_t log, uint32 seqno);

/* Return the number of pages queued up for potential logs to be written
 * to. */
int fs_log_page_count (fs_log_t log);

/* Add a page to the log code's queue of pages available. */
void fs_log_add_page (fs_log_t log, page_id page);

/* Add a page to the queue, but act as if it has already been written.  It
 * is an error to call this after calling fs_log_add_page. */
void fs_log_add_written_page (fs_log_t log, page_id page);

/* Return the next page that will be written. */
page_id fs_log_peek_page (fs_log_t log);

/* Return the next page that is needed for logging. */
page_id fs_log_peek_written (fs_log_t log);

/* Append a single log entry.  May cause an additional page to be used.
 * Only the number of arguments appropriate for the code will be used. */
void fs_log_add (fs_log_t log,
    fs_log_code_t       code,
    uint32      *args);

/* Ensure that it is possible to write the two named log codes to the same
 * page of the log.  This effectively assures that they are grouped and
 * treated atomically.  This may cause a flush if there isn't room for both
 * entries in the current page. */
void fs_log_group (fs_log_t log, fs_log_code_t a, fs_log_code_t b);

/* Flush the log to flash.  For some devices (NAND) this will always write
 * an entire page.  Other devices (NOR) may be able to write a page, and
 * not use up one of our allocated pages.  Returns the number of log pages
 * that were consumed by this flush.*/
void fs_log_flush (fs_log_t log);

/* Get the next available log page that has been fully flushed.  Returns
 * INVALID_PAGE_ID if there are not pages that have been flushed but not
 * returned by this function. */
page_id fs_log_get_written (fs_log_t log);

/* Return a count of the number of log pages that have been flushed fully.
 */
int fs_log_written_count (fs_log_t log);

/* Given a pointer to a particular log page, return true if it represents a
 * valid log page.  'dev' must be the device the page resides on (used to
 * determine the type of device).  If 'upgrade_page' is set to a
 * non-INVALID_PAGE_ID value, the page will be upgraded in place, if
 * possible and necessary. */
int fs_log_is_valid (const void *data, fs_device_t dev, page_id upgrade_page);

/***********************************************************************
 * Log page iteration.
 */

#define FS_LOG_ITER_GOOD        0
#define FS_LOG_ITER_ERASED      1
#define FS_LOG_ITER_CORRUPT     2

/* Read in a specified log page in preparation to iterate through it.
 * Returns various status FS_LOG_ITER_*, defined above.  If non-null, the
 * [header[0]] is set to the 32 bit marker at the head of the page.
 * [header[1]] is set to the following 32 bit marker. */
int fs_log_iter_set_page (fs_log_t log, page_id p, uint32 *header);

/* Peek the current iteration page. */
page_id fs_log_iter_peek_page (fs_log_t log);

/* Once the iterator is setup, step to the next field.  Code will be set to
 * the appropriate LOG code, or LOG_CODE_GROUP_END to indicate that we are
 * at the end of this log page. */
void fs_log_iter_step (fs_log_t log, fs_log_code_t *code, uint32 *args);

/* The iterators also have the ability to go back in time.  Although the
 * iterator will remember the previous page (and go back to it), the caller
 * must also remember what pages will come after this. */
void fs_log_iter_mark (fs_log_t log);
void fs_log_iter_reset (fs_log_t log);

/**********************************************************************
 *  ____       _            _
 * |  _ \ _ __(_)_   ____ _| |_ ___
 * | |_) | '__| \ \ / / _` | __/ _ \
 * |  __/| |  | |\ V / (_| | ||  __/
 * |_|   |_|  |_| \_/ \__,_|\__\___|
 *
 * Internal structure for the log.
 */

/* We keep track of a queue, both of pages that are available to be written
 * to, as well as of pages that we will later write a log to.  This is the
 * limit of how many of these pages there possibly are. */
#define FS_LOG_QUEUE_SIZE       100

/* Defined here to make it easer to parameterize later. */
#define FS_LOG_PAGE_SIZE        EFS_PAGE_SIZE

struct fs_log_data {
  fs_device_t           dev;

  /* Next sequence number to write. */
  uint32                seqno;

  /* Queue of pages. */
  page_id       queue[FS_LOG_QUEUE_SIZE];

  /* Parameters for the queue, [alloc] is the next page to allocate
   * (fs_log_add_page), [free] is the last page used (these are like head
   * and tail of a normal queue).  [flush] is where within the queue we've
   * flushed up to.  [count] is the number of pages between free and alloc.
   * Not counting wrapping of the queue, the parameters can be thought of
   * as describing a chain:
   *
   * free       flush             alloc
   *  |           |                 |
   *  V           V                 V
   *  +---+ +---+ +---+ +---+ +---+ +---+
   *  | 1 | | 2 | | 3 | | 4 | | 5 | | 6 |
   *  +---+ +---+ +---+ +---+ +---+ +---+
   *
   *  In this case, node 6 is the next page to be inserted by
   *  fs_log_add_page.  Node 3 is the next page to be written out (either
   *  by fs_log_add of fs_log_flush).  Node 1 is the next page to be given
   *  by fs_log_get_written.
   */
  int   q_alloc;
  int   q_flush;
  int   q_free;
  int   q_count;

  /* Buffer to hold a single page worth of log. */
  uint8         buffer[FS_LOG_PAGE_SIZE];

  /* Offset within the page where the next entry will be added. */
  int           group_offset;

  /* For the iterator, we have a page number and an offset. */
  page_id       iter_page;
  int           iter_offset;

  /* Also remember the mark position. */
  page_id       mark_page;
  int           mark_offset;

  /* Remember the last log page we have written. */
  page_id       last_written_log;
};

#ifdef __cplusplus
}
#endif


#endif /* __FS_NOR_LOG_H__ */