X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_packedtags2.c;h=e1d18cc33c683ebc1ba53fc18841b60040b46f84;hp=4873f78ef12c8656dcea8497ea6567a69f8c1d7d;hb=6af811eebaf8da9dbb58be70fbb283ecd95f8a32;hpb=470ba34cc1d593fca7cd98bb9a385a100f7cb3ac;ds=sidebyside diff --git a/yaffs_packedtags2.c b/yaffs_packedtags2.c index 4873f78..e1d18cc 100644 --- a/yaffs_packedtags2.c +++ b/yaffs_packedtags2.c @@ -1,7 +1,7 @@ /* * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. * - * Copyright (C) 2002-2010 Aleph One Ltd. + * Copyright (C) 2002-2011 Aleph One Ltd. * for Toby Churchill Ltd and Brightstar Engineering * * Created by Charles Manning @@ -14,7 +14,6 @@ #include "yaffs_packedtags2.h" #include "yportenv.h" #include "yaffs_trace.h" -#include "yaffs_tagsvalidity.h" /* This code packs a set of extended tags into a binary structure for * NAND storage @@ -32,62 +31,75 @@ #define EXTRA_SHADOWS_FLAG 0x20000000 #define EXTRA_SPARE_FLAGS 0x10000000 -#define ALL_EXTRA_FLAGS 0xF0000000 +#define ALL_EXTRA_FLAGS 0xf0000000 /* Also, the top 4 bits of the object Id are set to the object type. */ #define EXTRA_OBJECT_TYPE_SHIFT (28) -#define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT) +#define EXTRA_OBJECT_TYPE_MASK ((0x0f) << EXTRA_OBJECT_TYPE_SHIFT) - -static void yaffs_dump_packed_tags2_tags_only(const yaffs_packed_tags2_tags_only *ptt) +static void yaffs_dump_packed_tags2_tags_only( + const struct yaffs_packed_tags2_tags_only *ptt) { - T(YAFFS_TRACE_MTD, - (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR), - ptt->obj_id, ptt->chunk_id, ptt->n_bytes, - ptt->seq_number)); + yaffs_trace(YAFFS_TRACE_MTD, + "packed tags obj %d chunk %d byte %d seq %d", + ptt->obj_id, ptt->chunk_id, ptt->n_bytes, ptt->seq_number); } -static void yaffs_dump_packed_tags2(const yaffs_packed_tags2 *pt) + +static void yaffs_dump_packed_tags2(const struct yaffs_packed_tags2 *pt) { yaffs_dump_packed_tags2_tags_only(&pt->t); } -static void yaffs_dump_tags2(const yaffs_ext_tags *t) +static void yaffs_dump_tags2(const struct yaffs_ext_tags *t) { - T(YAFFS_TRACE_MTD, - (TSTR - ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d" - TENDSTR), t->ecc_result, t->block_bad, t->chunk_used, t->obj_id, - t->chunk_id, t->n_bytes, t->is_deleted, t->serial_number, - t->seq_number)); + yaffs_trace(YAFFS_TRACE_MTD, + "ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d", + t->ecc_result, t->block_bad, t->chunk_used, t->obj_id, + t->chunk_id, t->n_bytes, t->is_deleted, t->serial_number, + t->seq_number); } -void yaffs_pack_tags2_tags_only(yaffs_packed_tags2_tags_only *ptt, - const yaffs_ext_tags *t) +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->chunk_id = t->chunk_id; ptt->seq_number = t->seq_number; 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; + ptt->chunk_id = EXTRA_HEADER_INFO_FLAG | t->extra_parent_id; if (t->extra_is_shrink) ptt->chunk_id |= EXTRA_SHRINK_FLAG; if (t->extra_shadows) ptt->chunk_id |= EXTRA_SHADOWS_FLAG; ptt->obj_id &= ~EXTRA_OBJECT_TYPE_MASK; - ptt->obj_id |= - (t->extra_obj_type << EXTRA_OBJECT_TYPE_SHIFT); + ptt->obj_id |= (t->extra_obj_type << EXTRA_OBJECT_TYPE_SHIFT); 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; } @@ -96,98 +108,86 @@ void yaffs_pack_tags2_tags_only(yaffs_packed_tags2_tags_only *ptt, yaffs_dump_tags2(t); } - -void yaffs_pack_tags2(yaffs_packed_tags2 *pt, const yaffs_ext_tags *t, int tags_ecc) +void yaffs_pack_tags2(struct yaffs_packed_tags2 *pt, + const struct yaffs_ext_tags *t, int tags_ecc) { yaffs_pack_tags2_tags_only(&pt->t, t); - if(tags_ecc) + if (tags_ecc) yaffs_ecc_calc_other((unsigned char *)&pt->t, - sizeof(yaffs_packed_tags2_tags_only), - &pt->ecc); + sizeof(struct yaffs_packed_tags2_tags_only), + &pt->ecc); } - -void yaffs_unpack_tags2_tags_only(yaffs_ext_tags *t, - yaffs_packed_tags2_tags_only *ptt) +void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t, + struct yaffs_packed_tags2_tags_only *ptt) { + memset(t, 0, sizeof(struct yaffs_ext_tags)); + + if (ptt->seq_number == 0xffffffff) + return; + + t->block_bad = 0; + t->chunk_used = 1; + t->obj_id = ptt->obj_id; + t->chunk_id = ptt->chunk_id; + t->n_bytes = ptt->n_bytes; + t->is_deleted = 0; + t->serial_number = 0; + t->seq_number = ptt->seq_number; + + /* Do extra header info stuff */ + if (ptt->chunk_id & EXTRA_HEADER_INFO_FLAG) { + t->chunk_id = 0; + t->n_bytes = 0; + + t->extra_available = 1; + t->extra_parent_id = ptt->chunk_id & (~(ALL_EXTRA_FLAGS)); + t->extra_is_shrink = ptt->chunk_id & EXTRA_SHRINK_FLAG ? 1 : 0; + t->extra_shadows = ptt->chunk_id & EXTRA_SHADOWS_FLAG ? 1 : 0; + t->extra_obj_type = ptt->obj_id >> EXTRA_OBJECT_TYPE_SHIFT; + t->obj_id &= ~EXTRA_OBJECT_TYPE_MASK; - memset(t, 0, sizeof(yaffs_ext_tags)); - - yaffs_init_tags(t); - - if (ptt->seq_number != 0xFFFFFFFF) { - t->block_bad = 0; - t->chunk_used = 1; - t->obj_id = ptt->obj_id; - t->chunk_id = ptt->chunk_id; - t->n_bytes = ptt->n_bytes; - t->is_deleted = 0; - t->serial_number = 0; - t->seq_number = ptt->seq_number; - - /* Do extra header info stuff */ - - if (ptt->chunk_id & EXTRA_HEADER_INFO_FLAG) { - t->chunk_id = 0; - t->n_bytes = 0; - - t->extra_available = 1; - t->extra_parent_id = - ptt->chunk_id & (~(ALL_EXTRA_FLAGS)); - t->extra_is_shrink = - (ptt->chunk_id & EXTRA_SHRINK_FLAG) ? 1 : 0; - t->extra_shadows = - (ptt->chunk_id & EXTRA_SHADOWS_FLAG) ? 1 : 0; - t->extra_obj_type = - ptt->obj_id >> EXTRA_OBJECT_TYPE_SHIFT; - t->obj_id &= ~EXTRA_OBJECT_TYPE_MASK; - - if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK) - t->extra_equiv_id = ptt->n_bytes; - else - t->extra_length = ptt->n_bytes; - } + if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK) + t->extra_equiv_id = ptt->n_bytes; + else + t->extra_file_size = ptt->n_bytes; } - yaffs_dump_packed_tags2_tags_only(ptt); yaffs_dump_tags2(t); - } - -void yaffs_unpack_tags2(yaffs_ext_tags *t, yaffs_packed_tags2 *pt, int tags_ecc) +void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt, + int tags_ecc) { + enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_NO_ERROR; - yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_NO_ERROR; - - if (pt->t.seq_number != 0xFFFFFFFF && - tags_ecc){ + if (pt->t.seq_number != 0xffffffff && tags_ecc) { /* Chunk is in use and we need to do ECC */ - - yaffs_ecc_other ecc; + + struct yaffs_ecc_other ecc; int result; yaffs_ecc_calc_other((unsigned char *)&pt->t, - sizeof(yaffs_packed_tags2_tags_only), - &ecc); - result = yaffs_ecc_correct_other((unsigned char *)&pt->t, - sizeof(yaffs_packed_tags2_tags_only), - &pt->ecc, &ecc); + sizeof(struct yaffs_packed_tags2_tags_only), + &ecc); + result = + yaffs_ecc_correct_other((unsigned char *)&pt->t, + sizeof(struct yaffs_packed_tags2_tags_only), + &pt->ecc, &ecc); switch (result) { - case 0: - ecc_result = YAFFS_ECC_RESULT_NO_ERROR; - break; - case 1: - ecc_result = YAFFS_ECC_RESULT_FIXED; - break; - case -1: - ecc_result = YAFFS_ECC_RESULT_UNFIXED; - break; - default: - ecc_result = YAFFS_ECC_RESULT_UNKNOWN; + case 0: + ecc_result = YAFFS_ECC_RESULT_NO_ERROR; + break; + case 1: + ecc_result = YAFFS_ECC_RESULT_FIXED; + break; + case -1: + ecc_result = YAFFS_ECC_RESULT_UNFIXED; + break; + default: + ecc_result = YAFFS_ECC_RESULT_UNKNOWN; } } - yaffs_unpack_tags2_tags_only(t, &pt->t); t->ecc_result = ecc_result; @@ -195,4 +195,3 @@ void yaffs_unpack_tags2(yaffs_ext_tags *t, yaffs_packed_tags2 *pt, int tags_ecc) yaffs_dump_packed_tags2(pt); yaffs_dump_tags2(t); } -