#define YAFFS_HAS_EVICT_INODE
#endif
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) && \
+ (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0))
#define YAFFS_NEW_FOLLOW_LINK 1
#else
#define YAFFS_NEW_FOLLOW_LINK 0
#include <linux/seq_file.h>
#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
+#define PAGE_CACHE_SIZE PAGE_SIZE
+#define PAGE_CACHE_SHIFT PAGE_SHIFT
+#define Y_GET_DENTRY(f) ((f)->f_path.dentry)
+#define page_cache_release put_page
+#define YAFFS_NEW_XATTR 1
+#define YAFFS_NEW_GET_LINK 1
+#else
+#define Y_GET_DENTRY(f) ((f)->f_dentry)
+#define YAFFS_NEW_XATTR 0
+#define YAFFS_NEW_GET_LINK 0
+#endif
#define update_dir_time(dir) do {\
(dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
struct yaffs_obj *obj;
unsigned char *pg_buf;
int ret;
- loff_t pos = ((loff_t) pg->index) << PAGE_CACHE_SHIFT;
+ loff_t pos = ((loff_t) pg->index) << PAGE_SHIFT;
struct yaffs_dev *dev;
yaffs_trace(YAFFS_TRACE_OS,
"yaffs_readpage_nolock at %lld, size %08x",
(long long)pos,
- (unsigned)PAGE_CACHE_SIZE);
+ (unsigned)PAGE_SIZE);
- obj = yaffs_dentry_to_obj(f->f_dentry);
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
dev = obj->my_dev;
int n_free_chunks;
- obj = yaffs_dentry_to_obj(f->f_dentry);
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
dev = obj->my_dev;
struct yaffs_obj *obj;
struct yaffs_dev *dev;
- obj = yaffs_dentry_to_obj(f->f_dentry);
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
dev = obj->my_dev;
struct inode *inode;
struct yaffs_dev *dev;
- obj = yaffs_dentry_to_obj(f->f_dentry);
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
if (!obj) {
yaffs_trace(YAFFS_TRACE_OS,
yaffs_gross_lock(dev);
- inode = f->f_dentry->d_inode;
+ inode = Y_GET_DENTRY(f)->d_inode;
if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
ipos = inode->i_size;
static int yaffs_file_flush(struct file *file)
#endif
{
- struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_dentry);
+ struct yaffs_obj *obj = yaffs_dentry_to_obj(Y_GET_DENTRY(file));
struct yaffs_dev *dev = obj->my_dev;
yaffs_gross_lock(dev);
- yaffs_flush_file(obj, 1, 0);
+ yaffs_flush_file(obj, 1, 0, 0);
yaffs_gross_unlock(dev);
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;
}
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
static const struct file_operations yaffs_file_operations = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
+ .read = new_sync_read,
+ .write = new_sync_write,
+#endif
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
+#else
.read = do_sync_read,
.write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
+#endif
.mmap = generic_file_mmap,
.flush = yaffs_file_flush,
.fsync = yaffs_sync_object,
.splice_read = generic_file_splice_read,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+ .splice_write = iter_file_splice_write,
+#else
.splice_write = generic_file_splice_write,
+#endif
.llseek = generic_file_llseek,
};
return error;
}
+#if (YAFFS_NEW_XATTR > 0)
+static int yaffs_setxattr(struct dentry *dentry, struct inode *inode,
+ const char *name, const void *value, size_t size, int flags)
+{
+#else
static int yaffs_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
struct inode *inode = dentry->d_inode;
+#endif
int error = 0;
struct yaffs_dev *dev;
struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
return error;
}
+#ifdef YAFFS_NEW_XATTR
+static ssize_t yaffs_getxattr(struct dentry * dentry, struct inode *inode,
+ const char *name, void *buff, size_t size)
+{
+#else
static ssize_t yaffs_getxattr(struct dentry * dentry, const char *name,
void *buff, size_t size)
{
struct inode *inode = dentry->d_inode;
+#endif
int error = 0;
struct yaffs_dev *dev;
struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
return ret;
}
+#if (YAFFS_NEW_GET_LINK == 0)
#if (YAFFS_NEW_FOLLOW_LINK == 1)
static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
return ret;
#endif
}
+#else
+static const char *yaffs_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done)
+{
+ unsigned char *alias;
+ struct yaffs_dev *dev;
+
+ if (!dentry)
+ return ERR_PTR(-ECHILD);
+
+ dev = yaffs_dentry_to_obj(dentry)->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
+ yaffs_gross_unlock(dev);
+ if (!alias)
+ return ERR_PTR(-ENOMEM);
+ set_delayed_call(done, kfree_link, alias);
+ return alias;
+}
+#endif
#ifdef YAFFS_HAS_PUT_INODE
static const struct inode_operations yaffs_symlink_inode_operations = {
.readlink = yaffs_readlink,
+#if (YAFFS_NEW_GET_LINK == 1)
+ .get_link = yaffs_get_link,
+#else
.follow_link = yaffs_follow_link,
+#endif
#if (YAFFS_NEW_FOLLOW_LINK == 1)
.put_link = yaffs_put_link,
#endif
char name[YAFFS_MAX_NAME_LENGTH + 1];
- obj = yaffs_dentry_to_obj(f->f_dentry);
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
dev = obj->my_dev;
yaffs_gross_lock(dev);
struct yaffs_obj *obj;
struct yaffs_dev *dev;
struct yaffs_search_context *sc;
- struct inode *inode = f->f_dentry->d_inode;
+ struct inode *inode = Y_GET_DENTRY(f)->d_inode;
unsigned long offset, curoffs;
struct yaffs_obj *l;
int ret_val = 0;
char name[YAFFS_MAX_NAME_LENGTH + 1];
- obj = yaffs_dentry_to_obj(f->f_dentry);
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
dev = obj->my_dev;
yaffs_gross_lock(dev);
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_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);
}
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,
#ifdef YAFFS_HAS_WRITE_SUPER
.write_super = yaffs_write_super,
#endif
+ .remount_fs = yaffs_remount_fs,
};
struct yaffs_options {
/* Print header first */
if (step == 0)
buf +=
- sprintf(buf,
- "Multi-version YAFFS built:" __DATE__ " " __TIME__
- "\n");
+ sprintf(buf, "Multi-version YAFFS\n");
else if (step == 1)
buf += sprintf(buf, "\n");
else {
struct file_system_to_install *fsinst;
yaffs_trace(YAFFS_TRACE_ALWAYS,
- "yaffs built " __DATE__ " " __TIME__ " Installing.");
+ "yaffs Installing.");
mutex_init(&yaffs_context_lock);
struct file_system_to_install *fsinst;
yaffs_trace(YAFFS_TRACE_ALWAYS,
- "yaffs built " __DATE__ " " __TIME__ " removing.");
+ "yaffs removing.");
remove_proc_entry("yaffs", YPROC_ROOT);