/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
- * Copyright (C) 2002-2011 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
+ * Copyright (C) 2002-2018 Aleph One Ltd.
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, data, &tags);
- if (tags.ecc_result > YAFFS_ECC_RESULT_NO_ERROR)
+ if (result == YAFFS_FAIL ||
+ tags.ecc_result > YAFFS_ECC_RESULT_NO_ERROR)
retval = YAFFS_FAIL;
if (!yaffs_check_ff(data, dev->data_bytes_per_chunk) ||
int result;
result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, buffer, &temp_tags);
- if (memcmp(buffer, data, dev->data_bytes_per_chunk) ||
+ if (result == YAFFS_FAIL ||
+ memcmp(buffer, data, dev->data_bytes_per_chunk) ||
temp_tags.obj_id != tags->obj_id ||
temp_tags.chunk_id != tags->chunk_id ||
temp_tags.n_bytes != tags->n_bytes)
static int yaffs_find_alloc_block(struct yaffs_dev *dev)
{
- int i;
+ u32 i;
struct yaffs_block_info *bi;
if (dev->n_erased_blocks < 1) {
for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
dev->alloc_block_finder++;
- if (dev->alloc_block_finder < dev->internal_start_block
- || dev->alloc_block_finder > dev->internal_end_block) {
+ if (dev->alloc_block_finder < (int)dev->internal_start_block
+ || dev->alloc_block_finder > (int)dev->internal_end_block) {
dev->alloc_block_finder = dev->internal_start_block;
}
return -1;
}
- if (dev->n_erased_blocks < dev->param.n_reserved_blocks
+ if (dev->n_erased_blocks < (int)dev->param.n_reserved_blocks
&& dev->alloc_page == 0)
yaffs_trace(YAFFS_TRACE_ALLOCATE, "Allocating reserve");
const u8 *data,
struct yaffs_ext_tags *tags, int use_reserver)
{
- int attempts = 0;
+ u32 attempts = 0;
int write_ok = 0;
int chunk;
yaffs_handle_chunk_wr_ok(dev, chunk, data, tags);
} while (write_ok != YAFFS_OK &&
- (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));
+ (yaffs_wr_attempts == 0 || attempts <= yaffs_wr_attempts));
if (!write_ok)
chunk = -1;
static int yaffs_tags_match(const struct yaffs_ext_tags *tags, int obj_id,
int chunk_obj)
{
- return (tags->chunk_id == chunk_obj &&
- tags->obj_id == obj_id &&
+ return (tags->chunk_id == (u32)chunk_obj &&
+ tags->obj_id == (u32)obj_id &&
!tags->is_deleted) ? 1 : 0;
}
*/
static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev)
{
- int i;
+ u32 i;
if (dev->param.n_caches > 0) {
for (i = 0; i < dev->param.n_caches; i++) {
{
struct yaffs_cache *cache;
int usage;
- int i;
+ u32 i;
if (dev->param.n_caches < 1)
return NULL;
int chunk_id)
{
struct yaffs_dev *dev = obj->my_dev;
- int i;
+ u32 i;
if (dev->param.n_caches < 1)
return NULL;
static void yaffs_use_cache(struct yaffs_dev *dev, struct yaffs_cache *cache,
int is_write)
{
- int i;
+ u32 i;
if (dev->param.n_caches < 1)
return;
*/
static void yaffs_invalidate_whole_cache(struct yaffs_obj *in)
{
- int i;
+ u32 i;
struct yaffs_dev *dev = in->my_dev;
if (dev->param.n_caches > 0) {
{
struct yaffs_block_info *bi = yaffs_get_block_info(dev, block_no);
int erased_ok = 0;
- int i;
+ u32 i;
/* If the block is still healthy erase it and mark as clean.
* If the block has had a data failure, then retire it.
bi->block_state = YAFFS_BLOCK_STATE_DIRTY;
/* If this is the block being garbage collected then stop gc'ing */
- if (block_no == dev->gc_block)
+ if (block_no == (int)dev->gc_block)
dev->gc_block = 0;
/* If this block is currently the best candidate for gc
* then drop as a candidate */
- if (block_no == dev->gc_dirtiest) {
+ if (block_no == (int)dev->gc_dirtiest) {
dev->gc_dirtiest = 0;
dev->gc_pages_in_use = 0;
}
{
int old_chunk;
int ret_val = YAFFS_OK;
- int i;
+ u32 i;
int is_checkpt_block;
int max_copies;
int chunks_before = yaffs_get_erased_chunks(dev);
static unsigned yaffs_find_gc_block(struct yaffs_dev *dev,
int aggressive, int background)
{
- int i;
- int iterations;
- unsigned selected = 0;
+ u32 i;
+ u32 iterations;
+ u32 selected = 0;
int prioritised = 0;
int prioritised_exist = 0;
struct yaffs_block_info *bi;
- int threshold;
+ u32 threshold;
/* First let's see if we need to grab a prioritised block */
if (dev->has_pending_prioritised_gc && !aggressive) {
*/
if (!selected) {
- int pages_used;
+ u32 pages_used;
int n_blocks =
dev->internal_end_block - dev->internal_start_block + 1;
if (aggressive) {
threshold = dev->param.chunks_per_block;
iterations = n_blocks;
} else {
- int max_threshold;
+ u32 max_threshold;
if (background)
max_threshold = dev->param.chunks_per_block / 2;
gc_ok = yaffs_gc_block(dev, dev->gc_block, aggressive);
}
- if (dev->n_erased_blocks < (dev->param.n_reserved_blocks) &&
+ if (dev->n_erased_blocks < (int)dev->param.n_reserved_blocks &&
dev->gc_block > 0) {
yaffs_trace(YAFFS_TRACE_GC,
"yaffs: GC !!!no reclaim!!! n_erased_blocks %d after try %d block %d",
dev->n_erased_blocks, max_tries,
dev->gc_block);
}
- } while ((dev->n_erased_blocks < dev->param.n_reserved_blocks) &&
+ } while ((dev->n_erased_blocks < (int)dev->param.n_reserved_blocks) &&
(dev->gc_block > 0) && (max_tries < 2));
return aggressive ? gc_ok : YAFFS_OK;
(prev_chunk_id > 0) ? prev_tags.serial_number + 1 : 1;
new_tags.n_bytes = n_bytes;
- if (n_bytes < 1 || n_bytes > dev->data_bytes_per_chunk) {
+ if (n_bytes < 1 || n_bytes > (int)dev->data_bytes_per_chunk) {
yaffs_trace(YAFFS_TRACE_ERROR,
"Writing %d bytes to chunk!!!!!!!!!",
n_bytes);
struct yaffs_dev *dev;
struct yaffs_ext_tags tags;
int result;
- int alloc_failed = 0;
if (!in || !in->lazy_loaded || in->hdr_chunk < 1)
return;
dev = in->my_dev;
- in->lazy_loaded = 0;
buf = yaffs_get_temp_buffer(dev);
result = yaffs_rd_chunk_tags_nand(dev, in->hdr_chunk, buf, &tags);
+
+ if (result == YAFFS_FAIL)
+ return;
+
oh = (struct yaffs_obj_hdr *)buf;
yaffs_do_endian_oh(dev, oh);
+ in->lazy_loaded = 0;
in->yst_mode = oh->yst_mode;
yaffs_load_attribs(in, oh);
yaffs_set_obj_name_from_oh(in, oh);
- if (in->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) {
+ if (in->variant_type == YAFFS_OBJECT_TYPE_SYMLINK)
in->variant.symlink_variant.alias =
yaffs_clone_str(oh->alias);
- if (!in->variant.symlink_variant.alias)
- alloc_failed = 1; /* Not returned */
- }
yaffs_release_temp_buffer(dev, buf);
}
/* Access the old obj header just to read the name. */
result = yaffs_rd_chunk_tags_nand(dev, prev_chunk_id,
buffer, &old_tags);
-
- yaffs_verify_oh(in, oh, &old_tags, 0);
- memcpy(old_name, oh->name, sizeof(oh->name));
-
- /*
- * NB We only wipe the object header area because the rest of
- * the buffer might contain xattribs.
- */
- memset(oh, 0xff, sizeof(*oh));
+ if (result == YAFFS_OK) {
+ yaffs_verify_oh(in, oh, &old_tags, 0);
+ memcpy(old_name, oh->name, sizeof(oh->name));
+
+ /*
+ * NB We only wipe the object header area because the rest of
+ * the buffer might contain xattribs.
+ */
+ memset(oh, 0xff, sizeof(*oh));
+ }
} else {
memset(buffer, 0xff, dev->data_bytes_per_chunk);
}
* a whole chunk or we're using inband tags then use the cache
* (if there is caching) else bypass the cache.
*/
- if (cache || n_copy != dev->data_bytes_per_chunk ||
+ if (cache || n_copy != (int)dev->data_bytes_per_chunk ||
dev->param.inband_tags) {
if (dev->param.n_caches > 0) {
start >= dev->data_bytes_per_chunk) {
yaffs_trace(YAFFS_TRACE_ERROR,
"AddrToChunk of offset %lld gives chunk %d start %d",
- offset, chunk, start);
+ (long long)offset, chunk, start);
}
chunk++; /* File pos to chunk in file offset */
(start + n)) ? n_bytes_read : (start + n);
if (n_writeback < 0 ||
- n_writeback > dev->data_bytes_per_chunk)
+ n_writeback > (int)dev->data_bytes_per_chunk)
BUG();
} else {
n_writeback = dev->data_bytes_per_chunk;
}
- if (n_copy != dev->data_bytes_per_chunk ||
+ if (n_copy != (int)dev->data_bytes_per_chunk ||
!dev->param.cache_bypass_aligned ||
dev->param.inband_tags) {
/* An incomplete start or end chunk (or maybe both
if (chunk_id < 1)
continue;
- if (chunk_id <
+ if ((u32)chunk_id <
(dev->internal_start_block * dev->param.chunks_per_block) ||
- chunk_id >=
+ (u32)chunk_id >=
((dev->internal_end_block + 1) *
dev->param.chunks_per_block)) {
yaffs_trace(YAFFS_TRACE_ALWAYS,
if (obj->hdr_chunk > 0) {
result = yaffs_rd_chunk_tags_nand(obj->my_dev,
- obj->hdr_chunk,
- buffer, NULL);
+ obj->hdr_chunk, buffer, NULL);
+ if (result == YAFFS_OK)
+ yaffs_load_name_from_oh(obj->my_dev, name,
+ oh->name, buffer_size);
}
- yaffs_load_name_from_oh(obj->my_dev, name, oh->name,
- buffer_size);
-
yaffs_release_temp_buffer(obj->my_dev, buffer);
}
int yaffs_guts_format_dev(struct yaffs_dev *dev)
{
- int i;
+ u32 i;
enum yaffs_block_state state;
u32 dummy;
return YAFFS_OK;
}
+/*
+ * If the dev is mounted r/w then the cleanup will happen during
+ * yaffs_guts_initialise. However if the dev is mounted ro then
+ * the cleanup will be dfered until yaffs is remounted r/w.
+ */
+void yaffs_guts_cleanup(struct yaffs_dev *dev)
+{
+ yaffs_strip_deleted_objs(dev);
+ yaffs_fix_hanging_objs(dev);
+ if (dev->param.empty_lost_n_found)
+ yaffs_empty_l_n_f(dev);
+}
int yaffs_guts_initialise(struct yaffs_dev *dev)
{
int init_failed = 0;
- unsigned x;
- int bits;
+ u32 x;
+ u32 bits;
if(yaffs_guts_ll_init(dev) != YAFFS_OK)
return YAFFS_FAIL;
dev->gc_cleanup_list = NULL;
if (!init_failed && dev->param.n_caches > 0) {
- int i;
+ u32 i;
void *buf;
- int cache_bytes =
+ u32 cache_bytes =
dev->param.n_caches * sizeof(struct yaffs_cache);
if (dev->param.n_caches > YAFFS_MAX_SHORT_OP_CACHES)
init_failed = 1;
}
- yaffs_strip_deleted_objs(dev);
- yaffs_fix_hanging_objs(dev);
- if (dev->param.empty_lost_n_found)
- yaffs_empty_l_n_f(dev);
+ yaffs_guts_cleanup(dev);
}
if (init_failed) {
void yaffs_deinitialise(struct yaffs_dev *dev)
{
if (dev->is_mounted) {
- int i;
+ u32 i;
yaffs_deinit_blocks(dev);
yaffs_deinit_tnodes_and_objs(dev);
int yaffs_count_free_chunks(struct yaffs_dev *dev)
{
int n_free = 0;
- int b;
+ u32 b;
struct yaffs_block_info *blk;
blk = dev->block_info;
int n_free;
int n_dirty_caches;
int blocks_for_checkpt;
- int i;
+ u32 i;
n_free = dev->n_free_chunks;
n_free += dev->n_deleted_files;
loff_t fsize,
int do_endian)
{
- oh->file_size_low = (fsize & 0xFFFFFFFF);
- oh->file_size_high = ((fsize >> 32) & 0xFFFFFFFF);
+ oh->file_size_low = FSIZE_LOW(fsize);
+
+ oh->file_size_high = FSIZE_HIGH(fsize);
if (do_endian) {
yaffs_do_endian_u32(dev, &oh->file_size_low);
yaffs_do_endian_u32 (dev, &low);
yaffs_do_endian_u32 (dev, &high);
}
- retval = (((loff_t) high) << 32) |
- (((loff_t) low) & 0xFFFFFFFF);
+ retval = FSIZE_COMBINE(high, low);
} else {
u32 low = oh->file_size_low;
void yaffs_count_blocks_by_state(struct yaffs_dev *dev, int bs[10])
{
- int i;
+ u32 i;
struct yaffs_block_info *bi;
int s;