X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=df6cb001995f0cdc1d7364c9d5b51221dd274008;hp=d72aa5ba9e5a59c1c3722664fccd881b7694d3c1;hb=d9cae0a277c62c660e4802d3b8745500583273da;hpb=15af6e2cb583775682c96af704505bd7440a8551 diff --git a/yaffs_guts.c b/yaffs_guts.c index d72aa5b..df6cb00 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -44,8 +44,8 @@ static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk, /* Function to calculate chunk and offset */ -static inline void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr, - int *chunk_out, u32 *offset_out) +void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr, + int *chunk_out, u32 *offset_out) { int chunk; u32 offset; @@ -177,7 +177,8 @@ void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer) if (buffer) { /* assume it is an unmanaged one. */ - yaffs_trace(YAFFS_TRACE_BUFFERS, "Releasing unmanaged temp buffer"); + yaffs_trace(YAFFS_TRACE_BUFFERS, + "Releasing unmanaged temp buffer"); kfree(buffer); dev->unmanaged_buffer_deallocs++; } @@ -280,7 +281,8 @@ static void yaffs_handle_chunk_wr_error(struct yaffs_dev *dev, int nand_chunk, static inline int yaffs_hash_fn(int n) { - n = abs(n); + if (n < 0) + n = -n; return n % YAFFS_NOBJECT_BUCKETS; } @@ -598,7 +600,7 @@ static int yaffs_write_new_chunk(struct yaffs_dev *dev, yaffs_trace(YAFFS_TRACE_ERROR, "**>> yaffs write required %d attempts", attempts); - dev->n_retired_writes += (attempts - 1); + dev->n_retried_writes += (attempts - 1); } return chunk; @@ -696,6 +698,11 @@ void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj, #endif } +loff_t yaffs_max_file_size(struct yaffs_dev *dev) +{ + return ((loff_t) YAFFS_MAX_CHUNK_ID) * dev->data_bytes_per_chunk; +} + /*-------------------- TNODES ------------------- * List of spare tnodes @@ -1953,7 +1960,8 @@ struct yaffs_obj *yaffs_new_obj(struct yaffs_dev *dev, int number, case YAFFS_OBJECT_TYPE_FILE: the_obj->variant.file_variant.file_size = 0; the_obj->variant.file_variant.scanned_size = 0; - the_obj->variant.file_variant.shrink_size = ~0; /* max */ + the_obj->variant.file_variant.shrink_size = + yaffs_max_file_size(dev); the_obj->variant.file_variant.top_level = 0; the_obj->variant.file_variant.top = tn; break; @@ -2381,7 +2389,7 @@ void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no) bi->has_shrink_hdr = 0; bi->skip_erased_check = 1; /* Clean, so no need to check */ bi->gc_prioritise = 0; - bi->has_summary=0; + bi->has_summary = 0; yaffs_clear_chunk_bits(dev, block_no); @@ -2496,9 +2504,10 @@ static inline int yaffs_gc_process_chunk(struct yaffs_dev *dev, /* Update file size */ if (object->variant_type == YAFFS_OBJECT_TYPE_FILE) { - oh->file_size = + yaffs_oh_size_load(oh, + object->variant.file_variant.file_size); + tags.extra_file_size = object->variant.file_variant.file_size; - tags.extra_length = oh->file_size; } yaffs_verify_oh(object, oh, &tags, 1); @@ -3214,6 +3223,7 @@ static void yaffs_load_name_from_oh(struct yaffs_dev *dev, YCHAR *name, } } else { #else + dev = dev; { #endif strncpy(name, oh_name, buff_size - 1); @@ -3257,6 +3267,7 @@ static void yaffs_load_oh_from_name(struct yaffs_dev *dev, YCHAR *oh_name, } } else { #else + dev = dev; { #endif strncpy(oh_name, name, YAFFS_MAX_NAME_LENGTH - 1); @@ -3282,6 +3293,7 @@ int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force, u8 *buffer = NULL; YCHAR old_name[YAFFS_MAX_NAME_LENGTH + 1]; struct yaffs_obj_hdr *oh = NULL; + loff_t file_size = 0; strcpy(old_name, _Y("silly old name")); @@ -3334,10 +3346,10 @@ int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force, /* Should not happen */ break; case YAFFS_OBJECT_TYPE_FILE: - oh->file_size = - (oh->parent_obj_id == YAFFS_OBJECTID_DELETED || - oh->parent_obj_id == YAFFS_OBJECTID_UNLINKED) ? - 0 : in->variant.file_variant.file_size; + if (oh->parent_obj_id != YAFFS_OBJECTID_DELETED && + oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED) + file_size = in->variant.file_variant.file_size; + yaffs_oh_size_load(oh, file_size); break; case YAFFS_OBJECT_TYPE_HARDLINK: oh->equiv_id = in->variant.hardlink_variant.equiv_id; @@ -3371,7 +3383,7 @@ int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force, /* Add extra info for file header */ new_tags.extra_available = 1; new_tags.extra_parent_id = oh->parent_obj_id; - new_tags.extra_length = oh->file_size; + new_tags.extra_file_size = file_size; new_tags.extra_is_shrink = oh->is_shrink; new_tags.extra_equiv_id = oh->equiv_id; new_tags.extra_shadows = (oh->shadows_obj > 0) ? 1 : 0; @@ -3500,7 +3512,7 @@ int yaffs_file_rd(struct yaffs_obj *in, u8 * buffer, loff_t offset, int n_bytes) } int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, - int n_bytes, int write_trhrough) + int n_bytes, int write_through) { int chunk; @@ -3509,10 +3521,10 @@ int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, int n = n_bytes; int n_done = 0; int n_writeback; - int start_write = offset; + loff_t start_write = offset; int chunk_written = 0; u32 n_bytes_read; - u32 chunk_start; + loff_t chunk_start; struct yaffs_dev *dev; dev = in->my_dev; @@ -3520,11 +3532,12 @@ int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, while (n > 0 && chunk_written >= 0) { yaffs_addr_to_chunk(dev, offset, &chunk, &start); - if (chunk * dev->data_bytes_per_chunk + start != offset || + if (((loff_t)chunk) * + dev->data_bytes_per_chunk + start != offset || start >= dev->data_bytes_per_chunk) { yaffs_trace(YAFFS_TRACE_ERROR, - "AddrToChunk of offset %d gives chunk %d start %d", - (int)offset, chunk, start); + "AddrToChunk of offset %lld gives chunk %d start %d", + offset, chunk, start); } chunk++; /* File pos to chunk in file offset */ @@ -3541,7 +3554,8 @@ int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, * before. */ - chunk_start = ((chunk - 1) * dev->data_bytes_per_chunk); + chunk_start = (((loff_t)(chunk - 1)) * + dev->data_bytes_per_chunk); if (chunk_start > in->variant.file_variant.file_size) n_bytes_read = 0; /* Past end of file */ @@ -3609,7 +3623,7 @@ int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, cache->locked = 0; cache->n_bytes = n_writeback; - if (write_trhrough) { + if (write_through) { chunk_written = yaffs_wr_data_obj (cache->object, @@ -3669,25 +3683,34 @@ int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, } int yaffs_wr_file(struct yaffs_obj *in, const u8 *buffer, loff_t offset, - int n_bytes, int write_trhrough) + int n_bytes, int write_through) { yaffs2_handle_hole(in, offset); - return yaffs_do_file_wr(in, buffer, offset, n_bytes, write_trhrough); + return yaffs_do_file_wr(in, buffer, offset, n_bytes, write_through); } /* ---------------------- File resizing stuff ------------------ */ -static void yaffs_prune_chunks(struct yaffs_obj *in, int new_size) +static void yaffs_prune_chunks(struct yaffs_obj *in, loff_t new_size) { struct yaffs_dev *dev = in->my_dev; - int old_size = in->variant.file_variant.file_size; + loff_t old_size = in->variant.file_variant.file_size; int i; int chunk_id; - int last_del = 1 + (old_size - 1) / dev->data_bytes_per_chunk; - int start_del = 1 + (new_size + dev->data_bytes_per_chunk - 1) / - dev->data_bytes_per_chunk; + u32 dummy; + int last_del; + int start_del; + if (old_size > 0) + yaffs_addr_to_chunk(dev, old_size - 1, &last_del, &dummy); + else + last_del = 0; + + yaffs_addr_to_chunk(dev, new_size + dev->data_bytes_per_chunk - 1, + &start_del, &dummy); + last_del++; + start_del++; /* Delete backwards so that we don't end up with holes if * power is lost part-way through the operation. @@ -3751,7 +3774,7 @@ void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size) int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size) { struct yaffs_dev *dev = in->my_dev; - int old_size = in->variant.file_variant.file_size; + loff_t old_size = in->variant.file_variant.file_size; yaffs_flush_file_cache(in); yaffs_invalidate_whole_cache(in); @@ -4351,7 +4374,7 @@ struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *directory, */ yaffs_get_obj_name(l, buffer, YAFFS_MAX_NAME_LENGTH + 1); - if (strncmp(name, buffer, YAFFS_MAX_NAME_LENGTH) == 0) + if (!strncmp(name, buffer, YAFFS_MAX_NAME_LENGTH)) return l; } } @@ -4444,7 +4467,7 @@ int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR *name, int buffer_size) return strnlen(name, YAFFS_MAX_NAME_LENGTH); } -int yaffs_get_obj_length(struct yaffs_obj *obj) +loff_t yaffs_get_obj_length(struct yaffs_obj *obj) { /* Dereference any hard linking */ obj = yaffs_get_equivalent_obj(obj); @@ -4811,7 +4834,7 @@ int yaffs_guts_initialise(struct yaffs_dev *dev) if (!init_failed && !yaffs_create_initial_dir(dev)) init_failed = 1; - if(!init_failed && dev->param.is_yaffs2 && + if (!init_failed && dev->param.is_yaffs2 && !dev->param.disable_summary && !yaffs_summary_init(dev)) init_failed = 1; @@ -4878,7 +4901,7 @@ int yaffs_guts_initialise(struct yaffs_dev *dev) dev->n_page_writes = 0; dev->n_erasures = 0; dev->n_gc_copies = 0; - dev->n_retired_writes = 0; + dev->n_retried_writes = 0; dev->n_retired_blocks = 0; @@ -4984,3 +5007,26 @@ int yaffs_get_n_free_chunks(struct yaffs_dev *dev) return n_free; } + +/*\ + * Marshalling functions to get loff_t file sizes into aand out of + * object headers. + */ +void yaffs_oh_size_load(struct yaffs_obj_hdr *oh, loff_t fsize) +{ + oh->file_size_low = (fsize & 0xFFFFFFFF); + oh->file_size_high = ((fsize >> 32) & 0xFFFFFFFF); +} + +loff_t yaffs_oh_to_size(struct yaffs_obj_hdr *oh) +{ + loff_t retval; + + if (~(oh->file_size_high)) + retval = (((loff_t) oh->file_size_high) << 32) | + (((loff_t) oh->file_size_low) & 0xFFFFFFFF); + else + retval = (loff_t) oh->file_size_low; + + return retval; +}