/*
 * nasd_layout.h
 *
 * Structures for layout for NASD embedded filesystem
 *
 * Author: Jim Zelenka
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1998,1999.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */


#ifndef _NASD_LAYOUT_H_
#define _NASD_LAYOUT_H_

#include <nasd/nasd_options.h>
#include <nasd/nasd_security.h>
#include <nasd/nasd_threadstuff.h>
#include <nasd/nasd_od.h>
#include <nasd/nasd_sys.h>
#include <nasd/nasd_control.h>
#include <nasd/nasd_shutdown.h>
#include <nasd/nasd_cache.h>

typedef struct nasd_layout_switch_s            nasd_layout_switch_t;
typedef struct nasd_odc_prealloc_adj_handle_s  nasd_odc_prealloc_adj_handle_t;

struct nasd_odc_prealloc_adj_handle_s {
  nasd_blkcnt_t   prealloc_blocks; /* new target */
  nasd_oblkcnt_t  pb_need;         /* delta on current */
};

/*
 * Init layout type.
 */
typedef nasd_status_t (*nasd_nl_init_func_t)(
  nasd_od_config_t  *config);

/*
 * Allocating a new node block. Indicate prealloc
 * at this time as well to assist in layout decision,
 * as well as any hinted layout info. Give back the
 * node block in exle, and an optional prealloc range
 * in pre_exle.
 */
typedef nasd_status_t (*nasd_nl_get_node_block_func_t)(
  int                      partnum,
  nasd_blkcnt_t            prealloc_blocks,
  nasd_layout_hint_t      *layout_hint,
  nasd_odc_exlist_ent_t  **exle,
  nasd_odc_exlist_ent_t  **pre_exle);

/*
 * Unable to create node after all, undo get_node_block_func
 */
typedef nasd_status_t (*nasd_nl_node_fail_create_func_t)(
  int                     partnum,
  nasd_odc_exlist_ent_t  *exle,
  nasd_odc_exlist_ent_t  *pre_exle);

/*
 * Single block being freed up.
 */
typedef nasd_status_t (*nasd_nl_release_oneblock_func_t)(
  int            partnum,
  nasd_blkno_t   blkno,
  void          *layout_handle);

/*
 * Blocks are being freed up.
 */
typedef nasd_status_t (*nasd_nl_release_blocks_func_t)(
  int                     partnum,
  nasd_odc_exlist_ent_t  *exle,
  nasd_blkcnt_t          *blocks_released_p,
  void                   *layout_handle);

/*
 * Adjust preallocation on object to some new value.
 * This function should adjust the prealloc range on
 * the object if necessary and desired. If discard_exle
 * is non-NULL, the caller wants to free that block range
 * as well, and this routine should do so. These blocks
 * may be reused as a new preallocation range.
 */
typedef nasd_status_t (*nasd_nl_adj_prealloc_func_t)(
  int                              partnum,
  nasd_odc_ent_t                  *ne,
  nasd_odc_prealloc_adj_handle_t  *pah,
  int                              len_changed);

/*
 * An object with a preallocation range should lose that
 * specific range, without surrendering its reservation.
 */
typedef nasd_status_t (*nasd_nl_surrender_prealloc_func_t)(
  int              partnum,
  nasd_odc_ent_t  *ne);

/*
 * Allocate more blocks for an object.
 */
typedef nasd_status_t (*nasd_nl_alloc_blocks_func_t)(
  int                      partnum,
  nasd_odc_ent_t          *ne,
  nasd_blkcnt_t            needblks,
  nasd_blkno_t             blk_hint,
  nasd_odc_exlist_ent_t  **exle,
  nasd_blkcnt_t           *blocks_allocated_p);

/*
 * Node being deleted. Notification only, no action
 * needs to be taken.
 */
typedef nasd_status_t (*nasd_nl_node_deleting_func_t)(
  int              partnum,
  nasd_odc_ent_t  *ne);

/*
 * Perform any actions required on format, such as setting
 * aside blocks for permanent storage, etc.
 */
typedef nasd_status_t (*nasd_nl_format_func_t)(
  nasd_od_config_t  *config,
  nasd_blkno_t       first_real_data_blk);

typedef nasd_status_t (*nasd_nl_init_dynamic_func_t)(
  nasd_blkno_t first_real_data_blk);

struct nasd_layout_switch_s {
  nasd_layout_type_t                  nl_type;
  char                               *nl_name;
  nasd_nl_init_func_t                 nl_init;
  nasd_nl_format_func_t               nl_format;
  nasd_nl_init_dynamic_func_t         nl_init_dynamic;
  nasd_nl_get_node_block_func_t       nl_get_node_block;
  nasd_nl_node_fail_create_func_t     nl_node_fail_create;
  nasd_nl_release_oneblock_func_t     nl_release_oneblock;
  nasd_nl_release_blocks_func_t       nl_release_blocks;
  nasd_nl_adj_prealloc_func_t         nl_adj_prealloc;
  nasd_nl_surrender_prealloc_func_t   nl_surrender_prealloc;
  nasd_nl_node_deleting_func_t        nl_node_deleting;
  nasd_nl_alloc_blocks_func_t         nl_alloc_blocks;
};

/*
 * Layout globals
 */
extern nasd_ctrl_layout_stat_t nasd_drive_layout_stats;

/*
 * Generic layout routines
 */
nasd_status_t nasd_od_layout_init(
  nasd_od_config_t  *config);

nasd_status_t nasd_od_layout_init_dynamic(nasd_blkno_t first_real_data_blk);

nasd_status_t nasd_od_layout_get_node_block(
  int                      partnum,
  nasd_blkcnt_t            prealloc_blocks,
  nasd_layout_hint_t      *layout_hint,
  nasd_odc_exlist_ent_t  **exle,
  nasd_odc_exlist_ent_t  **pre_exle);

nasd_status_t nasd_od_layout_node_fail_create(
  int                     partnum,
  nasd_blkcnt_t           prealloc_blocks,
  nasd_odc_exlist_ent_t  *exle,
  nasd_odc_exlist_ent_t  *pre_exle);

nasd_status_t nasd_od_layout_release_oneblock(
  int            partnum,
  nasd_blkno_t   blknum,
  void          *layout_handle);

nasd_status_t nasd_od_layout_release_blocks(
  int                     partnum,
  nasd_odc_exlist_ent_t  *exle,
  void                   *layout_handle);

nasd_status_t nasd_od_layout_init_adj_prealloc(
  int                              partnum,
  nasd_odc_ent_t                  *ne,
  nasd_blkcnt_t                    prealloc_blocks,
  nasd_odc_prealloc_adj_handle_t  *pah);

nasd_status_t nasd_od_layout_cancel_adj_prealloc(
  int                              partnum,
  nasd_odc_ent_t                  *ne,
  nasd_odc_prealloc_adj_handle_t  *pah);

nasd_status_t nasd_od_layout_adj_prealloc(
  int                              partnum,
  nasd_odc_ent_t                  *ne,
  nasd_odc_prealloc_adj_handle_t  *pah,
  int                              len_changed);

nasd_status_t nasd_od_layout_surrender_prealloc(
  int              partnum,
  nasd_odc_ent_t  *ne);

nasd_status_t nasd_od_layout_node_deleting(
  int              partnum,
  nasd_odc_ent_t  *ne);

nasd_status_t nasd_od_layout_alloc_blocks(
  int                      partnum,
  nasd_odc_ent_t          *ne,
  nasd_blkcnt_t            needblks,
  nasd_blkno_t             blk_hint,
  nasd_odc_exlist_ent_t  **exle_p,
  nasd_blkcnt_t           *blocks_allocated_p);

nasd_status_t nasd_od_layout_get_prealloc(
  int                      partnum,
  nasd_odc_ent_t          *ne,
  nasd_blkcnt_t            needblks,
  nasd_odc_exlist_ent_t  **pre_exle_p,
  nasd_blkcnt_t           *gotp);

nasd_status_t nasd_od_layout_format(
  nasd_od_config_t  *config,
  nasd_blkno_t       first_real_data_blk);

#if NASD_DRIVE_LAYOUT_SEQUENTIAL_INCLUDE > 0
extern nasd_status_t nasd_nl_seq_init(
  nasd_od_config_t *config);
extern nasd_status_t nasd_nl_seq_cl_init(
  nasd_od_config_t *config);
extern nasd_status_t nasd_nl_seq_format(
  nasd_od_config_t  *config,
  nasd_blkno_t       first_real_data_blk);
extern nasd_status_t nasd_nl_seq_init_dynamic(
  nasd_blkno_t first_real_data_blk);
extern nasd_status_t nasd_nl_seq_get_node_block(
  int                      partnum,
  nasd_blkcnt_t            prealloc_blocks,
  nasd_layout_hint_t      *layout_hint,
  nasd_odc_exlist_ent_t  **exle,
  nasd_odc_exlist_ent_t  **pre_exle);
extern nasd_status_t nasd_nl_seq_node_fail_create(
  int                     partnum,
  nasd_odc_exlist_ent_t  *exle,
  nasd_odc_exlist_ent_t  *pre_exle);
extern nasd_status_t nasd_nl_seq_release_oneblock(
  int            partnum,
  nasd_blkno_t   blknum,
  void          *layout_handle);
extern nasd_status_t nasd_nl_seq_release_blocks(
  int                     partnum,
  nasd_odc_exlist_ent_t  *exle,
  nasd_blkcnt_t          *blocks_released_p,
  void                   *layout_handle);
extern nasd_status_t nasd_nl_seq_adj_prealloc(
  int                              partnum,
  nasd_odc_ent_t                  *ne,
  nasd_odc_prealloc_adj_handle_t  *pah,
  int                              len_changed);
extern nasd_status_t nasd_nl_seq_surrender_prealloc(
  int              partnum,
  nasd_odc_ent_t  *ne);
extern nasd_status_t nasd_nl_seq_node_deleting(
  int              partnum,
  nasd_odc_ent_t  *ne);
extern nasd_status_t nasd_nl_seq_alloc_blocks(
  int                      partnum,
  nasd_odc_ent_t          *ne,
  nasd_blkcnt_t            needblks,
  nasd_blkno_t             blk_hint,
  nasd_odc_exlist_ent_t  **exle_p,
  nasd_blkcnt_t           *blocks_allocated_p);
#endif /* NASD_DRIVE_LAYOUT_SEQUENTIAL_INCLUDE > 0 */

#if NASD_DRIVE_LAYOUT_REGION_INCLUDE > 0
/*
 * Region-based layout
 */
extern nasd_status_t nasd_nl_reg_init(nasd_od_config_t *config);
extern nasd_status_t nasd_nl_reg_nocl_init(nasd_od_config_t *config);
extern nasd_status_t nasd_nl_reg_format(nasd_od_config_t *config,
  nasd_blkno_t first_real_data_blk);
extern nasd_status_t nasd_nl_reg_init_dynamic(
  nasd_blkno_t first_real_data_blk);
extern nasd_status_t nasd_nl_reg_get_node_block(
  int                      partnum,
  nasd_blkcnt_t            prealloc_blocks,
  nasd_layout_hint_t      *layout_hint,
  nasd_odc_exlist_ent_t  **exle,
  nasd_odc_exlist_ent_t  **pre_exle);
extern nasd_status_t nasd_nl_reg_node_fail_create(
  int                     partnum,
  nasd_odc_exlist_ent_t  *exle,
  nasd_odc_exlist_ent_t  *pre_exle);
extern nasd_status_t nasd_nl_reg_release_oneblock(
  int            partnum,
  nasd_blkno_t   blknum,
  void          *layout_handle);
extern nasd_status_t nasd_nl_reg_release_blocks(
  int                     partnum,
  nasd_odc_exlist_ent_t  *exle,
  nasd_blkcnt_t          *blocks_released_p,
  void                   *layout_handle);
extern nasd_status_t nasd_nl_reg_adj_prealloc(
  int                              partnum,
  nasd_odc_ent_t                  *ne,
  nasd_odc_prealloc_adj_handle_t  *pah,
  int                              len_changed);
extern nasd_status_t nasd_nl_reg_surrender_prealloc(
  int              partnum,
  nasd_odc_ent_t  *ne);
extern nasd_status_t nasd_nl_reg_node_deleting(
  int              partnum,
  nasd_odc_ent_t  *ne);
extern nasd_status_t nasd_nl_reg_alloc_blocks(
  int                      partnum,
  nasd_odc_ent_t          *ne,
  nasd_blkcnt_t            needblks,
  nasd_blkno_t             blk_hint,
  nasd_odc_exlist_ent_t  **exle_p,
  nasd_blkcnt_t           *blocks_allocated_p);
#endif /* NASD_DRIVE_LAYOUT_REGION_INCLUDE > 0 */

#endif /* !_NASD_LAYOUT_H_ */

/* Local Variables:  */
/* indent-tabs-mode: nil */
/* tab-width: 2 */
/* End: */
