Currently, with YAFFS_NEW_PROCFS, "cat /proc/yaffs" always only show one line: ~# cat /proc/yaffs Multi-version YAFFS Fix by rewriting yaffs_proc_show(). Signed-off-by: Jisheng Zhang --- since v2: - remove the buggy "break" yaffs_vfs_multi.c | 394 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 244 insertions(+), 150 deletions(-) diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c index e4edb2c..d2a7a64 100644 --- a/yaffs_vfs_multi.c +++ b/yaffs_vfs_multi.c @@ -3275,149 +3275,6 @@ static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super, static struct proc_dir_entry *my_proc_entry; -static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev) -{ - struct yaffs_param *param = &dev->param; - int bs[10]; - - yaffs_count_blocks_by_state(dev,bs); - - buf += sprintf(buf, "start_block.......... %d\n", param->start_block); - buf += sprintf(buf, "end_block............ %d\n", param->end_block); - buf += sprintf(buf, "total_bytes_per_chunk %d\n", - param->total_bytes_per_chunk); - buf += sprintf(buf, "use_nand_ecc......... %d\n", param->use_nand_ecc); - buf += sprintf(buf, "no_tags_ecc.......... %d\n", param->no_tags_ecc); - buf += sprintf(buf, "is_yaffs2............ %d\n", param->is_yaffs2); - buf += sprintf(buf, "inband_tags.......... %d\n", param->inband_tags); - buf += sprintf(buf, "empty_lost_n_found... %d\n", - param->empty_lost_n_found); - buf += sprintf(buf, "disable_lazy_load.... %d\n", - param->disable_lazy_load); - buf += sprintf(buf, "disable_bad_block_mrk %d\n", - param->disable_bad_block_marking); - buf += sprintf(buf, "refresh_period....... %d\n", - param->refresh_period); - buf += sprintf(buf, "n_caches............. %d\n", param->n_caches); - buf += sprintf(buf, "n_reserved_blocks.... %d\n", - param->n_reserved_blocks); - buf += sprintf(buf, "always_check_erased.. %d\n", - param->always_check_erased); - buf += sprintf(buf, "\n"); - buf += sprintf(buf, "block count by state\n"); - buf += sprintf(buf, "0:%d 1:%d 2:%d 3:%d 4:%d\n", - bs[0], bs[1], bs[2], bs[3], bs[4]); - buf += sprintf(buf, "5:%d 6:%d 7:%d 8:%d 9:%d\n", - bs[5], bs[6], bs[7], bs[8], bs[9]); - - return buf; -} - -static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev) -{ - buf += sprintf(buf, "max file size....... %lld\n", - (long long) yaffs_max_file_size(dev)); - buf += sprintf(buf, "data_bytes_per_chunk. %d\n", - dev->data_bytes_per_chunk); - buf += sprintf(buf, "chunk_grp_bits....... %d\n", dev->chunk_grp_bits); - buf += sprintf(buf, "chunk_grp_size....... %d\n", dev->chunk_grp_size); - buf += sprintf(buf, "n_erased_blocks...... %d\n", dev->n_erased_blocks); - buf += sprintf(buf, "blocks_in_checkpt.... %d\n", - dev->blocks_in_checkpt); - buf += sprintf(buf, "\n"); - buf += sprintf(buf, "n_tnodes............. %d\n", dev->n_tnodes); - buf += sprintf(buf, "n_obj................ %d\n", dev->n_obj); - buf += sprintf(buf, "n_free_chunks........ %d\n", dev->n_free_chunks); - buf += sprintf(buf, "\n"); - buf += sprintf(buf, "n_page_writes........ %u\n", dev->n_page_writes); - buf += sprintf(buf, "n_page_reads......... %u\n", dev->n_page_reads); - buf += sprintf(buf, "n_erasures........... %u\n", dev->n_erasures); - buf += sprintf(buf, "n_gc_copies.......... %u\n", dev->n_gc_copies); - buf += sprintf(buf, "all_gcs.............. %u\n", dev->all_gcs); - buf += sprintf(buf, "passive_gc_count..... %u\n", - dev->passive_gc_count); - buf += sprintf(buf, "oldest_dirty_gc_count %u\n", - dev->oldest_dirty_gc_count); - buf += sprintf(buf, "n_gc_blocks.......... %u\n", dev->n_gc_blocks); - buf += sprintf(buf, "bg_gcs............... %u\n", dev->bg_gcs); - buf += sprintf(buf, "n_retried_writes..... %u\n", - dev->n_retried_writes); - buf += sprintf(buf, "n_retired_blocks..... %u\n", - dev->n_retired_blocks); - buf += sprintf(buf, "n_ecc_fixed.......... %u\n", dev->n_ecc_fixed); - buf += sprintf(buf, "n_ecc_unfixed........ %u\n", dev->n_ecc_unfixed); - buf += sprintf(buf, "n_tags_ecc_fixed..... %u\n", - dev->n_tags_ecc_fixed); - buf += sprintf(buf, "n_tags_ecc_unfixed... %u\n", - dev->n_tags_ecc_unfixed); - buf += sprintf(buf, "cache_hits........... %u\n", dev->cache_hits); - buf += sprintf(buf, "n_deleted_files...... %u\n", dev->n_deleted_files); - buf += sprintf(buf, "n_unlinked_files..... %u\n", - dev->n_unlinked_files); - buf += sprintf(buf, "refresh_count........ %u\n", dev->refresh_count); - buf += sprintf(buf, "n_bg_deletions....... %u\n", dev->n_bg_deletions); - buf += sprintf(buf, "tags_used............ %u\n", dev->tags_used); - buf += sprintf(buf, "summary_used......... %u\n", dev->summary_used); - - return buf; -} - -static int yaffs_proc_read(char *page, - char **start, - off_t offset, int count, int *eof, void *data) -{ - struct list_head *item; - char *buf = page; - int step = offset; - int n = 0; - - /* Get proc_file_read() to step 'offset' by one on each sucessive call. - * We use 'offset' (*ppos) to indicate where we are in dev_list. - * This also assumes the user has posted a read buffer large - * enough to hold the complete output; but that's life in /proc. - */ - - *(int *)start = 1; - - /* Print header first */ - if (step == 0) - buf += - sprintf(buf, "Multi-version YAFFS\n"); - else if (step == 1) - buf += sprintf(buf, "\n"); - else { - step -= 2; - - mutex_lock(&yaffs_context_lock); - - /* Locate and print the Nth entry. Order N-squared but N is small. */ - list_for_each(item, &yaffs_context_list) { - struct yaffs_linux_context *dc = - list_entry(item, struct yaffs_linux_context, - context_list); - struct yaffs_dev *dev = dc->dev; - - if (n < (step & ~1)) { - n += 2; - continue; - } - if ((step & 1) == 0) { - buf += - sprintf(buf, "\nDevice %d \"%s\"\n", n, - dev->param.name); - buf = yaffs_dump_dev_part0(buf, dev); - } else { - buf = yaffs_dump_dev_part1(buf, dev); - } - - break; - } - mutex_unlock(&yaffs_context_lock); - } - - return buf - page < count ? buf - page : count; -} - /** * Set the verbosity of the warnings and error messages. * @@ -3665,15 +3522,112 @@ static struct file_system_to_install fs_to_install[] = { #ifdef YAFFS_NEW_PROCFS +static void yaffs_dump_dev_part0(struct seq_file *m, struct yaffs_dev *dev) +{ + struct yaffs_param *param = &dev->param; + int bs[10]; + + yaffs_count_blocks_by_state(dev,bs); + + seq_printf(m, "start_block.......... %d\n", param->start_block); + seq_printf(m, "end_block............ %d\n", param->end_block); + seq_printf(m, "total_bytes_per_chunk %d\n", + param->total_bytes_per_chunk); + seq_printf(m, "use_nand_ecc......... %d\n", param->use_nand_ecc); + seq_printf(m, "no_tags_ecc.......... %d\n", param->no_tags_ecc); + seq_printf(m, "is_yaffs2............ %d\n", param->is_yaffs2); + seq_printf(m, "inband_tags.......... %d\n", param->inband_tags); + seq_printf(m, "empty_lost_n_found... %d\n", + param->empty_lost_n_found); + seq_printf(m, "disable_lazy_load.... %d\n", + param->disable_lazy_load); + seq_printf(m, "disable_bad_block_mrk %d\n", + param->disable_bad_block_marking); + seq_printf(m, "refresh_period....... %d\n", + param->refresh_period); + seq_printf(m, "n_caches............. %d\n", param->n_caches); + seq_printf(m, "n_reserved_blocks.... %d\n", + param->n_reserved_blocks); + seq_printf(m, "always_check_erased.. %d\n", + param->always_check_erased); + seq_printf(m, "\n"); + seq_printf(m, "block count by state\n"); + seq_printf(m, "0:%d 1:%d 2:%d 3:%d 4:%d\n", + bs[0], bs[1], bs[2], bs[3], bs[4]); + seq_printf(m, "5:%d 6:%d 7:%d 8:%d 9:%d\n", + bs[5], bs[6], bs[7], bs[8], bs[9]); +} + +static void yaffs_dump_dev_part1(struct seq_file *m, struct yaffs_dev *dev) +{ + seq_printf(m, "max file size....... %lld\n", + (long long) yaffs_max_file_size(dev)); + seq_printf(m, "data_bytes_per_chunk. %d\n", + dev->data_bytes_per_chunk); + seq_printf(m, "chunk_grp_bits....... %d\n", dev->chunk_grp_bits); + seq_printf(m, "chunk_grp_size....... %d\n", dev->chunk_grp_size); + seq_printf(m, "n_erased_blocks...... %d\n", dev->n_erased_blocks); + seq_printf(m, "blocks_in_checkpt.... %d\n", + dev->blocks_in_checkpt); + seq_printf(m, "\n"); + seq_printf(m, "n_tnodes............. %d\n", dev->n_tnodes); + seq_printf(m, "n_obj................ %d\n", dev->n_obj); + seq_printf(m, "n_free_chunks........ %d\n", dev->n_free_chunks); + seq_printf(m, "\n"); + seq_printf(m, "n_page_writes........ %u\n", dev->n_page_writes); + seq_printf(m, "n_page_reads......... %u\n", dev->n_page_reads); + seq_printf(m, "n_erasures........... %u\n", dev->n_erasures); + seq_printf(m, "n_gc_copies.......... %u\n", dev->n_gc_copies); + seq_printf(m, "all_gcs.............. %u\n", dev->all_gcs); + seq_printf(m, "passive_gc_count..... %u\n", + dev->passive_gc_count); + seq_printf(m, "oldest_dirty_gc_count %u\n", + dev->oldest_dirty_gc_count); + seq_printf(m, "n_gc_blocks.......... %u\n", dev->n_gc_blocks); + seq_printf(m, "bg_gcs............... %u\n", dev->bg_gcs); + seq_printf(m, "n_retried_writes..... %u\n", + dev->n_retried_writes); + seq_printf(m, "n_retired_blocks..... %u\n", + dev->n_retired_blocks); + seq_printf(m, "n_ecc_fixed.......... %u\n", dev->n_ecc_fixed); + seq_printf(m, "n_ecc_unfixed........ %u\n", dev->n_ecc_unfixed); + seq_printf(m, "n_tags_ecc_fixed..... %u\n", + dev->n_tags_ecc_fixed); + seq_printf(m, "n_tags_ecc_unfixed... %u\n", + dev->n_tags_ecc_unfixed); + seq_printf(m, "cache_hits........... %u\n", dev->cache_hits); + seq_printf(m, "n_deleted_files...... %u\n", dev->n_deleted_files); + seq_printf(m, "n_unlinked_files..... %u\n", + dev->n_unlinked_files); + seq_printf(m, "refresh_count........ %u\n", dev->refresh_count); + seq_printf(m, "n_bg_deletions....... %u\n", dev->n_bg_deletions); + seq_printf(m, "tags_used............ %u\n", dev->tags_used); + seq_printf(m, "summary_used......... %u\n", dev->summary_used); +} + static int yaffs_proc_show(struct seq_file *m, void *v) { - /* FIXME: Unify in a better way? */ - char buffer[512]; - char *start; - int len; + struct list_head *item; + int n = 0; + + seq_puts(m, "Multi-version YAFFS\n\n"); + mutex_lock(&yaffs_context_lock); + + /* Locate and print the Nth entry. Order N-squared but N is small. */ + list_for_each(item, &yaffs_context_list) { + struct yaffs_linux_context *dc = + list_entry(item, struct yaffs_linux_context, + context_list); + struct yaffs_dev *dev = dc->dev; + + seq_printf(m, "\nDevice %d \"%s\"\n", n, + dev->param.name); + yaffs_dump_dev_part0(m, dev); + yaffs_dump_dev_part1(m, dev); + n += 2; + } + mutex_unlock(&yaffs_context_lock); - len = yaffs_proc_read(buffer, &start, 0, sizeof(buffer), NULL, NULL); - seq_puts(m, buffer); return 0; } @@ -3704,9 +3658,149 @@ static int yaffs_procfs_init(void) return -ENOMEM; } } - #else +static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev) +{ + struct yaffs_param *param = &dev->param; + int bs[10]; + + yaffs_count_blocks_by_state(dev,bs); + + buf += sprintf(buf, "start_block.......... %d\n", param->start_block); + buf += sprintf(buf, "end_block............ %d\n", param->end_block); + buf += sprintf(buf, "total_bytes_per_chunk %d\n", + param->total_bytes_per_chunk); + buf += sprintf(buf, "use_nand_ecc......... %d\n", param->use_nand_ecc); + buf += sprintf(buf, "no_tags_ecc.......... %d\n", param->no_tags_ecc); + buf += sprintf(buf, "is_yaffs2............ %d\n", param->is_yaffs2); + buf += sprintf(buf, "inband_tags.......... %d\n", param->inband_tags); + buf += sprintf(buf, "empty_lost_n_found... %d\n", + param->empty_lost_n_found); + buf += sprintf(buf, "disable_lazy_load.... %d\n", + param->disable_lazy_load); + buf += sprintf(buf, "disable_bad_block_mrk %d\n", + param->disable_bad_block_marking); + buf += sprintf(buf, "refresh_period....... %d\n", + param->refresh_period); + buf += sprintf(buf, "n_caches............. %d\n", param->n_caches); + buf += sprintf(buf, "n_reserved_blocks.... %d\n", + param->n_reserved_blocks); + buf += sprintf(buf, "always_check_erased.. %d\n", + param->always_check_erased); + buf += sprintf(buf, "\n"); + buf += sprintf(buf, "block count by state\n"); + buf += sprintf(buf, "0:%d 1:%d 2:%d 3:%d 4:%d\n", + bs[0], bs[1], bs[2], bs[3], bs[4]); + buf += sprintf(buf, "5:%d 6:%d 7:%d 8:%d 9:%d\n", + bs[5], bs[6], bs[7], bs[8], bs[9]); + + return buf; +} + +static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev) +{ + buf += sprintf(buf, "max file size....... %lld\n", + (long long) yaffs_max_file_size(dev)); + buf += sprintf(buf, "data_bytes_per_chunk. %d\n", + dev->data_bytes_per_chunk); + buf += sprintf(buf, "chunk_grp_bits....... %d\n", dev->chunk_grp_bits); + buf += sprintf(buf, "chunk_grp_size....... %d\n", dev->chunk_grp_size); + buf += sprintf(buf, "n_erased_blocks...... %d\n", dev->n_erased_blocks); + buf += sprintf(buf, "blocks_in_checkpt.... %d\n", + dev->blocks_in_checkpt); + buf += sprintf(buf, "\n"); + buf += sprintf(buf, "n_tnodes............. %d\n", dev->n_tnodes); + buf += sprintf(buf, "n_obj................ %d\n", dev->n_obj); + buf += sprintf(buf, "n_free_chunks........ %d\n", dev->n_free_chunks); + buf += sprintf(buf, "\n"); + buf += sprintf(buf, "n_page_writes........ %u\n", dev->n_page_writes); + buf += sprintf(buf, "n_page_reads......... %u\n", dev->n_page_reads); + buf += sprintf(buf, "n_erasures........... %u\n", dev->n_erasures); + buf += sprintf(buf, "n_gc_copies.......... %u\n", dev->n_gc_copies); + buf += sprintf(buf, "all_gcs.............. %u\n", dev->all_gcs); + buf += sprintf(buf, "passive_gc_count..... %u\n", + dev->passive_gc_count); + buf += sprintf(buf, "oldest_dirty_gc_count %u\n", + dev->oldest_dirty_gc_count); + buf += sprintf(buf, "n_gc_blocks.......... %u\n", dev->n_gc_blocks); + buf += sprintf(buf, "bg_gcs............... %u\n", dev->bg_gcs); + buf += sprintf(buf, "n_retried_writes..... %u\n", + dev->n_retried_writes); + buf += sprintf(buf, "n_retired_blocks..... %u\n", + dev->n_retired_blocks); + buf += sprintf(buf, "n_ecc_fixed.......... %u\n", dev->n_ecc_fixed); + buf += sprintf(buf, "n_ecc_unfixed........ %u\n", dev->n_ecc_unfixed); + buf += sprintf(buf, "n_tags_ecc_fixed..... %u\n", + dev->n_tags_ecc_fixed); + buf += sprintf(buf, "n_tags_ecc_unfixed... %u\n", + dev->n_tags_ecc_unfixed); + buf += sprintf(buf, "cache_hits........... %u\n", dev->cache_hits); + buf += sprintf(buf, "n_deleted_files...... %u\n", dev->n_deleted_files); + buf += sprintf(buf, "n_unlinked_files..... %u\n", + dev->n_unlinked_files); + buf += sprintf(buf, "refresh_count........ %u\n", dev->refresh_count); + buf += sprintf(buf, "n_bg_deletions....... %u\n", dev->n_bg_deletions); + buf += sprintf(buf, "tags_used............ %u\n", dev->tags_used); + buf += sprintf(buf, "summary_used......... %u\n", dev->summary_used); + + return buf; +} + +static int yaffs_proc_read(char *page, + char **start, + off_t offset, int count, int *eof, void *data) +{ + struct list_head *item; + char *buf = page; + int step = offset; + int n = 0; + + /* Get proc_file_read() to step 'offset' by one on each sucessive call. + * We use 'offset' (*ppos) to indicate where we are in dev_list. + * This also assumes the user has posted a read buffer large + * enough to hold the complete output; but that's life in /proc. + */ + + *(int *)start = 1; + + /* Print header first */ + if (step == 0) + buf += + sprintf(buf, "Multi-version YAFFS\n"); + else if (step == 1) + buf += sprintf(buf, "\n"); + else { + step -= 2; + + mutex_lock(&yaffs_context_lock); + + /* Locate and print the Nth entry. Order N-squared but N is small. */ + list_for_each(item, &yaffs_context_list) { + struct yaffs_linux_context *dc = + list_entry(item, struct yaffs_linux_context, + context_list); + struct yaffs_dev *dev = dc->dev; + if (n < (step & ~1)) { + n += 2; + continue; + } + if ((step & 1) == 0) { + buf += + sprintf(buf, "\nDevice %d \"%s\"\n", n, + dev->param.name); + buf = yaffs_dump_dev_part0(buf, dev); + } else { + buf = yaffs_dump_dev_part1(buf, dev); + } + + break; + } + mutex_unlock(&yaffs_context_lock); + } + + return buf - page < count ? buf - page : count; +} static int yaffs_procfs_init(void) { -- 1.9.1