blob: caee6f6b3681dbb5f3a33d6ea76bcd4ea2f95b4b [file] [log] [blame]
/*
* Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SDFAT_AMAP_H
#define _SDFAT_AMAP_H
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/rbtree.h>
/* AMAP Configuration Variable */
#define SMART_ALLOC_N_HOT_AU (5)
/* Allocating Destination (for smart allocator):
* moved to sdfat.h
*/
/*
* #define ALLOC_COLD_ALIGNED (1)
* #define ALLOC_COLD_PACKING (2)
* #define ALLOC_COLD_SEQ (4)
*/
/* Minimum sectors for support AMAP create */
#define AMAP_MIN_SUPPORT_SECTORS (1048576)
#define amap_add_hot_au(amap, au) amap_insert_to_list(au, &amap->slist_hot)
/* singly linked list */
struct slist_head {
struct slist_head *next;
struct slist_head *head;
};
/* AU entry type */
typedef struct __AU_INFO_T {
uint16_t idx; /* the index of the AU (0, 1, 2, ... ) */
uint16_t free_clusters; /* # of available cluster */
union {
struct list_head head;
struct slist_head shead;/* singly linked list head for hot list */
};
} AU_INFO_T;
/* Allocation Target AU */
typedef struct __TARGET_AU_T {
AU_INFO_T *au; /* Working AU */
uint16_t idx; /* Intra-AU cluster index */
uint16_t clu_to_skip; /* Clusters to skip */
} TARGET_AU_T;
/* AMAP free-clusters-based node */
typedef struct {
struct list_head head; /* the list of AUs */
} FCLU_NODE_T;
/* AMAP options */
typedef struct {
unsigned int packing_ratio; /* Tunable packing ratio */
unsigned int au_size; /* AU size in sectors */
unsigned int au_align_factor; /* Hidden sectors % au_size */
} AMAP_OPT_T;
typedef struct __AMAP_T {
spinlock_t amap_lock; /* obsolete */
struct super_block *sb;
int n_au;
int n_clean_au, n_full_au;
int clu_align_bias;
uint16_t clusters_per_au;
AU_INFO_T **au_table; /* An array of AU_INFO entries */
AMAP_OPT_T option;
/* Size-based AU management pool (cold) */
FCLU_NODE_T *fclu_nodes; /* An array of listheads */
int fclu_order; /* Page order that fclu_nodes needs */
int fclu_hint; /* maximum # of free clusters in an AU */
/* Hot AU list */
unsigned int total_fclu_hot; /* Free clusters in hot list */
struct slist_head slist_hot; /* Hot AU list */
/* Ignored AU list */
struct slist_head slist_ignored;
/* Allocator variables (keep 2 AUs at maximum) */
TARGET_AU_T cur_cold;
TARGET_AU_T cur_hot;
int n_need_packing;
} AMAP_T;
/* AU table */
#define N_AU_PER_TABLE (int)(PAGE_SIZE / sizeof(AU_INFO_T))
#define GET_AU(amap, i_AU) (amap->au_table[(i_AU) / N_AU_PER_TABLE] + ((i_AU) % N_AU_PER_TABLE))
//#define MAX_CLU_PER_AU (int)(PAGE_SIZE / sizeof(FCLU_NODE_T))
#define MAX_CLU_PER_AU (1024)
/* Cold AU bucket <-> # of freeclusters */
#define NODE_CLEAN(amap) (&amap->fclu_nodes[amap->clusters_per_au - 1])
#define NODE(fclu, amap) (&amap->fclu_nodes[fclu - 1])
#define FREE_CLUSTERS(node, amap) ((int)(node - amap->fclu_nodes) + 1)
/* AU status */
#define MAGIC_WORKING ((struct slist_head *)0xFFFF5091)
#define IS_AU_HOT(au, amap) (au->shead.head == &amap->slist_hot)
#define IS_AU_IGNORED(au, amap) (au->shead.head == &amap->slist_ignored)
#define IS_AU_WORKING(au, amap) (au->shead.head == MAGIC_WORKING)
#define SET_AU_WORKING(au) (au->shead.head = MAGIC_WORKING)
/* AU <-> cluster */
#define i_AU_of_CLU(amap, clu) ((amap->clu_align_bias + clu) / amap->clusters_per_au)
#define CLU_of_i_AU(amap, i_au, idx) \
((uint32_t)(i_au) * (uint32_t)amap->clusters_per_au + (idx) - amap->clu_align_bias)
/*
* NOTE : AMAP internal functions are moved to core.h
*/
#endif /* _SDFAT_AMAP_H */