mirror of
https://github.com/torvalds/linux.git
synced 2024-11-18 18:11:56 +00:00
5f7a01e222
Most users of jffs2 are 32-bit systems that traditionally only support timestamps using a 32-bit signed time_t, in the range from years 1902 to 2038. On 64-bit systems, jffs2 however interpreted the same timestamps as unsigned values, reading back negative times (before 1970) as times between 2038 and 2106. Now that Linux supports 64-bit inode timestamps even on 32-bit systems, let's use the second interpretation everywhere to allow jffs2 to be used on 32-bit systems beyond 2038 without a fundamental change to the inode format. This has a slight risk of regressions, when existing files with timestamps before 1970 are present in file system images and are now interpreted as future time stamps. I considered moving the wraparound point a bit, e.g. to 1960, in order to deal with timestamps that ended up on Dec 31, 1969 due to incorrect timezone handling. However, this would complicate the implementation unnecessarily, so I went with the simplest possible method of extending the timestamps. Writing files with timestamps before 1970 or after 2106 now results in those times being clamped in the file system. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
201 lines
7.5 KiB
C
201 lines
7.5 KiB
C
/*
|
|
* JFFS2 -- Journalling Flash File System, Version 2.
|
|
*
|
|
* Copyright © 2001-2007 Red Hat, Inc.
|
|
*
|
|
* Created by David Woodhouse <dwmw2@infradead.org>
|
|
*
|
|
* For licensing information, see the file 'LICENCE' in this directory.
|
|
*
|
|
*/
|
|
|
|
#ifndef __JFFS2_OS_LINUX_H__
|
|
#define __JFFS2_OS_LINUX_H__
|
|
|
|
/* JFFS2 uses Linux mode bits natively -- no need for conversion */
|
|
#define os_to_jffs2_mode(x) (x)
|
|
#define jffs2_to_os_mode(x) (x)
|
|
|
|
struct kstatfs;
|
|
struct kvec;
|
|
|
|
#define JFFS2_INODE_INFO(i) (container_of(i, struct jffs2_inode_info, vfs_inode))
|
|
#define OFNI_EDONI_2SFFJ(f) (&(f)->vfs_inode)
|
|
#define JFFS2_SB_INFO(sb) (sb->s_fs_info)
|
|
#define OFNI_BS_2SFFJ(c) ((struct super_block *)c->os_priv)
|
|
|
|
|
|
#define JFFS2_F_I_SIZE(f) (OFNI_EDONI_2SFFJ(f)->i_size)
|
|
#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode)
|
|
#define JFFS2_F_I_UID(f) (i_uid_read(OFNI_EDONI_2SFFJ(f)))
|
|
#define JFFS2_F_I_GID(f) (i_gid_read(OFNI_EDONI_2SFFJ(f)))
|
|
#define JFFS2_F_I_RDEV(f) (OFNI_EDONI_2SFFJ(f)->i_rdev)
|
|
|
|
#define JFFS2_CLAMP_TIME(t) ((uint32_t)clamp_t(time64_t, (t), 0, U32_MAX))
|
|
#define ITIME(sec) ((struct timespec64){sec, 0})
|
|
#define JFFS2_NOW() JFFS2_CLAMP_TIME(ktime_get_real_seconds())
|
|
#define I_SEC(tv) JFFS2_CLAMP_TIME((tv).tv_sec)
|
|
#define JFFS2_F_I_CTIME(f) I_SEC(OFNI_EDONI_2SFFJ(f)->i_ctime)
|
|
#define JFFS2_F_I_MTIME(f) I_SEC(OFNI_EDONI_2SFFJ(f)->i_mtime)
|
|
#define JFFS2_F_I_ATIME(f) I_SEC(OFNI_EDONI_2SFFJ(f)->i_atime)
|
|
#define sleep_on_spinunlock(wq, s) \
|
|
do { \
|
|
DECLARE_WAITQUEUE(__wait, current); \
|
|
add_wait_queue((wq), &__wait); \
|
|
set_current_state(TASK_UNINTERRUPTIBLE); \
|
|
spin_unlock(s); \
|
|
schedule(); \
|
|
remove_wait_queue((wq), &__wait); \
|
|
} while(0)
|
|
|
|
static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
|
|
{
|
|
f->highest_version = 0;
|
|
f->fragtree = RB_ROOT;
|
|
f->metadata = NULL;
|
|
f->dents = NULL;
|
|
f->target = NULL;
|
|
f->flags = 0;
|
|
f->usercompr = 0;
|
|
}
|
|
|
|
|
|
#define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & SB_RDONLY)
|
|
|
|
#define SECTOR_ADDR(x) ( (((unsigned long)(x) / c->sector_size) * c->sector_size) )
|
|
#ifndef CONFIG_JFFS2_FS_WRITEBUFFER
|
|
|
|
|
|
#ifdef CONFIG_JFFS2_SUMMARY
|
|
#define jffs2_can_mark_obsolete(c) (0)
|
|
#else
|
|
#define jffs2_can_mark_obsolete(c) (1)
|
|
#endif
|
|
|
|
#define jffs2_is_writebuffered(c) (0)
|
|
#define jffs2_cleanmarker_oob(c) (0)
|
|
#define jffs2_write_nand_cleanmarker(c,jeb) (-EIO)
|
|
|
|
#define jffs2_flash_write(c, ofs, len, retlen, buf) jffs2_flash_direct_write(c, ofs, len, retlen, buf)
|
|
#define jffs2_flash_read(c, ofs, len, retlen, buf) (mtd_read((c)->mtd, ofs, len, retlen, buf))
|
|
#define jffs2_flush_wbuf_pad(c) ({ do{} while(0); (void)(c), 0; })
|
|
#define jffs2_flush_wbuf_gc(c, i) ({ do{} while(0); (void)(c), (void) i, 0; })
|
|
#define jffs2_write_nand_badblock(c,jeb,bad_offset) (1)
|
|
#define jffs2_nand_flash_setup(c) (0)
|
|
#define jffs2_nand_flash_cleanup(c) do {} while(0)
|
|
#define jffs2_wbuf_dirty(c) (0)
|
|
#define jffs2_flash_writev(a,b,c,d,e,f) jffs2_flash_direct_writev(a,b,c,d,e)
|
|
#define jffs2_wbuf_timeout NULL
|
|
#define jffs2_wbuf_process NULL
|
|
#define jffs2_dataflash(c) (0)
|
|
#define jffs2_dataflash_setup(c) (0)
|
|
#define jffs2_dataflash_cleanup(c) do {} while (0)
|
|
#define jffs2_nor_wbuf_flash(c) (0)
|
|
#define jffs2_nor_wbuf_flash_setup(c) (0)
|
|
#define jffs2_nor_wbuf_flash_cleanup(c) do {} while (0)
|
|
#define jffs2_ubivol(c) (0)
|
|
#define jffs2_ubivol_setup(c) (0)
|
|
#define jffs2_ubivol_cleanup(c) do {} while (0)
|
|
#define jffs2_dirty_trigger(c) do {} while (0)
|
|
|
|
#else /* NAND and/or ECC'd NOR support present */
|
|
|
|
#define jffs2_is_writebuffered(c) (c->wbuf != NULL)
|
|
|
|
#ifdef CONFIG_JFFS2_SUMMARY
|
|
#define jffs2_can_mark_obsolete(c) (0)
|
|
#else
|
|
#define jffs2_can_mark_obsolete(c) (c->mtd->flags & (MTD_BIT_WRITEABLE))
|
|
#endif
|
|
|
|
#define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH)
|
|
|
|
#define jffs2_wbuf_dirty(c) (!!(c)->wbuf_len)
|
|
|
|
/* wbuf.c */
|
|
int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino);
|
|
int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf);
|
|
int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, u_char *buf);
|
|
int jffs2_check_oob_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,int mode);
|
|
int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
|
|
int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
|
|
int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset);
|
|
void jffs2_wbuf_timeout(unsigned long data);
|
|
void jffs2_wbuf_process(void *data);
|
|
int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino);
|
|
int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c);
|
|
int jffs2_nand_flash_setup(struct jffs2_sb_info *c);
|
|
void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c);
|
|
|
|
#define jffs2_dataflash(c) (c->mtd->type == MTD_DATAFLASH)
|
|
int jffs2_dataflash_setup(struct jffs2_sb_info *c);
|
|
void jffs2_dataflash_cleanup(struct jffs2_sb_info *c);
|
|
#define jffs2_ubivol(c) (c->mtd->type == MTD_UBIVOLUME)
|
|
int jffs2_ubivol_setup(struct jffs2_sb_info *c);
|
|
void jffs2_ubivol_cleanup(struct jffs2_sb_info *c);
|
|
|
|
#define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && ! (c->mtd->flags & MTD_BIT_WRITEABLE))
|
|
int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c);
|
|
void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c);
|
|
void jffs2_dirty_trigger(struct jffs2_sb_info *c);
|
|
|
|
#endif /* WRITEBUFFER */
|
|
|
|
/* background.c */
|
|
int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c);
|
|
void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c);
|
|
void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c);
|
|
|
|
/* dir.c */
|
|
extern const struct file_operations jffs2_dir_operations;
|
|
extern const struct inode_operations jffs2_dir_inode_operations;
|
|
|
|
/* file.c */
|
|
extern const struct file_operations jffs2_file_operations;
|
|
extern const struct inode_operations jffs2_file_inode_operations;
|
|
extern const struct address_space_operations jffs2_file_address_operations;
|
|
int jffs2_fsync(struct file *, loff_t, loff_t, int);
|
|
int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
|
|
|
|
/* ioctl.c */
|
|
long jffs2_ioctl(struct file *, unsigned int, unsigned long);
|
|
|
|
/* symlink.c */
|
|
extern const struct inode_operations jffs2_symlink_inode_operations;
|
|
|
|
/* fs.c */
|
|
int jffs2_setattr (struct dentry *, struct iattr *);
|
|
int jffs2_do_setattr (struct inode *, struct iattr *);
|
|
struct inode *jffs2_iget(struct super_block *, unsigned long);
|
|
void jffs2_evict_inode (struct inode *);
|
|
void jffs2_dirty_inode(struct inode *inode, int flags);
|
|
struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode,
|
|
struct jffs2_raw_inode *ri);
|
|
int jffs2_statfs (struct dentry *, struct kstatfs *);
|
|
int jffs2_do_remount_fs(struct super_block *, int *, char *);
|
|
int jffs2_do_fill_super(struct super_block *sb, void *data, int silent);
|
|
void jffs2_gc_release_inode(struct jffs2_sb_info *c,
|
|
struct jffs2_inode_info *f);
|
|
struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
|
|
int inum, int unlinked);
|
|
|
|
unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
|
|
struct jffs2_inode_info *f,
|
|
unsigned long offset,
|
|
unsigned long *priv);
|
|
void jffs2_gc_release_page(struct jffs2_sb_info *c,
|
|
unsigned char *pg,
|
|
unsigned long *priv);
|
|
void jffs2_flash_cleanup(struct jffs2_sb_info *c);
|
|
|
|
|
|
/* writev.c */
|
|
int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
|
|
unsigned long count, loff_t to, size_t *retlen);
|
|
int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
|
|
size_t *retlen, const u_char *buf);
|
|
|
|
#endif /* __JFFS2_OS_LINUX_H__ */
|
|
|
|
|