diff options
Diffstat (limited to 'target/linux/generic/files')
5 files changed, 75 insertions, 42 deletions
diff --git a/target/linux/generic/files/fs/yaffs2/NOTE.openwrt b/target/linux/generic/files/fs/yaffs2/NOTE.openwrt index ad807bdc09..e84fbe6fc6 100644 --- a/target/linux/generic/files/fs/yaffs2/NOTE.openwrt +++ b/target/linux/generic/files/fs/yaffs2/NOTE.openwrt @@ -1,4 +1,4 @@ The yaffs2 source has been fetched from the yaffs2 GIT tree. URL: git://www.aleph1.co.uk/yaffs2 -Version: 7e5cf0fa1b694f835cdc184a8395b229fa29f9ae (2014-08-07) +Version: 583dbd9cc2668870cb013f051ba59f7d3e513dae (2015-06-02) diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.c b/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.c index e739fb4a10..16ee1e0695 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.c @@ -237,8 +237,9 @@ int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing) dev->blocks_in_checkpt = 0; dev->checkpt_max_blocks = (dev->internal_end_block - dev->internal_start_block) / 16 + 2; - dev->checkpt_block_list = - kmalloc(sizeof(int) * dev->checkpt_max_blocks, GFP_NOFS); + if (!dev->checkpt_block_list) + dev->checkpt_block_list = + kmalloc(sizeof(int) * dev->checkpt_max_blocks, GFP_NOFS); if (!dev->checkpt_block_list) return 0; @@ -348,7 +349,6 @@ int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes) int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes) { int i = 0; - int ok = 1; struct yaffs_ext_tags tags; int chunk; int offset_chunk; @@ -360,7 +360,7 @@ int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes) if (dev->checkpt_open_write) return -1; - while (i < n_bytes && ok) { + while (i < n_bytes) { if (dev->checkpt_byte_offs < 0 || dev->checkpt_byte_offs >= dev->data_bytes_per_chunk) { @@ -370,10 +370,9 @@ int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes) dev->checkpt_cur_chunk = 0; } - if (dev->checkpt_cur_block < 0) { - ok = 0; + /* Bail out if we can't find a checpoint block */ + if (dev->checkpt_cur_block < 0) break; - } chunk = dev->checkpt_cur_block * dev->param.chunks_per_block + @@ -382,22 +381,21 @@ int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes) offset_chunk = apply_chunk_offset(dev, chunk); dev->n_page_reads++; - /* read in the next chunk */ + /* Read in the next chunk */ dev->tagger.read_chunk_tags_fn(dev, offset_chunk, dev->checkpt_buffer, &tags); + /* Bail out if the chunk is corrupted. */ if (tags.chunk_id != (dev->checkpt_page_seq + 1) || tags.ecc_result > YAFFS_ECC_RESULT_FIXED || - tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA) { - ok = 0; + tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA) break; - } - if(!yaffs2_checkpt_check_chunk_hdr(dev)) { - ok = 0; + + /* Bail out if it is not a checkpoint chunk. */ + if(!yaffs2_checkpt_check_chunk_hdr(dev)) break; - } dev->checkpt_page_seq++; dev->checkpt_cur_chunk++; @@ -417,7 +415,7 @@ int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes) dev->checkpt_byte_count++; } - return i; + return i; /* Number of bytes read */ } int yaffs_checkpt_close(struct yaffs_dev *dev) @@ -441,8 +439,6 @@ int yaffs_checkpt_close(struct yaffs_dev *dev) if (bi && bi->block_state == YAFFS_BLOCK_STATE_EMPTY) bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT; } - kfree(dev->checkpt_block_list); - dev->checkpt_block_list = NULL; } dev->n_free_chunks -= @@ -452,14 +448,10 @@ int yaffs_checkpt_close(struct yaffs_dev *dev) yaffs_trace(YAFFS_TRACE_CHECKPOINT, "checkpoint byte count %d", dev->checkpt_byte_count); - if (dev->checkpt_buffer) { - /* free the buffer */ - kfree(dev->checkpt_buffer); - dev->checkpt_buffer = NULL; + if (dev->checkpt_buffer) return 1; - } else { + else return 0; - } } int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev) diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_guts.c b/target/linux/generic/files/fs/yaffs2/yaffs_guts.c index 1c0ae71320..89fb2a9bba 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_guts.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_guts.c @@ -1922,21 +1922,18 @@ static int yaffs_new_obj_id(struct yaffs_dev *dev) struct list_head *i; u32 n = (u32) bucket; - /* Now find an object value that has not already been taken - * by scanning the list. + /* + * Now find an object value that has not already been taken + * by scanning the list, incrementing each time by number of buckets. */ - while (!found) { found = 1; n += YAFFS_NOBJECT_BUCKETS; - if (1 || dev->obj_bucket[bucket].count > 0) { - list_for_each(i, &dev->obj_bucket[bucket].list) { - /* If there is already one in the list */ - if (i && list_entry(i, struct yaffs_obj, - hash_link)->obj_id == n) { - found = 0; - } - } + list_for_each(i, &dev->obj_bucket[bucket].list) { + /* Check if this value is already taken. */ + if (i && list_entry(i, struct yaffs_obj, + hash_link)->obj_id == n) + found = 0; } } return n; @@ -5022,8 +5019,15 @@ void yaffs_deinitialise(struct yaffs_dev *dev) kfree(dev->gc_cleanup_list); - for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { kfree(dev->temp_buffer[i].buffer); + dev->temp_buffer[i].buffer = NULL; + } + + kfree(dev->checkpt_buffer); + dev->checkpt_buffer = NULL; + kfree(dev->checkpt_block_list); + dev->checkpt_block_list = NULL; dev->is_mounted = 0; diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c b/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c index 76bc1db59f..6540434371 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c @@ -738,7 +738,7 @@ static int yaffs_file_flush(struct file *file) yaffs_gross_lock(dev); - yaffs_flush_file(obj, 1, 0); + yaffs_flush_file(obj, 1, 0, 0); yaffs_gross_unlock(dev); @@ -768,7 +768,7 @@ static int yaffs_sync_object(struct file *file, struct dentry *dentry, yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, "yaffs_sync_object"); yaffs_gross_lock(dev); - yaffs_flush_file(obj, 1, datasync); + yaffs_flush_file(obj, 1, datasync, 0); yaffs_gross_unlock(dev); return 0; } @@ -2187,7 +2187,7 @@ static void yaffs_flush_inodes(struct super_block *sb) yaffs_trace(YAFFS_TRACE_OS, "flushing obj %d", obj->obj_id); - yaffs_flush_file(obj, 1, 0); + yaffs_flush_file(obj, 1, 0, 0); } } } @@ -2200,7 +2200,7 @@ static void yaffs_flush_super(struct super_block *sb, int do_checkpoint) yaffs_flush_inodes(sb); yaffs_update_dirty_dirs(dev); - yaffs_flush_whole_cache(dev); + yaffs_flush_whole_cache(dev, 1); if (do_checkpoint) yaffs_checkpoint_save(dev); } @@ -2579,7 +2579,45 @@ static int yaffs_sync_fs(struct super_block *sb) return 0; } +/* the function only is used to change dev->read_only when this file system + * is remounted. + */ +static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) +{ + int read_only = 0; + struct mtd_info *mtd; + struct yaffs_dev *dev = 0; + /* Get the device */ + mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); + if (!mtd) { + yaffs_trace(YAFFS_TRACE_ALWAYS, + "MTD device #%u doesn't appear to exist", + MINOR(sb->s_dev)); + return 1; + } + + /* Check it's NAND */ + if (mtd->type != MTD_NANDFLASH) { + yaffs_trace(YAFFS_TRACE_ALWAYS, + "MTD device is not NAND it's type %d", + mtd->type); + return 1; + } + + read_only = ((*flags & MS_RDONLY) != 0); + if (!read_only && !(mtd->flags & MTD_WRITEABLE)) { + read_only = 1; + printk(KERN_INFO + "yaffs: mtd is read only, setting superblock read only"); + *flags |= MS_RDONLY; + } + + dev = sb->s_fs_info; + dev->read_only = read_only; + + return 0; +} static const struct super_operations yaffs_super_ops = { .statfs = yaffs_statfs, @@ -2601,6 +2639,7 @@ static const struct super_operations yaffs_super_ops = { #ifdef YAFFS_HAS_WRITE_SUPER .write_super = yaffs_write_super, #endif + .remount_fs = yaffs_remount_fs, }; struct yaffs_options { diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c b/target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c index 8c31a661ff..9fb7c944ca 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c @@ -1351,7 +1351,6 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev) int n_to_scan = 0; enum yaffs_block_state state; int c; - int deleted; LIST_HEAD(hard_list); struct yaffs_block_info *bi; u32 seq_number; @@ -1469,7 +1468,6 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev) /* get the block to scan in the correct order */ blk = block_index[block_iter].block; bi = yaffs_get_block_info(dev, blk); - deleted = 0; summary_available = yaffs_summary_read(dev, dev->sum_tags, blk); |