/* 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);
}
} else {
#else
+ dev = dev;
{
#endif
strncpy(name, oh_name, buff_size - 1);
}
} else {
#else
+ dev = dev;
{
#endif
strncpy(oh_name, name, YAFFS_MAX_NAME_LENGTH - 1);
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"));
/* 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;
/* 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;
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);
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);
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 = (((loff_t) oh->file_size_high) << 32) |
+ (((loff_t) oh->file_size_low) & 0xFFFFFFFF);
+ return retval;
+}
*/
#define YAFFS_MAGIC 0x5941ff53
+/*
+ * Tnodes form a tree with the tnodes in "levels"
+ * Levels greater than 0 hold 8 slots which point to other tnodes.
+ * Those at level 0 hold 16 slots which point to chunks in NAND.
+ *
+ * A maximum level of 8 thust supports files of size up to:
+ *
+ * 2^(3*MAX_LEVEL+4)
+ *
+ * Thus a max level of 8 supports files with up to 2^^28 chunks which gives
+ * a maximum file size of arounf 51Gbytees with 2k chunks.
+ */
#define YAFFS_NTNODES_LEVEL0 16
#define YAFFS_TNODES_LEVEL0_BITS 4
#define YAFFS_TNODES_LEVEL0_MASK 0xf
#define YAFFS_NTNODES_INTERNAL (YAFFS_NTNODES_LEVEL0 / 2)
#define YAFFS_TNODES_INTERNAL_BITS (YAFFS_TNODES_LEVEL0_BITS - 1)
#define YAFFS_TNODES_INTERNAL_MASK 0x7
-#define YAFFS_TNODES_MAX_LEVEL 6
+#define YAFFS_TNODES_MAX_LEVEL 8
/* Constants for YAFFS1 mode */
#define YAFFS_OBJECT_SPACE 0x40000
#define YAFFS_MAX_OBJECT_ID (YAFFS_OBJECT_SPACE - 1)
-#define YAFFS_CHECKPOINT_VERSION 4
+#define YAFFS_CHECKPOINT_VERSION 5
#ifdef CONFIG_YAFFS_UNICODE
#define YAFFS_MAX_NAME_LENGTH 127
enum yaffs_obj_type extra_obj_type; /* What object type? */
- unsigned extra_length; /* Length if it is a file */
+ loff_t extra_file_size; /* Length if it is a file */
unsigned extra_equiv_id; /* Equivalent object for a hard link */
};
u32 yst_ctime;
/* File size applies to files only */
- int file_size;
+ u32 file_size_low;
/* Equivalent object id applies to hard links only. */
int equiv_id;
u32 inband_shadowed_obj_id;
u32 inband_is_shrink;
- u32 reserved[2];
+ u32 file_size_high;
+ u32 reserved[1];
int shadows_obj; /* This object header shadows the
specified object if > 0 */
*/
struct yaffs_file_var {
- u32 file_size;
- u32 scanned_size;
- u32 shrink_size;
+ loff_t file_size;
+ loff_t scanned_size;
+ loff_t shrink_size;
int top_level;
struct yaffs_tnode *top;
};
u8 unlink_allowed:1;
u8 serial;
int n_data_chunks;
- u32 size_or_equiv_obj;
+ loff_t size_or_equiv_obj;
};
/*--------------------- Temporary buffers ----------------
int yaffs_del_obj(struct yaffs_obj *obj);
int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR * name, int buffer_size);
-int yaffs_get_obj_length(struct yaffs_obj *obj);
+loff_t yaffs_get_obj_length(struct yaffs_obj *obj);
int yaffs_get_obj_inode(struct yaffs_obj *obj);
unsigned yaffs_get_obj_type(struct yaffs_obj *obj);
int yaffs_get_obj_link_count(struct yaffs_obj *obj);
unsigned pos);
int yaffs_is_non_empty_dir(struct yaffs_obj *obj);
+
+/*\
+ * 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);
+loff_t yaffs_oh_to_size(struct yaffs_obj_hdr *oh);
+
#endif
}
+static int yaffs_check_tags_extra_packable(const struct yaffs_ext_tags *t)
+{
+ if(t->chunk_id != 0 || !t->extra_available)
+ return 0;
+
+ /* Check if the file size is too long to store */
+ if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE &&
+ (t->extra_file_size>> 31) != 0)
+ return 0;
+ return 1;
+}
+
void yaffs_pack_tags2_tags_only(struct yaffs_packed_tags2_tags_only *ptt,
const struct yaffs_ext_tags *t)
{
ptt->n_bytes = t->n_bytes;
ptt->obj_id = t->obj_id;
- if (t->chunk_id == 0 && t->extra_available) {
+ /* Only store extra tags for object headers.
+ * If it is a file then only store if the file size is short\
+ * enough to fit.
+ */
+ if (yaffs_check_tags_extra_packable(t)) {
/* Store the extra header info instead */
/* We save the parent object in the chunk_id */
ptt->chunk_id = EXTRA_HEADER_INFO_FLAG | t->extra_parent_id;
if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK)
ptt->n_bytes = t->extra_equiv_id;
else if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE)
- ptt->n_bytes = t->extra_length;
+ ptt->n_bytes = (unsigned) t->extra_file_size;
else
ptt->n_bytes = 0;
}
if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK)
t->extra_equiv_id = ptt->n_bytes;
else
- t->extra_length = ptt->n_bytes;
+ t->extra_file_size = ptt->n_bytes;
}
yaffs_dump_packed_tags2_tags_only(ptt);
yaffs_dump_tags2(t);
case YAFFS_OBJECT_TYPE_FILE:
if (dev->param.
use_header_file_size)
-
- in->variant.
- file_variant.file_size
- = oh->file_size;
-
+ in->variant.
+ file_variant.file_size
+ = yaffs_oh_to_size(oh);
break;
case YAFFS_OBJECT_TYPE_HARDLINK:
in->variant.
if (local_buffer) {
/* fill hole with zero bytes */
- int pos = old_file_size;
+ loff_t pos = old_file_size;
int this_write;
int written;
memset(local_buffer, 0, dev->data_bytes_per_chunk);
struct yaffs_obj *in;
struct yaffs_obj *parent;
int equiv_id;
- int file_size;
+ loff_t file_size;
int is_shrink;
int is_unlinked;
struct yaffs_ext_tags tags;
dev->n_free_chunks++;
} else if (tags.chunk_id > 0) {
/* chunk_id > 0 so it is a data chunk... */
- unsigned int endpos;
- u32 chunk_base = (tags.chunk_id - 1) *
+ loff_t endpos;
+ loff_t chunk_base = (tags.chunk_id - 1) *
dev->data_bytes_per_chunk;
*found_chunks = 1;
(tags.extra_available &&
tags.extra_obj_type == YAFFS_OBJECT_TYPE_FILE)
)) {
- u32 this_size = (oh) ?
- oh->file_size :
- tags.extra_length;
+ loff_t this_size = (oh) ?
+ yaffs_oh_to_size(oh) :
+ tags.extra_file_size;
u32 parent_obj_id = (oh) ?
oh->parent_obj_id :
tags.extra_parent_id;
parent = yaffs_find_or_create_by_number(dev,
oh->parent_obj_id,
YAFFS_OBJECT_TYPE_DIRECTORY);
- file_size = oh->file_size;
+ file_size = yaffs_oh_to_size(oh);
is_shrink = oh->is_shrink;
equiv_id = oh->equiv_id;
} else {
parent = yaffs_find_or_create_by_number(dev,
tags.extra_parent_id,
YAFFS_OBJECT_TYPE_DIRECTORY);
- file_size = tags.extra_length;
+ file_size = tags.extra_file_size;
is_shrink = tags.extra_is_shrink;
equiv_id = tags.extra_equiv_id;
in->lazy_loaded = 1;