138 lines
4 KiB
C
138 lines
4 KiB
C
|
/*
|
||
|
* 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 */
|