X-Git-Url: https://yaffs.net/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_vfs_single.c;h=1abbfd859a4217767a90d6af13d9a9862a091e19;hp=d8379d45964aa2f8dc8a82bc0e2c83c52386bcaa;hb=b4ce1bb1b46accb1619dc07164ef6945feded9db;hpb=ce0a5fb9849b6dc0d1347709b28d3a34eefec662 diff --git a/yaffs_vfs_single.c b/yaffs_vfs_single.c index d8379d4..1abbfd8 100644 --- a/yaffs_vfs_single.c +++ b/yaffs_vfs_single.c @@ -1,8 +1,7 @@ /* * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. * - * Copyright (C) 2002-2011 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering + * Copyright (C) 2002-2018 Aleph One Ltd. * * Created by Charles Manning * Acknowledgements: @@ -436,7 +435,8 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry) return -ENOTEMPTY; } -static int yaffs_sync_object(struct file *file, loff_t start, loff_t end, int datasync) +static int yaffs_sync_object(struct file *file, + loff_t start, loff_t end, int datasync) { struct yaffs_obj *obj; @@ -449,7 +449,7 @@ static int yaffs_sync_object(struct file *file, loff_t start, loff_t end, int da 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; } @@ -889,7 +889,7 @@ static int yaffs_file_flush(struct file *file, fl_owner_t id) yaffs_gross_lock(dev); - yaffs_flush_file(obj, 1, 0); + yaffs_flush_file(obj, 1, 0, 0); yaffs_gross_unlock(dev); @@ -1097,12 +1097,14 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg) unsigned char *pg_buf; int ret; struct yaffs_dev *dev; + loff_t pos = ((loff_t) pg->index) << PAGE_CACHE_SHIFT; yaffs_trace(YAFFS_TRACE_OS, - "yaffs_readpage_nolock at %08x, size %08x", - (unsigned)(pg->index << PAGE_CACHE_SHIFT), + "yaffs_readpage_nolock at %lld, size %08x", + (long long)pos, (unsigned)PAGE_CACHE_SIZE); + obj = yaffs_dentry_to_obj(f->f_dentry); dev = obj->my_dev; @@ -1114,8 +1116,7 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg) yaffs_gross_lock(dev); - ret = yaffs_file_rd(obj, pg_buf, - pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE); + ret = yaffs_file_rd(obj, pg_buf, pos, PAGE_CACHE_SIZE); yaffs_gross_unlock(dev); @@ -1218,7 +1219,8 @@ static int yaffs_writepage(struct page *page, struct writeback_control *wbc) (int)obj->variant.file_variant.file_size, (int)inode->i_size); n_written = yaffs_wr_file(obj, buffer, - page->index << PAGE_CACHE_SHIFT, n_bytes, 0); + ((loff_t)page->index) << PAGE_CACHE_SHIFT, + n_bytes, 0); yaffs_touch_super(dev); @@ -1487,15 +1489,34 @@ static void yaffs_flush_inodes(struct super_block *sb) { struct inode *iptr; struct yaffs_obj *obj; + struct yaffs_dev *dev = yaffs_super_to_dev(sb); + spin_lock(&sb->s_inode_list_lock); list_for_each_entry(iptr, &sb->s_inodes, i_sb_list) { + spin_lock(&inode->i_lock); + if (iptr->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) { + spin_unlock(&inode->i_lock); + continue; + } + + __iget(iptr); + spin_unlock(&inode->i_lock); + spin_unlock(&sb->s_inode_list_lock); + obj = yaffs_inode_to_obj(iptr); if (obj) { yaffs_trace(YAFFS_TRACE_OS, "flushing obj %d", obj->obj_id); - yaffs_flush_file(obj, 1, 0); + yaffs_flush_file(obj, 1, 0, 0); } + + yaffs_gross_unlock(dev); + iput(iptr); + yaffs_gross_lock(dev); + + spin_lock(&sb->s_inode_list_lock); } + spin_unlock(&sb->s_inode_list_lock); } static void yaffs_flush_super(struct super_block *sb, int do_checkpoint) @@ -1507,7 +1528,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); } @@ -1909,6 +1930,7 @@ static void yaffs_fill_inode_from_obj(struct inode *inode, static void yaffs_put_super(struct super_block *sb) { struct yaffs_dev *dev = yaffs_super_to_dev(sb); + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); yaffs_trace(YAFFS_TRACE_OS, "yaffs_put_super"); @@ -1938,24 +1960,62 @@ static void yaffs_put_super(struct super_block *sb) } kfree(dev); + + if (mtd && mtd->sync) + mtd->sync(mtd); + + if (mtd) + put_mtd_device(mtd); } -static void yaffs_mtd_put_super(struct super_block *sb) +/* 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) { - struct mtd_info *mtd = yaffs_dev_to_mtd(yaffs_super_to_dev(sb)); + int read_only = 0; + struct mtd_info *mtd; + struct yaffs_dev *dev = 0; - if (mtd->sync) - mtd->sync(mtd); + /* 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; + } - put_mtd_device(mtd); + 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, .put_super = yaffs_put_super, .evict_inode = yaffs_evict_inode, .sync_fs = yaffs_sync_fs, .write_super = yaffs_write_super, + .remount_fs = yaffs_remount_fs, }; static struct super_block *yaffs_internal_read_super(int yaffs_version, @@ -2031,7 +2091,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, /* Get the device */ mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); - if (!mtd) { + if (IS_ERR(mtd)) { yaffs_trace(YAFFS_TRACE_ALWAYS, "MTD device #%u doesn't appear to exist", MINOR(sb->s_dev)); @@ -2125,9 +2185,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, kfree(context); dev = NULL; context = NULL; - } - if (!dev) { /* Deep shit could not allocate device structure */ yaffs_trace(YAFFS_TRACE_ALWAYS, "yaffs_read_super failed trying to allocate yaffs_dev"); @@ -2210,7 +2268,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, yaffs_dev_to_lc(dev)->put_super_fn = yaffs_mtd_put_super; param->sb_dirty_fn = yaffs_touch_super; - param->gc_control = yaffs_gc_control_callback; + param->gc_control_fn = yaffs_gc_control_callback; yaffs_dev_to_lc(dev)->super = sb; @@ -2257,6 +2315,8 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, if (!context->bg_thread) param->defered_dir_update = 0; + sb->s_maxbytes = yaffs_max_file_size(dev); + /* Release lock before yaffs_get_inode() */ yaffs_gross_unlock(dev); @@ -2366,9 +2426,10 @@ static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev) static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev) { - buf += - sprintf(buf, "data_bytes_per_chunk.. %d\n", - dev->data_bytes_per_chunk); + 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 +=