summaryrefslogtreecommitdiffstats
path: root/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2015-03-31 15:31:57 +0000
committerGabor Juhos <juhosg@openwrt.org>2015-03-31 15:31:57 +0000
commit82f0308be91d572df10dadfe59f196e14760dc3d (patch)
tree06f81e98d755d3b1d9a199b9b78a277ce3577b03 /target/linux/generic/files/fs/yaffs2/yaffs_vfs.c
parent640318e62090821c1778dc9e3dfc5608bdcd7f0b (diff)
downloadmaster-31e0f0ae-82f0308be91d572df10dadfe59f196e14760dc3d.tar.gz
master-31e0f0ae-82f0308be91d572df10dadfe59f196e14760dc3d.tar.bz2
master-31e0f0ae-82f0308be91d572df10dadfe59f196e14760dc3d.zip
kernel: update yaffs code to the latest version
Use the latest version of the yaffs code. Fetched from the yaffs2 git tree and it is based on the following commit: commit 7e5cf0fa1b694f835cdc184a8395b229fa29f9ae Author: Charles Manning <cdhmanning@gmail.com> Date: Thu Aug 7 11:25:05 2014 +1200 yaffs-direct: Basic tests. Add lpthread flag for background gc support Signed-off-by: Charles Manning <cdhmanning@gmail.com> Signed-off-by: Gabor Juhos <juhosg@openwrt.org> SVN-Revision: 45188
Diffstat (limited to 'target/linux/generic/files/fs/yaffs2/yaffs_vfs.c')
-rw-r--r--target/linux/generic/files/fs/yaffs2/yaffs_vfs.c218
1 files changed, 191 insertions, 27 deletions
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c b/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c
index 67050d4e3d..76bc1db59f 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c
@@ -236,6 +236,15 @@ MODULE_PARM(yaffs_gc_control, "i");
#define Y_CLEAR_INODE(i) end_writeback(i)
#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
+#define YAFFS_USE_DIR_ITERATE
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
+#define YAFFS_NEW_PROCFS
+#include <linux/seq_file.h>
+#endif
+
#define update_dir_time(dir) do {\
(dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
@@ -1023,7 +1032,11 @@ static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
if (!alias)
return -ENOMEM;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
ret = vfs_readlink(dentry, buffer, buflen, alias);
+#else
+ ret = readlink_copy(buffer, buflen, alias);
+#endif
kfree(alias);
return ret;
}
@@ -1206,6 +1219,23 @@ struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
#define YCRED(x) (x->cred)
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#define YPROC_uid(p) (YCRED(p)->fsuid)
+#define YPROC_gid(p) (YCRED(p)->fsgid)
+#define EXTRACT_gid(x) x
+#define EXTRACT_uid(x) x
+#define MAKE_gid(x) x
+#define MAKE_uid(x) x
+#else
+#define YPROC_uid(p) from_kuid(&init_user_ns, YCRED(p)->fsuid)
+#define YPROC_gid(p) from_kgid(&init_user_ns, YCRED(p)->fsgid)
+#define EXTRACT_gid(x) from_kgid(&init_user_ns, x)
+#define EXTRACT_uid(x) from_kuid(&init_user_ns, x)
+#define MAKE_gid(x) make_kgid(&init_user_ns, x)
+#define MAKE_uid(x) make_kuid(&init_user_ns, x)
+#endif
+
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
dev_t rdev)
@@ -1225,9 +1255,9 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
int error = -ENOSPC;
- uid_t uid = YCRED(current)->fsuid;
+ uid_t uid = YPROC_uid(current);
gid_t gid =
- (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
+ (dir->i_mode & S_ISGID) ? EXTRACT_gid(dir->i_gid) : YPROC_gid(current);
if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
mode |= S_ISGID;
@@ -1424,9 +1454,9 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
{
struct yaffs_obj *obj;
struct yaffs_dev *dev;
- uid_t uid = YCRED(current)->fsuid;
+ uid_t uid = YPROC_uid(current);
gid_t gid =
- (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
+ (dir->i_mode & S_ISGID) ? EXTRACT_gid(dir->i_gid) : YPROC_gid(current);
yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
@@ -1674,6 +1704,77 @@ static void yaffs_remove_obj_callback(struct yaffs_obj *obj)
/*-----------------------------------------------------------------*/
+#ifdef YAFFS_USE_DIR_ITERATE
+static int yaffs_iterate(struct file *f, struct dir_context *dc)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+ struct yaffs_search_context *sc;
+ unsigned long curoffs;
+ struct yaffs_obj *l;
+ int ret_val = 0;
+
+ char name[YAFFS_MAX_NAME_LENGTH + 1];
+
+ obj = yaffs_dentry_to_obj(f->f_dentry);
+ dev = obj->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ yaffs_dev_to_lc(dev)->readdir_process = current;
+
+ sc = yaffs_new_search(obj);
+ if (!sc) {
+ ret_val = -ENOMEM;
+ goto out;
+ }
+
+ if (!dir_emit_dots(f, dc))
+ return 0;
+
+ curoffs = 1;
+
+ while (sc->next_return) {
+ curoffs++;
+ l = sc->next_return;
+ if (curoffs >= dc->pos) {
+ int this_inode = yaffs_get_obj_inode(l);
+ int this_type = yaffs_get_obj_type(l);
+
+ yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_readdir: %s inode %d",
+ name, yaffs_get_obj_inode(l));
+
+ yaffs_gross_unlock(dev);
+
+ if (!dir_emit(dc,
+ name,
+ strlen(name),
+ this_inode,
+ this_type)) {
+ yaffs_gross_lock(dev);
+ goto out;
+ }
+
+ yaffs_gross_lock(dev);
+
+ dc->pos++;
+ f->f_pos++;
+ }
+ yaffs_search_advance(sc);
+ }
+
+out:
+ yaffs_search_end(sc);
+ yaffs_dev_to_lc(dev)->readdir_process = NULL;
+ yaffs_gross_unlock(dev);
+
+ return ret_val;
+}
+
+#else
+
static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
{
struct yaffs_obj *obj;
@@ -1781,9 +1882,15 @@ out:
return ret_val;
}
+#endif
+
static const struct file_operations yaffs_dir_operations = {
.read = generic_read_dir,
+#ifdef YAFFS_USE_DIR_ITERATE
+ .iterate = yaffs_iterate,
+#else
.readdir = yaffs_readdir,
+#endif
.fsync = yaffs_sync_object,
.llseek = generic_file_llseek,
};
@@ -1829,8 +1936,8 @@ static void yaffs_fill_inode_from_obj(struct inode *inode,
inode->i_ino = obj->obj_id;
inode->i_mode = obj->yst_mode;
- inode->i_uid = obj->yst_uid;
- inode->i_gid = obj->yst_gid;
+ inode->i_uid = MAKE_uid(obj->yst_uid);
+ inode->i_gid = MAKE_gid(obj->yst_gid);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
inode->i_blksize = inode->i_sb->s_blocksize;
#endif
@@ -1856,7 +1963,7 @@ static void yaffs_fill_inode_from_obj(struct inode *inode,
yaffs_trace(YAFFS_TRACE_OS,
"yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
- inode->i_mode, inode->i_uid, inode->i_gid,
+ inode->i_mode, obj->yst_uid, obj->yst_gid,
inode->i_size, atomic_read(&inode->i_count));
switch (obj->yst_mode & S_IFMT) {
@@ -2670,7 +2777,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,
"yaffs: MTD device %u either not valid or unavailable",
MINOR(sb->s_dev));
@@ -2713,15 +2820,11 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
context = kmalloc(sizeof(struct yaffs_linux_context), GFP_KERNEL);
if (!dev || !context) {
- if (dev)
- kfree(dev);
- if (context)
- kfree(context);
+ kfree(dev);
+ 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 struct yaffs_dev."
@@ -3188,7 +3291,7 @@ static struct {
#define MAX_MASK_NAME_LENGTH 40
static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
- unsigned long count, void *data)
+ unsigned long count)
{
unsigned rg = 0, mask_bitfield;
char *end;
@@ -3289,7 +3392,7 @@ static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
*/
static int yaffs_proc_debug_write(struct file *file, const char *buf,
- unsigned long count, void *data)
+ unsigned long count)
{
char str[100];
@@ -3301,7 +3404,7 @@ static int yaffs_proc_debug_write(struct file *file, const char *buf,
struct list_head *item;
memset(str, 0, sizeof(str));
- memcpy(str, buf, min(count, sizeof(str) -1));
+ memcpy(str, buf, min((size_t)count, sizeof(str) -1));
cmd = str[1];
@@ -3364,12 +3467,18 @@ static int yaffs_proc_debug_write(struct file *file, const char *buf,
return count;
}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
static int yaffs_proc_write(struct file *file, const char *buf,
- unsigned long count, void *data)
+ unsigned long count, void *ppos)
+#else
+static ssize_t yaffs_proc_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+#endif
{
if (buf[0] == '.')
- return yaffs_proc_debug_write(file, buf, count, data);
- return yaffs_proc_write_trace_options(file, buf, count, data);
+ return yaffs_proc_debug_write(file, buf, count);
+ return yaffs_proc_write_trace_options(file, buf, count);
}
/* Stuff to handle installation of file systems */
@@ -3384,16 +3493,52 @@ static struct file_system_to_install fs_to_install[] = {
{NULL, 0}
};
-static int __init init_yaffs_fs(void)
+
+#ifdef YAFFS_NEW_PROCFS
+static int yaffs_proc_show(struct seq_file *m, void *v)
{
- int error = 0;
- struct file_system_to_install *fsinst;
+ /* FIXME: Unify in a better way? */
+ char buffer[512];
+ char *start;
+ int len;
- yaffs_trace(YAFFS_TRACE_ALWAYS,
- "yaffs built " __DATE__ " " __TIME__ " Installing.");
+ len = yaffs_proc_read(buffer, &start, 0, sizeof(buffer), NULL, NULL);
+ seq_puts(m, buffer);
+ return 0;
+}
+
+static int yaffs_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, yaffs_proc_show, NULL);
+}
+
+static struct file_operations procfs_ops = {
+ .owner = THIS_MODULE,
+ .open = yaffs_proc_open,
+ .read = seq_read,
+ .write = yaffs_proc_write,
+};
+
+static int yaffs_procfs_init(void)
+{
+ /* Install the proc_fs entries */
+ my_proc_entry = proc_create("yaffs",
+ S_IRUGO | S_IFREG,
+ YPROC_ROOT,
+ &procfs_ops);
+
+ if (my_proc_entry) {
+ return 0;
+ } else {
+ return -ENOMEM;
+ }
+}
+
+#else
- mutex_init(&yaffs_context_lock);
+static int yaffs_procfs_init(void)
+{
/* Install the proc_fs entries */
my_proc_entry = create_proc_entry("yaffs",
S_IRUGO | S_IFREG, YPROC_ROOT);
@@ -3402,9 +3547,28 @@ static int __init init_yaffs_fs(void)
my_proc_entry->write_proc = yaffs_proc_write;
my_proc_entry->read_proc = yaffs_proc_read;
my_proc_entry->data = NULL;
+ return 0;
} else {
return -ENOMEM;
- }
+ }
+}
+
+#endif
+
+
+static int __init init_yaffs_fs(void)
+{
+ int error = 0;
+ struct file_system_to_install *fsinst;
+
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs built " __DATE__ " " __TIME__ " Installing.");
+
+ mutex_init(&yaffs_context_lock);
+
+ error = yaffs_procfs_init();
+ if (error)
+ return error;
/* Now add the file system entries */