#include "yaffs_nameval.h"
#include "yaffs_allocator.h"
#include "yaffs_attribs.h"
+ #include "yaffs_summary.h"
/* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */
#define YAFFS_GC_GOOD_ENOUGH 2
void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR * name)
{
-#ifndef CONFIG_YAFFS_NO_SHORT_NAMES
memset(obj->short_name, 0, sizeof(obj->short_name));
if (name &&
strnlen(name, YAFFS_SHORT_NAME_LENGTH + 1) <=
strcpy(obj->short_name, name);
else
obj->short_name[0] = _Y('\0');
-#endif
obj->sum = yaffs_calc_name_sum(name);
}
bi->has_shrink_hdr = 0;
bi->skip_erased_check = 1; /* Clean, so no need to check */
bi->gc_prioritise = 0;
+ bi->has_summary=0;
+
yaffs_clear_chunk_bits(dev, block_no);
yaffs_trace(YAFFS_TRACE_ERASE, "Erased block %d", block_no);
dev->gc_disable = 1;
+ yaffs_summary_gc(dev, block);
+
if (is_checkpt_block || !yaffs_still_some_chunks(dev, block)) {
yaffs_trace(YAFFS_TRACE_TRACING,
"Collecting block %d that has no chunks in use",
{
memset(name, 0, buffer_size * sizeof(YCHAR));
yaffs_check_obj_details_loaded(obj);
- if (obj->obj_id == YAFFS_OBJECTID_LOSTNFOUND)
+ if (obj->obj_id == YAFFS_OBJECTID_LOSTNFOUND) {
strncpy(name, YAFFS_LOSTNFOUND_NAME, buffer_size - 1);
-#ifndef CONFIG_YAFFS_NO_SHORT_NAMES
- else if (obj->short_name[0])
+ } else if (obj->short_name[0]) {
strcpy(name, obj->short_name);
-#endif
- else if (obj->hdr_chunk > 0) {
+ } else if (obj->hdr_chunk > 0) {
int result;
u8 *buffer = yaffs_get_temp_buffer(obj->my_dev);
if (!dev->param.erase_fn || !dev->param.initialise_flash_fn)
return 0;
-#ifdef CONFIG_YAFFS_YAFFS2
-
/* Can use the "with tags" style interface for yaffs1 or yaffs2 */
if (dev->param.write_chunk_tags_fn &&
dev->param.read_chunk_tags_fn &&
!dev->param.read_chunk_fn &&
dev->param.bad_block_fn && dev->param.query_block_fn)
return 1;
-#endif
/* Can use the "spare" style interface for yaffs1 */
if (!dev->param.is_yaffs2 &&
if (!init_failed && !yaffs_create_initial_dir(dev))
init_failed = 1;
+ if(!init_failed && dev->param.is_yaffs2 &&
+ !dev->param.disable_summary &&
+ !yaffs_summary_init(dev))
+ init_failed = 1;
+
if (!init_failed) {
/* Now scan the flash. */
if (dev->param.is_yaffs2) {
yaffs_deinit_blocks(dev);
yaffs_deinit_tnodes_and_objs(dev);
+ yaffs_summary_deinit(dev);
+
if (dev->param.n_caches > 0 && dev->cache) {
for (i = 0; i < dev->param.n_caches; i++) {
#define YAFFS_TNODES_INTERNAL_MASK 0x7
#define YAFFS_TNODES_MAX_LEVEL 6
-#ifndef CONFIG_YAFFS_NO_YAFFS1
+
+/* Constants for YAFFS1 mode */
#define YAFFS_BYTES_PER_SPARE 16
#define YAFFS_BYTES_PER_CHUNK 512
#define YAFFS_CHUNK_SIZE_SHIFT 9
#define YAFFS_CHUNKS_PER_BLOCK 32
#define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK)
-#endif
#define YAFFS_MIN_YAFFS2_CHUNK_SIZE 1024
#define YAFFS_MIN_YAFFS2_SPARE_SIZE 32
#define YAFFS_OBJECTID_UNLINKED 3
#define YAFFS_OBJECTID_DELETED 4
+ /* Fake object Id for summary data */
+ #define YAFFS_OBJECTID_SUMMARY 0x10
+
/* Pseudo object ids for checkpointing */
- #define YAFFS_OBJECTID_SB_HEADER 0x10
#define YAFFS_OBJECTID_CHECKPOINT_DATA 0x20
- #define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x21
+ #define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x21
#define YAFFS_MAX_SHORT_OP_CACHES 20
u8 *data;
};
-/* Tags structures in RAM
+/* yaffs1 tags structures in RAM
* NB This uses bitfield. Bitfields should not straddle a u32 boundary
* otherwise the structure size will get blown out.
*/
-#ifndef CONFIG_YAFFS_NO_YAFFS1
struct yaffs_tags {
unsigned chunk_id:20;
unsigned serial_number:2;
u8 as_bytes[8];
};
-#endif
/* Stuff used for extended tags in YAFFS2 */
Block should be prioritised for GC */
u32 chunk_error_strikes:3; /* How many times we've had ecc etc
failures on this block and tried to reuse it */
+ u32 has_summary:1; /* The block has a summary */
-#ifdef CONFIG_YAFFS_YAFFS2
u32 has_shrink_hdr:1; /* This block has at least one shrink header */
u32 seq_number; /* block sequence number for yaffs2 */
-#endif
};
u32 yst_mode;
-#ifndef CONFIG_YAFFS_NO_SHORT_NAMES
YCHAR short_name[YAFFS_SHORT_NAME_LENGTH + 1];
-#endif
#ifdef CONFIG_YAFFS_WINCE
u32 win_ctime[2];
*/
int use_nand_ecc; /* Flag to decide whether or not to use
* NAND driver ECC on data (yaffs1) */
+ int tags_9bytes; /* Use 9 byte tags */
int no_tags_ecc; /* Flag to decide whether or not to do ECC
* on packed tags (yaffs2) */
int (*initialise_flash_fn) (struct yaffs_dev *dev);
int (*deinitialise_flash_fn) (struct yaffs_dev *dev);
-#ifdef CONFIG_YAFFS_YAFFS2
+ /* yaffs2 mode functions */
int (*write_chunk_tags_fn) (struct yaffs_dev *dev,
int nand_chunk, const u8 *data,
const struct yaffs_ext_tags *tags);
int (*query_block_fn) (struct yaffs_dev *dev, int block_no,
enum yaffs_block_state *state,
u32 *seq_number);
-#endif
/* The remove_obj_fn function must be supplied by OS flavours that
* need it.
int auto_unicode;
#endif
int always_check_erased; /* Force chunk erased check always on */
+
+ int disable_summary;
};
struct yaffs_dev {
unsigned gc_block;
unsigned gc_chunk;
unsigned gc_skip;
+ struct yaffs_summary_tags *gc_sum_tags;
/* Special directories */
struct yaffs_obj *root_dir;
/* Dirty directory handling */
struct list_head dirty_dirs; /* List of dirty directories */
- /* Statistcs */
+ /* Summary */
+ int chunks_per_summary;
+ struct yaffs_summary_tags *sum_tags;
+
+ /* Statistics */
u32 n_page_writes;
u32 n_page_reads;
u32 n_erasures;
u32 n_unmarked_deletions;
u32 refresh_count;
u32 cache_hits;
+ u32 tags_used;
+ u32 summary_used;
};
unsigned int yaffs_auto_checkpoint = 1;
unsigned int yaffs_gc_control = 1;
unsigned int yaffs_bg_enable = 1;
-
+unsigned int yaffs_auto_select = 1;
/* Module Parameters */
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
module_param(yaffs_trace_mask, uint, 0644);
static int yaffs_writepage(struct page *page);
#endif
-#ifdef CONFIG_YAFFS_XATTR
static int yaffs_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags);
static ssize_t yaffs_getxattr(struct dentry *dentry, const char *name,
void *buff, size_t size);
static int yaffs_removexattr(struct dentry *dentry, const char *name);
static ssize_t yaffs_listxattr(struct dentry *dentry, char *buff, size_t size);
-#endif
#if (YAFFS_USE_WRITE_BEGIN_END != 0)
static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
static const struct inode_operations yaffs_file_inode_operations = {
.setattr = yaffs_setattr,
-#ifdef CONFIG_YAFFS_XATTR
.setxattr = yaffs_setxattr,
.getxattr = yaffs_getxattr,
.listxattr = yaffs_listxattr,
.removexattr = yaffs_removexattr,
-#endif
};
static const struct inode_operations yaffs_symlink_inode_operations = {
.put_link = yaffs_put_link,
#endif
.setattr = yaffs_setattr,
-#ifdef CONFIG_YAFFS_XATTR
.setxattr = yaffs_setxattr,
.getxattr = yaffs_getxattr,
.listxattr = yaffs_listxattr,
.removexattr = yaffs_removexattr,
-#endif
};
static const struct inode_operations yaffs_dir_inode_operations = {
.mknod = yaffs_mknod,
.rename = yaffs_rename,
.setattr = yaffs_setattr,
-#ifdef CONFIG_YAFFS_XATTR
.setxattr = yaffs_setxattr,
.getxattr = yaffs_getxattr,
.listxattr = yaffs_listxattr,
.removexattr = yaffs_removexattr,
-#endif
};
static const struct file_operations yaffs_dir_operations = {
return error;
}
-#ifdef CONFIG_YAFFS_XATTR
static int yaffs_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
return error;
}
-#endif
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
int lazy_loading_overridden;
int empty_lost_and_found;
int empty_lost_and_found_overridden;
+ int disable_summary;
};
#define MAX_OPT_LEN 30
} else if (!strcmp(cur_opt, "lazy-loading-on")) {
options->lazy_loading_enabled = 1;
options->lazy_loading_overridden = 1;
+ } else if (!strcmp(cur_opt, "disable_summary")) {
+ options->disable_summary = 1;
} else if (!strcmp(cur_opt, "empty-lost-and-found-off")) {
options->empty_lost_and_found = 0;
options->empty_lost_and_found_overridden = 1;
yaffs_trace(YAFFS_TRACE_OS, " size %lld", mtd->size);
#endif
-#ifdef CONFIG_YAFFS_AUTO_YAFFS2
-
- if (yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) {
+ if (yaffs_auto_select && yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) {
yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs2");
yaffs_version = 2;
}
yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs1");
yaffs_version = 1;
}
-#endif
if (yaffs_version == 2) {
/* Check for version 2 style functions */
param->n_caches = (options.no_cache) ? 0 : 10;
param->inband_tags = options.inband_tags;
-#ifdef CONFIG_YAFFS_DISABLE_LAZY_LOAD
- param->disable_lazy_load = 1;
-#endif
-#ifdef CONFIG_YAFFS_XATTR
param->enable_xattr = 1;
-#endif
if (options.lazy_loading_overridden)
param->disable_lazy_load = !options.lazy_loading_enabled;
-#ifdef CONFIG_YAFFS_DISABLE_TAGS_ECC
- param->no_tags_ecc = 1;
-#endif
-
-#ifdef CONFIG_YAFFS_DISABLE_BACKGROUND
-#else
param->defered_dir_update = 1;
-#endif
if (options.tags_ecc_overridden)
param->no_tags_ecc = !options.tags_ecc_on;
-#ifdef CONFIG_YAFFS_EMPTY_LOST_AND_FOUND
param->empty_lost_n_found = 1;
-#endif
-
-#ifdef CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING
- param->refresh_period = 0;
-#else
param->refresh_period = 500;
-#endif
-
-#ifdef CONFIG_YAFFS__ALWAYS_CHECK_CHUNK_ERASED
- param->always_check_erased = 1;
-#endif
+ param->disable_summary = options.disable_summary;
if (options.empty_lost_and_found_overridden)
param->empty_lost_n_found = options.empty_lost_and_found;
yaffs_dev_to_lc(dev)->super = sb;
-#ifndef CONFIG_YAFFS_DOES_ECC
param->use_nand_ecc = 1;
-#endif
-
-#ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES
- param->wide_tnodes_disabled = 1;
-#endif
param->skip_checkpt_rd = options.skip_checkpoint_read;
param->skip_checkpt_wr = options.skip_checkpoint_write;
FS_REQUIRES_DEV);
#endif
-#ifdef CONFIG_YAFFS_YAFFS2
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
FS_REQUIRES_DEV);
#endif
-#endif /* CONFIG_YAFFS_YAFFS2 */
static struct proc_dir_entry *my_proc_entry;
dev->n_unlinked_files);
buf += sprintf(buf, "refresh_count........ %u\n", dev->refresh_count);
buf += sprintf(buf, "n_bg_deletions....... %u\n", dev->n_bg_deletions);
+ buf += sprintf(buf, "tags_used............ %u\n", dev->tags_used);
+ buf += sprintf(buf, "summary_used......... %u\n", dev->summary_used);
return buf;
}
yaffs_trace(YAFFS_TRACE_ALWAYS,
"yaffs built " __DATE__ " " __TIME__ " Installing.");
-#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED
- yaffs_trace(YAFFS_TRACE_ALWAYS,
- " \n\n\n\nYAFFS-WARNING CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED selected.\n\n\n\n"
- );
-#endif
-
mutex_init(&yaffs_context_lock);
/* Install the proc_fs entries */