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> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@45188 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
a42b37dd86
commit
472f5abe11
|
@ -1,4 +1,4 @@
|
||||||
The yaffs2 source has been fetched from the yaffs2 GIT tree.
|
The yaffs2 source has been fetched from the yaffs2 GIT tree.
|
||||||
|
|
||||||
URL: git://www.aleph1.co.uk/yaffs2
|
URL: git://www.aleph1.co.uk/yaffs2
|
||||||
Version: bc76682d93955cfb33051beb503ad9f8a5450578 (2013-12-03)
|
Version: 7e5cf0fa1b694f835cdc184a8395b229fa29f9ae (2014-08-07)
|
||||||
|
|
|
@ -14,6 +14,14 @@
|
||||||
#include "yaffs_guts.h"
|
#include "yaffs_guts.h"
|
||||||
#include "yaffs_attribs.h"
|
#include "yaffs_attribs.h"
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||||
|
#define IATTR_UID ia_uid
|
||||||
|
#define IATTR_GID ia_gid
|
||||||
|
#else
|
||||||
|
#define IATTR_UID ia_uid.val
|
||||||
|
#define IATTR_GID ia_gid.val
|
||||||
|
#endif
|
||||||
|
|
||||||
void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
|
void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
|
||||||
{
|
{
|
||||||
obj->yst_uid = oh->yst_uid;
|
obj->yst_uid = oh->yst_uid;
|
||||||
|
@ -77,9 +85,9 @@ int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr)
|
||||||
if (valid & ATTR_MODE)
|
if (valid & ATTR_MODE)
|
||||||
obj->yst_mode = attr->ia_mode;
|
obj->yst_mode = attr->ia_mode;
|
||||||
if (valid & ATTR_UID)
|
if (valid & ATTR_UID)
|
||||||
obj->yst_uid = attr->ia_uid;
|
obj->yst_uid = attr->IATTR_UID;
|
||||||
if (valid & ATTR_GID)
|
if (valid & ATTR_GID)
|
||||||
obj->yst_gid = attr->ia_gid;
|
obj->yst_gid = attr->IATTR_GID;
|
||||||
|
|
||||||
if (valid & ATTR_ATIME)
|
if (valid & ATTR_ATIME)
|
||||||
obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
|
obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
|
||||||
|
@ -103,9 +111,9 @@ int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr)
|
||||||
|
|
||||||
attr->ia_mode = obj->yst_mode;
|
attr->ia_mode = obj->yst_mode;
|
||||||
valid |= ATTR_MODE;
|
valid |= ATTR_MODE;
|
||||||
attr->ia_uid = obj->yst_uid;
|
attr->IATTR_UID = obj->yst_uid;
|
||||||
valid |= ATTR_UID;
|
valid |= ATTR_UID;
|
||||||
attr->ia_gid = obj->yst_gid;
|
attr->IATTR_GID = obj->yst_gid;
|
||||||
valid |= ATTR_GID;
|
valid |= ATTR_GID;
|
||||||
|
|
||||||
Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
|
Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
|
||||||
|
|
|
@ -631,6 +631,78 @@ static void yaffs_retire_block(struct yaffs_dev *dev, int flash_block)
|
||||||
|
|
||||||
/*---------------- Name handling functions ------------*/
|
/*---------------- Name handling functions ------------*/
|
||||||
|
|
||||||
|
static void yaffs_load_name_from_oh(struct yaffs_dev *dev, YCHAR *name,
|
||||||
|
const YCHAR *oh_name, int buff_size)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_YAFFS_AUTO_UNICODE
|
||||||
|
if (dev->param.auto_unicode) {
|
||||||
|
if (*oh_name) {
|
||||||
|
/* It is an ASCII name, do an ASCII to
|
||||||
|
* unicode conversion */
|
||||||
|
const char *ascii_oh_name = (const char *)oh_name;
|
||||||
|
int n = buff_size - 1;
|
||||||
|
while (n > 0 && *ascii_oh_name) {
|
||||||
|
*name = *ascii_oh_name;
|
||||||
|
name++;
|
||||||
|
ascii_oh_name++;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strncpy(name, oh_name + 1, buff_size - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#else
|
||||||
|
(void) dev;
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
strncpy(name, oh_name, buff_size - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void yaffs_load_oh_from_name(struct yaffs_dev *dev, YCHAR *oh_name,
|
||||||
|
const YCHAR *name)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_YAFFS_AUTO_UNICODE
|
||||||
|
|
||||||
|
int is_ascii;
|
||||||
|
const YCHAR *w;
|
||||||
|
|
||||||
|
if (dev->param.auto_unicode) {
|
||||||
|
|
||||||
|
is_ascii = 1;
|
||||||
|
w = name;
|
||||||
|
|
||||||
|
/* Figure out if the name will fit in ascii character set */
|
||||||
|
while (is_ascii && *w) {
|
||||||
|
if ((*w) & 0xff00)
|
||||||
|
is_ascii = 0;
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_ascii) {
|
||||||
|
/* It is an ASCII name, so convert unicode to ascii */
|
||||||
|
char *ascii_oh_name = (char *)oh_name;
|
||||||
|
int n = YAFFS_MAX_NAME_LENGTH - 1;
|
||||||
|
while (n > 0 && *name) {
|
||||||
|
*ascii_oh_name = *name;
|
||||||
|
name++;
|
||||||
|
ascii_oh_name++;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Unicode name, so save starting at the second YCHAR */
|
||||||
|
*oh_name = 0;
|
||||||
|
strncpy(oh_name + 1, name, YAFFS_MAX_NAME_LENGTH - 2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#else
|
||||||
|
dev = dev;
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
strncpy(oh_name, name, YAFFS_MAX_NAME_LENGTH - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static u16 yaffs_calc_name_sum(const YCHAR *name)
|
static u16 yaffs_calc_name_sum(const YCHAR *name)
|
||||||
{
|
{
|
||||||
u16 sum = 0;
|
u16 sum = 0;
|
||||||
|
@ -1377,56 +1449,49 @@ static int yaffs_obj_cache_dirty(struct yaffs_obj *obj)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void yaffs_flush_file_cache(struct yaffs_obj *obj)
|
static void yaffs_flush_single_cache(struct yaffs_cache *cache, int discard)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!cache || cache->locked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Write it out and free it up if need be.*/
|
||||||
|
if (cache->dirty) {
|
||||||
|
yaffs_wr_data_obj(cache->object,
|
||||||
|
cache->chunk_id,
|
||||||
|
cache->data,
|
||||||
|
cache->n_bytes,
|
||||||
|
1);
|
||||||
|
|
||||||
|
cache->dirty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (discard)
|
||||||
|
cache->object = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void yaffs_flush_file_cache(struct yaffs_obj *obj, int discard)
|
||||||
{
|
{
|
||||||
struct yaffs_dev *dev = obj->my_dev;
|
struct yaffs_dev *dev = obj->my_dev;
|
||||||
int lowest = -99; /* Stop compiler whining. */
|
|
||||||
int i;
|
int i;
|
||||||
struct yaffs_cache *cache;
|
struct yaffs_cache *cache;
|
||||||
int chunk_written = 0;
|
|
||||||
int n_caches = obj->my_dev->param.n_caches;
|
int n_caches = obj->my_dev->param.n_caches;
|
||||||
|
|
||||||
if (n_caches < 1)
|
if (n_caches < 1)
|
||||||
return;
|
return;
|
||||||
do {
|
|
||||||
cache = NULL;
|
|
||||||
|
|
||||||
/* Find the lowest dirty chunk for this object */
|
|
||||||
for (i = 0; i < n_caches; i++) {
|
|
||||||
if (dev->cache[i].object == obj &&
|
|
||||||
dev->cache[i].dirty) {
|
|
||||||
if (!cache ||
|
|
||||||
dev->cache[i].chunk_id < lowest) {
|
|
||||||
cache = &dev->cache[i];
|
|
||||||
lowest = cache->chunk_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cache && !cache->locked) {
|
/* Find the chunks for this object and flush them. */
|
||||||
/* Write it out and free it up */
|
for (i = 0; i < n_caches; i++) {
|
||||||
chunk_written =
|
cache = &dev->cache[i];
|
||||||
yaffs_wr_data_obj(cache->object,
|
if (cache->object == obj)
|
||||||
cache->chunk_id,
|
yaffs_flush_single_cache(cache, discard);
|
||||||
cache->data,
|
}
|
||||||
cache->n_bytes, 1);
|
|
||||||
cache->dirty = 0;
|
|
||||||
cache->object = NULL;
|
|
||||||
}
|
|
||||||
} while (cache && chunk_written > 0);
|
|
||||||
|
|
||||||
if (cache)
|
|
||||||
/* Hoosterman, disk full while writing cache out. */
|
|
||||||
yaffs_trace(YAFFS_TRACE_ERROR,
|
|
||||||
"yaffs tragedy: no space during cache write");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*yaffs_flush_whole_cache(dev)
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
void yaffs_flush_whole_cache(struct yaffs_dev *dev)
|
void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard)
|
||||||
{
|
{
|
||||||
struct yaffs_obj *obj;
|
struct yaffs_obj *obj;
|
||||||
int n_caches = dev->param.n_caches;
|
int n_caches = dev->param.n_caches;
|
||||||
|
@ -1442,12 +1507,12 @@ void yaffs_flush_whole_cache(struct yaffs_dev *dev)
|
||||||
obj = dev->cache[i].object;
|
obj = dev->cache[i].object;
|
||||||
}
|
}
|
||||||
if (obj)
|
if (obj)
|
||||||
yaffs_flush_file_cache(obj);
|
yaffs_flush_file_cache(obj, discard);
|
||||||
} while (obj);
|
} while (obj);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Grab us a cache chunk for use.
|
/* Grab us an unused cache chunk for use.
|
||||||
* First look for an empty one.
|
* First look for an empty one.
|
||||||
* Then look for the least recently used non-dirty one.
|
* Then look for the least recently used non-dirty one.
|
||||||
* Then look for the least recently used dirty one...., flush and look again.
|
* Then look for the least recently used dirty one...., flush and look again.
|
||||||
|
@ -1462,56 +1527,50 @@ static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev)
|
||||||
return &dev->cache[i];
|
return &dev->cache[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
|
static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
|
||||||
{
|
{
|
||||||
struct yaffs_cache *cache;
|
struct yaffs_cache *cache;
|
||||||
struct yaffs_obj *the_obj;
|
|
||||||
int usage;
|
int usage;
|
||||||
int i;
|
int i;
|
||||||
int pushout;
|
|
||||||
|
|
||||||
if (dev->param.n_caches < 1)
|
if (dev->param.n_caches < 1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Try find a non-dirty one... */
|
/* First look for an unused cache */
|
||||||
|
|
||||||
cache = yaffs_grab_chunk_worker(dev);
|
cache = yaffs_grab_chunk_worker(dev);
|
||||||
|
|
||||||
if (!cache) {
|
if (cache)
|
||||||
/* They were all dirty, find the LRU object and flush
|
return cache;
|
||||||
* its cache, then find again.
|
|
||||||
* NB what's here is not very accurate,
|
|
||||||
* we actually flush the object with the LRU chunk.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* With locking we can't assume we can use entry zero,
|
/*
|
||||||
* Set the_obj to a valid pointer for Coverity. */
|
* Thery were all in use.
|
||||||
the_obj = dev->cache[0].object;
|
* Find the LRU cache and flush it if it is dirty.
|
||||||
usage = -1;
|
*/
|
||||||
cache = NULL;
|
|
||||||
pushout = -1;
|
|
||||||
|
|
||||||
for (i = 0; i < dev->param.n_caches; i++) {
|
usage = -1;
|
||||||
if (dev->cache[i].object &&
|
cache = NULL;
|
||||||
!dev->cache[i].locked &&
|
|
||||||
(dev->cache[i].last_use < usage ||
|
for (i = 0; i < dev->param.n_caches; i++) {
|
||||||
!cache)) {
|
if (dev->cache[i].object &&
|
||||||
|
!dev->cache[i].locked &&
|
||||||
|
(dev->cache[i].last_use < usage || !cache)) {
|
||||||
usage = dev->cache[i].last_use;
|
usage = dev->cache[i].last_use;
|
||||||
the_obj = dev->cache[i].object;
|
|
||||||
cache = &dev->cache[i];
|
cache = &dev->cache[i];
|
||||||
pushout = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cache || cache->dirty) {
|
|
||||||
/* Flush and try again */
|
|
||||||
yaffs_flush_file_cache(the_obj);
|
|
||||||
cache = yaffs_grab_chunk_worker(dev);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
yaffs_flush_single_cache(cache, 1);
|
||||||
|
#else
|
||||||
|
yaffs_flush_file_cache(cache->object, 1);
|
||||||
|
cache = yaffs_grab_chunk_worker(dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3189,78 +3248,6 @@ static void yaffs_check_obj_details_loaded(struct yaffs_obj *in)
|
||||||
yaffs_release_temp_buffer(dev, buf);
|
yaffs_release_temp_buffer(dev, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void yaffs_load_name_from_oh(struct yaffs_dev *dev, YCHAR *name,
|
|
||||||
const YCHAR *oh_name, int buff_size)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_YAFFS_AUTO_UNICODE
|
|
||||||
if (dev->param.auto_unicode) {
|
|
||||||
if (*oh_name) {
|
|
||||||
/* It is an ASCII name, do an ASCII to
|
|
||||||
* unicode conversion */
|
|
||||||
const char *ascii_oh_name = (const char *)oh_name;
|
|
||||||
int n = buff_size - 1;
|
|
||||||
while (n > 0 && *ascii_oh_name) {
|
|
||||||
*name = *ascii_oh_name;
|
|
||||||
name++;
|
|
||||||
ascii_oh_name++;
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
strncpy(name, oh_name + 1, buff_size - 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
#else
|
|
||||||
(void) dev;
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
strncpy(name, oh_name, buff_size - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void yaffs_load_oh_from_name(struct yaffs_dev *dev, YCHAR *oh_name,
|
|
||||||
const YCHAR *name)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_YAFFS_AUTO_UNICODE
|
|
||||||
|
|
||||||
int is_ascii;
|
|
||||||
YCHAR *w;
|
|
||||||
|
|
||||||
if (dev->param.auto_unicode) {
|
|
||||||
|
|
||||||
is_ascii = 1;
|
|
||||||
w = name;
|
|
||||||
|
|
||||||
/* Figure out if the name will fit in ascii character set */
|
|
||||||
while (is_ascii && *w) {
|
|
||||||
if ((*w) & 0xff00)
|
|
||||||
is_ascii = 0;
|
|
||||||
w++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_ascii) {
|
|
||||||
/* It is an ASCII name, so convert unicode to ascii */
|
|
||||||
char *ascii_oh_name = (char *)oh_name;
|
|
||||||
int n = YAFFS_MAX_NAME_LENGTH - 1;
|
|
||||||
while (n > 0 && *name) {
|
|
||||||
*ascii_oh_name = *name;
|
|
||||||
name++;
|
|
||||||
ascii_oh_name++;
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Unicode name, so save starting at the second YCHAR */
|
|
||||||
*oh_name = 0;
|
|
||||||
strncpy(oh_name + 1, name, YAFFS_MAX_NAME_LENGTH - 2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
#else
|
|
||||||
dev = dev;
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
strncpy(oh_name, name, YAFFS_MAX_NAME_LENGTH - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* UpdateObjectHeader updates the header on NAND for an object.
|
/* UpdateObjectHeader updates the header on NAND for an object.
|
||||||
* If name is not NULL, then that new name is used.
|
* If name is not NULL, then that new name is used.
|
||||||
*/
|
*/
|
||||||
|
@ -3765,7 +3752,7 @@ int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size)
|
||||||
struct yaffs_dev *dev = in->my_dev;
|
struct yaffs_dev *dev = in->my_dev;
|
||||||
loff_t old_size = in->variant.file_variant.file_size;
|
loff_t old_size = in->variant.file_variant.file_size;
|
||||||
|
|
||||||
yaffs_flush_file_cache(in);
|
yaffs_flush_file_cache(in, 1);
|
||||||
yaffs_invalidate_whole_cache(in);
|
yaffs_invalidate_whole_cache(in);
|
||||||
|
|
||||||
yaffs_check_gc(dev, 0);
|
yaffs_check_gc(dev, 0);
|
||||||
|
@ -3798,12 +3785,15 @@ int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size)
|
||||||
return YAFFS_OK;
|
return YAFFS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int yaffs_flush_file(struct yaffs_obj *in, int update_time, int data_sync)
|
int yaffs_flush_file(struct yaffs_obj *in,
|
||||||
|
int update_time,
|
||||||
|
int data_sync,
|
||||||
|
int discard_cache)
|
||||||
{
|
{
|
||||||
if (!in->dirty)
|
if (!in->dirty)
|
||||||
return YAFFS_OK;
|
return YAFFS_OK;
|
||||||
|
|
||||||
yaffs_flush_file_cache(in);
|
yaffs_flush_file_cache(in, discard_cache);
|
||||||
|
|
||||||
if (data_sync)
|
if (data_sync)
|
||||||
return YAFFS_OK;
|
return YAFFS_OK;
|
||||||
|
@ -3950,6 +3940,70 @@ int yaffs_del_obj(struct yaffs_obj *obj)
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void yaffs_empty_dir_to_dir(struct yaffs_obj *from_dir,
|
||||||
|
struct yaffs_obj *to_dir)
|
||||||
|
{
|
||||||
|
struct yaffs_obj *obj;
|
||||||
|
struct list_head *lh;
|
||||||
|
struct list_head *n;
|
||||||
|
|
||||||
|
list_for_each_safe(lh, n, &from_dir->variant.dir_variant.children) {
|
||||||
|
obj = list_entry(lh, struct yaffs_obj, siblings);
|
||||||
|
yaffs_add_obj_to_dir(to_dir, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct yaffs_obj *yaffs_retype_obj(struct yaffs_obj *obj,
|
||||||
|
enum yaffs_obj_type type)
|
||||||
|
{
|
||||||
|
/* Tear down the old variant */
|
||||||
|
switch (obj->variant_type) {
|
||||||
|
case YAFFS_OBJECT_TYPE_FILE:
|
||||||
|
/* Nuke file data */
|
||||||
|
yaffs_resize_file(obj, 0);
|
||||||
|
yaffs_free_tnode(obj->my_dev, obj->variant.file_variant.top);
|
||||||
|
obj->variant.file_variant.top = NULL;
|
||||||
|
break;
|
||||||
|
case YAFFS_OBJECT_TYPE_DIRECTORY:
|
||||||
|
/* Put the children in lost and found. */
|
||||||
|
yaffs_empty_dir_to_dir(obj, obj->my_dev->lost_n_found);
|
||||||
|
if (!list_empty(&obj->variant.dir_variant.dirty))
|
||||||
|
list_del_init(&obj->variant.dir_variant.dirty);
|
||||||
|
break;
|
||||||
|
case YAFFS_OBJECT_TYPE_SYMLINK:
|
||||||
|
/* Nuke symplink data */
|
||||||
|
kfree(obj->variant.symlink_variant.alias);
|
||||||
|
obj->variant.symlink_variant.alias = NULL;
|
||||||
|
break;
|
||||||
|
case YAFFS_OBJECT_TYPE_HARDLINK:
|
||||||
|
list_del_init(&obj->hard_links);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&obj->variant, 0, sizeof(obj->variant));
|
||||||
|
|
||||||
|
/*Set up new variant if the memset is not enough. */
|
||||||
|
switch (type) {
|
||||||
|
case YAFFS_OBJECT_TYPE_DIRECTORY:
|
||||||
|
INIT_LIST_HEAD(&obj->variant.dir_variant.children);
|
||||||
|
INIT_LIST_HEAD(&obj->variant.dir_variant.dirty);
|
||||||
|
break;
|
||||||
|
case YAFFS_OBJECT_TYPE_FILE:
|
||||||
|
case YAFFS_OBJECT_TYPE_SYMLINK:
|
||||||
|
case YAFFS_OBJECT_TYPE_HARDLINK:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->variant_type = type;
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static int yaffs_unlink_worker(struct yaffs_obj *obj)
|
static int yaffs_unlink_worker(struct yaffs_obj *obj)
|
||||||
{
|
{
|
||||||
int del_now = 0;
|
int del_now = 0;
|
||||||
|
@ -4678,7 +4732,7 @@ int yaffs_guts_ll_init(struct yaffs_dev *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int yaffs_format_dev(struct yaffs_dev *dev)
|
int yaffs_guts_format_dev(struct yaffs_dev *dev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
enum yaffs_block_state state;
|
enum yaffs_block_state state;
|
||||||
|
|
|
@ -144,12 +144,12 @@ struct yaffs_cache {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct yaffs_tags {
|
struct yaffs_tags {
|
||||||
unsigned chunk_id:20;
|
u32 chunk_id:20;
|
||||||
unsigned serial_number:2;
|
u32 serial_number:2;
|
||||||
unsigned n_bytes_lsb:10;
|
u32 n_bytes_lsb:10;
|
||||||
unsigned obj_id:18;
|
u32 obj_id:18;
|
||||||
unsigned ecc:12;
|
u32 ecc:12;
|
||||||
unsigned n_bytes_msb:2;
|
u32 n_bytes_msb:2;
|
||||||
};
|
};
|
||||||
|
|
||||||
union yaffs_tags_union {
|
union yaffs_tags_union {
|
||||||
|
@ -287,9 +287,9 @@ enum yaffs_block_state {
|
||||||
|
|
||||||
struct yaffs_block_info {
|
struct yaffs_block_info {
|
||||||
|
|
||||||
int soft_del_pages:10; /* number of soft deleted pages */
|
s32 soft_del_pages:10; /* number of soft deleted pages */
|
||||||
int pages_in_use:10; /* number of pages in use */
|
s32 pages_in_use:10; /* number of pages in use */
|
||||||
unsigned block_state:4; /* One of the above block states. */
|
u32 block_state:4; /* One of the above block states. */
|
||||||
/* NB use unsigned because enum is sometimes
|
/* NB use unsigned because enum is sometimes
|
||||||
* an int */
|
* an int */
|
||||||
u32 needs_retiring:1; /* Data has failed on this block, */
|
u32 needs_retiring:1; /* Data has failed on this block, */
|
||||||
|
@ -688,8 +688,8 @@ struct yaffs_dev {
|
||||||
/* Block Info */
|
/* Block Info */
|
||||||
struct yaffs_block_info *block_info;
|
struct yaffs_block_info *block_info;
|
||||||
u8 *chunk_bits; /* bitmap of chunks in use */
|
u8 *chunk_bits; /* bitmap of chunks in use */
|
||||||
unsigned block_info_alt:1; /* allocated using alternative alloc */
|
u8 block_info_alt:1; /* allocated using alternative alloc */
|
||||||
unsigned chunk_bits_alt:1; /* allocated using alternative alloc */
|
u8 chunk_bits_alt:1; /* allocated using alternative alloc */
|
||||||
int chunk_bit_stride; /* Number of bytes of chunk_bits per block.
|
int chunk_bit_stride; /* Number of bytes of chunk_bits per block.
|
||||||
* Must be consistent with chunks_per_block.
|
* Must be consistent with chunks_per_block.
|
||||||
*/
|
*/
|
||||||
|
@ -776,6 +776,7 @@ struct yaffs_dev {
|
||||||
u32 n_page_writes;
|
u32 n_page_writes;
|
||||||
u32 n_page_reads;
|
u32 n_page_reads;
|
||||||
u32 n_erasures;
|
u32 n_erasures;
|
||||||
|
u32 n_bad_queries;
|
||||||
u32 n_bad_markings;
|
u32 n_bad_markings;
|
||||||
u32 n_erase_failures;
|
u32 n_erase_failures;
|
||||||
u32 n_gc_copies;
|
u32 n_gc_copies;
|
||||||
|
@ -854,6 +855,9 @@ int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR * old_name,
|
||||||
|
|
||||||
int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR * name);
|
int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR * name);
|
||||||
int yaffs_del_obj(struct yaffs_obj *obj);
|
int yaffs_del_obj(struct yaffs_obj *obj);
|
||||||
|
struct yaffs_obj *yaffs_retype_obj(struct yaffs_obj *obj,
|
||||||
|
enum yaffs_obj_type type);
|
||||||
|
|
||||||
|
|
||||||
int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR * name, int buffer_size);
|
int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR * name, int buffer_size);
|
||||||
loff_t yaffs_get_obj_length(struct yaffs_obj *obj);
|
loff_t yaffs_get_obj_length(struct yaffs_obj *obj);
|
||||||
|
@ -872,10 +876,13 @@ struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent,
|
||||||
const YCHAR *name, u32 mode, u32 uid,
|
const YCHAR *name, u32 mode, u32 uid,
|
||||||
u32 gid);
|
u32 gid);
|
||||||
|
|
||||||
int yaffs_flush_file(struct yaffs_obj *obj, int update_time, int data_sync);
|
int yaffs_flush_file(struct yaffs_obj *in,
|
||||||
|
int update_time,
|
||||||
|
int data_sync,
|
||||||
|
int discard_cache);
|
||||||
|
|
||||||
/* Flushing and checkpointing */
|
/* Flushing and checkpointing */
|
||||||
void yaffs_flush_whole_cache(struct yaffs_dev *dev);
|
void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard);
|
||||||
|
|
||||||
int yaffs_checkpoint_save(struct yaffs_dev *dev);
|
int yaffs_checkpoint_save(struct yaffs_dev *dev);
|
||||||
int yaffs_checkpoint_restore(struct yaffs_dev *dev);
|
int yaffs_checkpoint_restore(struct yaffs_dev *dev);
|
||||||
|
@ -978,7 +985,7 @@ u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn,
|
||||||
|
|
||||||
int yaffs_is_non_empty_dir(struct yaffs_obj *obj);
|
int yaffs_is_non_empty_dir(struct yaffs_obj *obj);
|
||||||
|
|
||||||
int yaffs_format_dev(struct yaffs_dev *dev);
|
int yaffs_guts_format_dev(struct yaffs_dev *dev);
|
||||||
|
|
||||||
void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr,
|
void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr,
|
||||||
int *chunk_out, u32 *offset_out);
|
int *chunk_out, u32 *offset_out);
|
||||||
|
|
|
@ -22,12 +22,14 @@
|
||||||
#include "linux/kernel.h"
|
#include "linux/kernel.h"
|
||||||
#include "linux/version.h"
|
#include "linux/version.h"
|
||||||
#include "linux/types.h"
|
#include "linux/types.h"
|
||||||
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
|
||||||
|
#include "uapi/linux/major.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "yaffs_trace.h"
|
#include "yaffs_trace.h"
|
||||||
#include "yaffs_guts.h"
|
#include "yaffs_guts.h"
|
||||||
#include "yaffs_linux.h"
|
#include "yaffs_linux.h"
|
||||||
|
|
||||||
|
|
||||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
|
||||||
#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO
|
#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,13 +21,13 @@
|
||||||
#include "yaffs_guts.h"
|
#include "yaffs_guts.h"
|
||||||
|
|
||||||
struct yaffs_packed_tags1 {
|
struct yaffs_packed_tags1 {
|
||||||
unsigned chunk_id:20;
|
u32 chunk_id:20;
|
||||||
unsigned serial_number:2;
|
u32 serial_number:2;
|
||||||
unsigned n_bytes:10;
|
u32 n_bytes:10;
|
||||||
unsigned obj_id:18;
|
u32 obj_id:18;
|
||||||
unsigned ecc:12;
|
u32 ecc:12;
|
||||||
unsigned deleted:1;
|
u32 deleted:1;
|
||||||
unsigned unused_stuff:1;
|
u32 unused_stuff:1;
|
||||||
unsigned should_be_ff;
|
unsigned should_be_ff;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -235,7 +235,6 @@ int yaffs_summary_read(struct yaffs_dev *dev,
|
||||||
if (result == YAFFS_OK) {
|
if (result == YAFFS_OK) {
|
||||||
/* Verify header */
|
/* Verify header */
|
||||||
if (hdr.version != YAFFS_SUMMARY_VERSION ||
|
if (hdr.version != YAFFS_SUMMARY_VERSION ||
|
||||||
hdr.block != blk ||
|
|
||||||
hdr.seq != bi->seq_number ||
|
hdr.seq != bi->seq_number ||
|
||||||
hdr.sum != yaffs_summary_sum(dev))
|
hdr.sum != yaffs_summary_sum(dev))
|
||||||
result = YAFFS_FAIL;
|
result = YAFFS_FAIL;
|
||||||
|
|
|
@ -236,6 +236,15 @@ MODULE_PARM(yaffs_gc_control, "i");
|
||||||
#define Y_CLEAR_INODE(i) end_writeback(i)
|
#define Y_CLEAR_INODE(i) end_writeback(i)
|
||||||
#endif
|
#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 {\
|
#define update_dir_time(dir) do {\
|
||||||
(dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
|
(dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
|
||||||
|
@ -1023,7 +1032,11 @@ static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
|
||||||
if (!alias)
|
if (!alias)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
|
||||||
ret = vfs_readlink(dentry, buffer, buflen, alias);
|
ret = vfs_readlink(dentry, buffer, buflen, alias);
|
||||||
|
#else
|
||||||
|
ret = readlink_copy(buffer, buflen, alias);
|
||||||
|
#endif
|
||||||
kfree(alias);
|
kfree(alias);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1206,6 +1219,23 @@ struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
|
||||||
#define YCRED(x) (x->cred)
|
#define YCRED(x) (x->cred)
|
||||||
#endif
|
#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))
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
|
||||||
static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
|
static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||||
dev_t rdev)
|
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);
|
struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
|
||||||
|
|
||||||
int error = -ENOSPC;
|
int error = -ENOSPC;
|
||||||
uid_t uid = YCRED(current)->fsuid;
|
uid_t uid = YPROC_uid(current);
|
||||||
gid_t gid =
|
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))
|
if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
|
||||||
mode |= S_ISGID;
|
mode |= S_ISGID;
|
||||||
|
@ -1424,9 +1454,9 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
|
||||||
{
|
{
|
||||||
struct yaffs_obj *obj;
|
struct yaffs_obj *obj;
|
||||||
struct yaffs_dev *dev;
|
struct yaffs_dev *dev;
|
||||||
uid_t uid = YCRED(current)->fsuid;
|
uid_t uid = YPROC_uid(current);
|
||||||
gid_t gid =
|
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");
|
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)
|
static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
|
||||||
{
|
{
|
||||||
struct yaffs_obj *obj;
|
struct yaffs_obj *obj;
|
||||||
|
@ -1781,9 +1882,15 @@ out:
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct file_operations yaffs_dir_operations = {
|
static const struct file_operations yaffs_dir_operations = {
|
||||||
.read = generic_read_dir,
|
.read = generic_read_dir,
|
||||||
|
#ifdef YAFFS_USE_DIR_ITERATE
|
||||||
|
.iterate = yaffs_iterate,
|
||||||
|
#else
|
||||||
.readdir = yaffs_readdir,
|
.readdir = yaffs_readdir,
|
||||||
|
#endif
|
||||||
.fsync = yaffs_sync_object,
|
.fsync = yaffs_sync_object,
|
||||||
.llseek = generic_file_llseek,
|
.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_ino = obj->obj_id;
|
||||||
inode->i_mode = obj->yst_mode;
|
inode->i_mode = obj->yst_mode;
|
||||||
inode->i_uid = obj->yst_uid;
|
inode->i_uid = MAKE_uid(obj->yst_uid);
|
||||||
inode->i_gid = obj->yst_gid;
|
inode->i_gid = MAKE_gid(obj->yst_gid);
|
||||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
|
||||||
inode->i_blksize = inode->i_sb->s_blocksize;
|
inode->i_blksize = inode->i_sb->s_blocksize;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1856,7 +1963,7 @@ static void yaffs_fill_inode_from_obj(struct inode *inode,
|
||||||
|
|
||||||
yaffs_trace(YAFFS_TRACE_OS,
|
yaffs_trace(YAFFS_TRACE_OS,
|
||||||
"yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
|
"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));
|
inode->i_size, atomic_read(&inode->i_count));
|
||||||
|
|
||||||
switch (obj->yst_mode & S_IFMT) {
|
switch (obj->yst_mode & S_IFMT) {
|
||||||
|
@ -2670,7 +2777,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
|
||||||
|
|
||||||
/* Get the device */
|
/* Get the device */
|
||||||
mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
|
mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
|
||||||
if (!mtd) {
|
if (IS_ERR(mtd)) {
|
||||||
yaffs_trace(YAFFS_TRACE_ALWAYS,
|
yaffs_trace(YAFFS_TRACE_ALWAYS,
|
||||||
"yaffs: MTD device %u either not valid or unavailable",
|
"yaffs: MTD device %u either not valid or unavailable",
|
||||||
MINOR(sb->s_dev));
|
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);
|
context = kmalloc(sizeof(struct yaffs_linux_context), GFP_KERNEL);
|
||||||
|
|
||||||
if (!dev || !context) {
|
if (!dev || !context) {
|
||||||
if (dev)
|
kfree(dev);
|
||||||
kfree(dev);
|
kfree(context);
|
||||||
if (context)
|
|
||||||
kfree(context);
|
|
||||||
dev = NULL;
|
dev = NULL;
|
||||||
context = NULL;
|
context = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (!dev) {
|
|
||||||
/* Deep shit could not allocate device structure */
|
/* Deep shit could not allocate device structure */
|
||||||
yaffs_trace(YAFFS_TRACE_ALWAYS,
|
yaffs_trace(YAFFS_TRACE_ALWAYS,
|
||||||
"yaffs_read_super: Failed trying to allocate struct yaffs_dev."
|
"yaffs_read_super: Failed trying to allocate struct yaffs_dev."
|
||||||
|
@ -3188,7 +3291,7 @@ static struct {
|
||||||
|
|
||||||
#define MAX_MASK_NAME_LENGTH 40
|
#define MAX_MASK_NAME_LENGTH 40
|
||||||
static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
|
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;
|
unsigned rg = 0, mask_bitfield;
|
||||||
char *end;
|
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,
|
static int yaffs_proc_debug_write(struct file *file, const char *buf,
|
||||||
unsigned long count, void *data)
|
unsigned long count)
|
||||||
{
|
{
|
||||||
|
|
||||||
char str[100];
|
char str[100];
|
||||||
|
@ -3301,7 +3404,7 @@ static int yaffs_proc_debug_write(struct file *file, const char *buf,
|
||||||
struct list_head *item;
|
struct list_head *item;
|
||||||
|
|
||||||
memset(str, 0, sizeof(str));
|
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];
|
cmd = str[1];
|
||||||
|
|
||||||
|
@ -3364,12 +3467,18 @@ static int yaffs_proc_debug_write(struct file *file, const char *buf,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||||
static int yaffs_proc_write(struct file *file, const char *buf,
|
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] == '.')
|
if (buf[0] == '.')
|
||||||
return yaffs_proc_debug_write(file, buf, count, data);
|
return yaffs_proc_debug_write(file, buf, count);
|
||||||
return yaffs_proc_write_trace_options(file, buf, count, data);
|
return yaffs_proc_write_trace_options(file, buf, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stuff to handle installation of file systems */
|
/* Stuff to handle installation of file systems */
|
||||||
|
@ -3384,6 +3493,69 @@ static struct file_system_to_install fs_to_install[] = {
|
||||||
{NULL, 0}
|
{NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef YAFFS_NEW_PROCFS
|
||||||
|
static int yaffs_proc_show(struct seq_file *m, void *v)
|
||||||
|
{
|
||||||
|
/* FIXME: Unify in a better way? */
|
||||||
|
char buffer[512];
|
||||||
|
char *start;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
static int yaffs_procfs_init(void)
|
||||||
|
{
|
||||||
|
/* Install the proc_fs entries */
|
||||||
|
my_proc_entry = create_proc_entry("yaffs",
|
||||||
|
S_IRUGO | S_IFREG, YPROC_ROOT);
|
||||||
|
|
||||||
|
if (my_proc_entry) {
|
||||||
|
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)
|
static int __init init_yaffs_fs(void)
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
@ -3394,17 +3566,9 @@ static int __init init_yaffs_fs(void)
|
||||||
|
|
||||||
mutex_init(&yaffs_context_lock);
|
mutex_init(&yaffs_context_lock);
|
||||||
|
|
||||||
/* Install the proc_fs entries */
|
error = yaffs_procfs_init();
|
||||||
my_proc_entry = create_proc_entry("yaffs",
|
if (error)
|
||||||
S_IRUGO | S_IFREG, YPROC_ROOT);
|
return error;
|
||||||
|
|
||||||
if (my_proc_entry) {
|
|
||||||
my_proc_entry->write_proc = yaffs_proc_write;
|
|
||||||
my_proc_entry->read_proc = yaffs_proc_read;
|
|
||||||
my_proc_entry->data = NULL;
|
|
||||||
} else {
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now add the file system entries */
|
/* Now add the file system entries */
|
||||||
|
|
||||||
|
|
|
@ -1193,12 +1193,14 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!in->valid && in->variant_type !=
|
if (!in->valid && in->variant_type !=
|
||||||
(oh ? oh->type : tags.extra_obj_type))
|
(oh ? oh->type : tags.extra_obj_type)) {
|
||||||
yaffs_trace(YAFFS_TRACE_ERROR,
|
yaffs_trace(YAFFS_TRACE_ERROR,
|
||||||
"yaffs tragedy: Bad object type, %d != %d, for object %d at chunk %d during scan",
|
"yaffs tragedy: Bad type, %d != %d, for object %d at chunk %d during scan",
|
||||||
oh ? oh->type : tags.extra_obj_type,
|
oh ? oh->type : tags.extra_obj_type,
|
||||||
in->variant_type, tags.obj_id,
|
in->variant_type, tags.obj_id,
|
||||||
chunk);
|
chunk);
|
||||||
|
in = yaffs_retype_obj(in, oh ? oh->type : tags.extra_obj_type);
|
||||||
|
}
|
||||||
|
|
||||||
if (!in->valid &&
|
if (!in->valid &&
|
||||||
(tags.obj_id == YAFFS_OBJECTID_ROOT ||
|
(tags.obj_id == YAFFS_OBJECTID_ROOT ||
|
||||||
|
@ -1439,7 +1441,7 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
|
||||||
bi++;
|
bi++;
|
||||||
}
|
}
|
||||||
|
|
||||||
yaffs_trace(YAFFS_TRACE_SCAN, "%d blocks to be sorted...", n_to_scan);
|
yaffs_trace(YAFFS_TRACE_ALWAYS, "%d blocks to be sorted...", n_to_scan);
|
||||||
|
|
||||||
cond_resched();
|
cond_resched();
|
||||||
|
|
||||||
|
|
|
@ -1,155 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
|
||||||
@@ -329,6 +329,33 @@ static int yaffs_readpage(struct file *f
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
|
|
||||||
+#define YCRED_FSUID() from_kuid(&init_user_ns, current_fsuid())
|
|
||||||
+#define YCRED_FSGID() from_kgid(&init_user_ns, current_fsgid())
|
|
||||||
+#else
|
|
||||||
+#define YCRED_FSUID() YCRED(current)->fsuid
|
|
||||||
+#define YCRED_FSGID() YCRED(current)->fsgid
|
|
||||||
+
|
|
||||||
+static inline uid_t i_uid_read(const struct inode *inode)
|
|
||||||
+{
|
|
||||||
+ return inode->i_uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline gid_t i_gid_read(const struct inode *inode)
|
|
||||||
+{
|
|
||||||
+ return inode->i_gid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void i_uid_write(struct inode *inode, uid_t uid)
|
|
||||||
+{
|
|
||||||
+ inode->i_uid = uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void i_gid_write(struct inode *inode, gid_t gid)
|
|
||||||
+{
|
|
||||||
+ inode->i_gid = gid;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
|
|
||||||
{
|
|
||||||
@@ -1225,9 +1252,9 @@ static int yaffs_mknod(struct inode *dir
|
|
||||||
struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
|
|
||||||
|
|
||||||
int error = -ENOSPC;
|
|
||||||
- uid_t uid = YCRED(current)->fsuid;
|
|
||||||
+ uid_t uid = YCRED_FSUID();
|
|
||||||
gid_t gid =
|
|
||||||
- (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
|
|
||||||
+ (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
|
|
||||||
|
|
||||||
if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
|
|
||||||
mode |= S_ISGID;
|
|
||||||
@@ -1424,9 +1451,9 @@ static int yaffs_symlink(struct inode *d
|
|
||||||
{
|
|
||||||
struct yaffs_obj *obj;
|
|
||||||
struct yaffs_dev *dev;
|
|
||||||
- uid_t uid = YCRED(current)->fsuid;
|
|
||||||
+ uid_t uid = YCRED_FSUID();
|
|
||||||
gid_t gid =
|
|
||||||
- (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
|
|
||||||
+ (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
|
|
||||||
|
|
||||||
yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
|
|
||||||
|
|
||||||
@@ -1829,8 +1856,8 @@ static void yaffs_fill_inode_from_obj(st
|
|
||||||
|
|
||||||
inode->i_ino = obj->obj_id;
|
|
||||||
inode->i_mode = obj->yst_mode;
|
|
||||||
- inode->i_uid = obj->yst_uid;
|
|
||||||
- inode->i_gid = obj->yst_gid;
|
|
||||||
+ i_uid_write(inode, obj->yst_uid);
|
|
||||||
+ i_gid_write(inode, obj->yst_gid);
|
|
||||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
|
|
||||||
inode->i_blksize = inode->i_sb->s_blocksize;
|
|
||||||
#endif
|
|
||||||
@@ -1856,7 +1883,7 @@ static void yaffs_fill_inode_from_obj(st
|
|
||||||
|
|
||||||
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, i_uid_read(inode), i_gid_read(inode),
|
|
||||||
inode->i_size, atomic_read(&inode->i_count));
|
|
||||||
|
|
||||||
switch (obj->yst_mode & S_IFMT) {
|
|
||||||
--- a/fs/yaffs2/yaffs_attribs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_attribs.c
|
|
||||||
@@ -14,6 +14,48 @@
|
|
||||||
#include "yaffs_guts.h"
|
|
||||||
#include "yaffs_attribs.h"
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
|
|
||||||
+static inline uid_t ia_uid_read(const struct iattr *iattr)
|
|
||||||
+{
|
|
||||||
+ return from_kuid(&init_user_ns, iattr->ia_uid);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline gid_t ia_gid_read(const struct iattr *iattr)
|
|
||||||
+{
|
|
||||||
+ return from_kgid(&init_user_ns, iattr->ia_gid);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_uid = make_kuid(&init_user_ns, uid);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_gid = make_kgid(&init_user_ns, gid);
|
|
||||||
+}
|
|
||||||
+#else
|
|
||||||
+static inline uid_t ia_uid_read(const struct iattr *iattr)
|
|
||||||
+{
|
|
||||||
+ return iattr->ia_uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline gid_t ia_gid_read(const struct iattr *inode)
|
|
||||||
+{
|
|
||||||
+ return iattr->ia_gid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_uid = uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_gid = gid;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
|
|
||||||
{
|
|
||||||
obj->yst_uid = oh->yst_uid;
|
|
||||||
@@ -77,9 +119,9 @@ int yaffs_set_attribs(struct yaffs_obj *
|
|
||||||
if (valid & ATTR_MODE)
|
|
||||||
obj->yst_mode = attr->ia_mode;
|
|
||||||
if (valid & ATTR_UID)
|
|
||||||
- obj->yst_uid = attr->ia_uid;
|
|
||||||
+ obj->yst_uid = ia_uid_read(attr);
|
|
||||||
if (valid & ATTR_GID)
|
|
||||||
- obj->yst_gid = attr->ia_gid;
|
|
||||||
+ obj->yst_gid = ia_gid_read(attr);
|
|
||||||
|
|
||||||
if (valid & ATTR_ATIME)
|
|
||||||
obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
|
|
||||||
@@ -103,9 +145,9 @@ int yaffs_get_attribs(struct yaffs_obj *
|
|
||||||
|
|
||||||
attr->ia_mode = obj->yst_mode;
|
|
||||||
valid |= ATTR_MODE;
|
|
||||||
- attr->ia_uid = obj->yst_uid;
|
|
||||||
+ ia_uid_write(attr, obj->yst_uid);
|
|
||||||
valid |= ATTR_UID;
|
|
||||||
- attr->ia_gid = obj->yst_gid;
|
|
||||||
+ ia_gid_write(attr, obj->yst_gid);
|
|
||||||
valid |= ATTR_GID;
|
|
||||||
|
|
||||||
Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
--- a/fs/yaffs2/yaffs_vfs.c
|
||||||
|
+++ b/fs/yaffs2/yaffs_vfs.c
|
||||||
|
@@ -738,7 +738,7 @@ static int yaffs_file_flush(struct file
|
||||||
|
|
||||||
|
yaffs_gross_lock(dev);
|
||||||
|
|
||||||
|
- yaffs_flush_file(obj, 1, 0);
|
||||||
|
+ yaffs_flush_file(obj, 1, 0, 1);
|
||||||
|
|
||||||
|
yaffs_gross_unlock(dev);
|
||||||
|
|
||||||
|
@@ -768,7 +768,7 @@ static int yaffs_sync_object(struct file
|
||||||
|
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, 1);
|
||||||
|
yaffs_gross_unlock(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -2187,7 +2187,7 @@ static void yaffs_flush_inodes(struct su
|
||||||
|
yaffs_trace(YAFFS_TRACE_OS,
|
||||||
|
"flushing obj %d",
|
||||||
|
obj->obj_id);
|
||||||
|
- yaffs_flush_file(obj, 1, 0);
|
||||||
|
+ yaffs_flush_file(obj, 1, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -2200,7 +2200,7 @@ static void yaffs_flush_super(struct sup
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
|
||||||
@@ -3025,6 +3025,7 @@ static DECLARE_FSTYPE(yaffs2_fs_type, "y
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
|
|
||||||
static struct proc_dir_entry *my_proc_entry;
|
|
||||||
|
|
||||||
static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
|
|
||||||
@@ -3398,6 +3399,7 @@ static int yaffs_proc_write(struct file
|
|
||||||
return yaffs_proc_debug_write(file, buf, count, data);
|
|
||||||
return yaffs_proc_write_trace_options(file, buf, count, data);
|
|
||||||
}
|
|
||||||
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) */
|
|
||||||
|
|
||||||
/* Stuff to handle installation of file systems */
|
|
||||||
struct file_system_to_install {
|
|
||||||
@@ -3421,6 +3423,7 @@ static int __init init_yaffs_fs(void)
|
|
||||||
|
|
||||||
mutex_init(&yaffs_context_lock);
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
|
|
||||||
/* Install the proc_fs entries */
|
|
||||||
my_proc_entry = create_proc_entry("yaffs",
|
|
||||||
S_IRUGO | S_IFREG, YPROC_ROOT);
|
|
||||||
@@ -3432,6 +3435,7 @@ static int __init init_yaffs_fs(void)
|
|
||||||
} else {
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
/* Now add the file system entries */
|
|
||||||
|
|
||||||
@@ -3468,7 +3472,9 @@ static void __exit exit_yaffs_fs(void)
|
|
||||||
yaffs_trace(YAFFS_TRACE_ALWAYS,
|
|
||||||
"yaffs built " __DATE__ " " __TIME__ " removing.");
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
|
|
||||||
remove_proc_entry("yaffs", YPROC_ROOT);
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
fsinst = fs_to_install;
|
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
|
||||||
@@ -1701,6 +1701,110 @@ static void yaffs_remove_obj_callback(st
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------*/
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
|
|
||||||
+static int yaffs_readdir(struct file *file, struct dir_context *ctx)
|
|
||||||
+{
|
|
||||||
+ struct yaffs_obj *obj;
|
|
||||||
+ struct yaffs_dev *dev;
|
|
||||||
+ struct yaffs_search_context *sc;
|
|
||||||
+ struct inode *inode = file->f_dentry->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(file->f_dentry);
|
|
||||||
+ dev = obj->my_dev;
|
|
||||||
+
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+
|
|
||||||
+ yaffs_dev_to_lc(dev)->readdir_process = current;
|
|
||||||
+
|
|
||||||
+ offset = ctx->pos;
|
|
||||||
+
|
|
||||||
+ sc = yaffs_new_search(obj);
|
|
||||||
+ if (!sc) {
|
|
||||||
+ ret_val = -ENOMEM;
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ yaffs_trace(YAFFS_TRACE_OS,
|
|
||||||
+ "yaffs_readdir: starting at %d", (int)offset);
|
|
||||||
+
|
|
||||||
+ if (offset == 0) {
|
|
||||||
+ yaffs_trace(YAFFS_TRACE_OS,
|
|
||||||
+ "yaffs_readdir: entry . ino %d",
|
|
||||||
+ (int)inode->i_ino);
|
|
||||||
+ yaffs_gross_unlock(dev);
|
|
||||||
+ if (!dir_emit_dot(file, ctx)) {
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ offset++;
|
|
||||||
+ ctx->pos++;
|
|
||||||
+ }
|
|
||||||
+ if (offset == 1) {
|
|
||||||
+ yaffs_trace(YAFFS_TRACE_OS,
|
|
||||||
+ "yaffs_readdir: entry .. ino %d",
|
|
||||||
+ (int)file->f_dentry->d_parent->d_inode->i_ino);
|
|
||||||
+ yaffs_gross_unlock(dev);
|
|
||||||
+ if (!dir_emit_dotdot(file, ctx)) {
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ offset++;
|
|
||||||
+ ctx->pos++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ curoffs = 1;
|
|
||||||
+
|
|
||||||
+ /* If the directory has changed since the open or last call to
|
|
||||||
+ readdir, rewind to after the 2 canned entries. */
|
|
||||||
+ if (file->f_version != inode->i_version) {
|
|
||||||
+ offset = 2;
|
|
||||||
+ ctx->pos = offset;
|
|
||||||
+ file->f_version = inode->i_version;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ while (sc->next_return) {
|
|
||||||
+ curoffs++;
|
|
||||||
+ l = sc->next_return;
|
|
||||||
+ if (curoffs >= offset) {
|
|
||||||
+ 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(ctx, name, strlen(name),
|
|
||||||
+ this_inode, this_type) < 0) {
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+
|
|
||||||
+ offset++;
|
|
||||||
+ ctx->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;
|
|
||||||
@@ -1807,10 +1911,15 @@ out:
|
|
||||||
|
|
||||||
return ret_val;
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
static const struct file_operations yaffs_dir_operations = {
|
|
||||||
.read = generic_read_dir,
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
|
|
||||||
+ .iterate = yaffs_readdir,
|
|
||||||
+#else
|
|
||||||
.readdir = yaffs_readdir,
|
|
||||||
+#endif
|
|
||||||
.fsync = yaffs_sync_object,
|
|
||||||
.llseek = generic_file_llseek,
|
|
||||||
};
|
|
|
@ -4,7 +4,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
---
|
---
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
--- a/fs/yaffs2/yaffs_vfs.c
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
+++ b/fs/yaffs2/yaffs_vfs.c
|
||||||
@@ -2634,6 +2634,7 @@ static const struct super_operations yaf
|
@@ -2605,6 +2605,7 @@ static const struct super_operations yaf
|
||||||
|
|
||||||
struct yaffs_options {
|
struct yaffs_options {
|
||||||
int inband_tags;
|
int inband_tags;
|
||||||
|
@ -12,7 +12,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
int skip_checkpoint_read;
|
int skip_checkpoint_read;
|
||||||
int skip_checkpoint_write;
|
int skip_checkpoint_write;
|
||||||
int no_cache;
|
int no_cache;
|
||||||
@@ -2673,6 +2674,8 @@ static int yaffs_parse_options(struct ya
|
@@ -2644,6 +2645,8 @@ static int yaffs_parse_options(struct ya
|
||||||
|
|
||||||
if (!strcmp(cur_opt, "inband-tags")) {
|
if (!strcmp(cur_opt, "inband-tags")) {
|
||||||
options->inband_tags = 1;
|
options->inband_tags = 1;
|
||||||
|
@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
} else if (!strcmp(cur_opt, "tags-ecc-off")) {
|
} else if (!strcmp(cur_opt, "tags-ecc-off")) {
|
||||||
options->tags_ecc_on = 0;
|
options->tags_ecc_on = 0;
|
||||||
options->tags_ecc_overridden = 1;
|
options->tags_ecc_overridden = 1;
|
||||||
@@ -2746,7 +2749,6 @@ static struct super_block *yaffs_interna
|
@@ -2717,7 +2720,6 @@ static struct super_block *yaffs_interna
|
||||||
struct yaffs_param *param;
|
struct yaffs_param *param;
|
||||||
|
|
||||||
int read_only = 0;
|
int read_only = 0;
|
||||||
|
@ -29,7 +29,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
|
|
||||||
struct yaffs_options options;
|
struct yaffs_options options;
|
||||||
|
|
||||||
@@ -2786,6 +2788,9 @@ static struct super_block *yaffs_interna
|
@@ -2757,6 +2759,9 @@ static struct super_block *yaffs_interna
|
||||||
|
|
||||||
memset(&options, 0, sizeof(options));
|
memset(&options, 0, sizeof(options));
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
if (yaffs_parse_options(&options, data_str)) {
|
if (yaffs_parse_options(&options, data_str)) {
|
||||||
/* Option parsing failed */
|
/* Option parsing failed */
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2819,17 +2824,22 @@ static struct super_block *yaffs_interna
|
@@ -2790,17 +2795,22 @@ static struct super_block *yaffs_interna
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Added NCB 26/5/2006 for completeness */
|
/* Added NCB 26/5/2006 for completeness */
|
||||||
|
@ -68,7 +68,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* OK, so if we got here, we have an MTD that's NAND and looks
|
/* OK, so if we got here, we have an MTD that's NAND and looks
|
||||||
@@ -2890,7 +2900,8 @@ static struct super_block *yaffs_interna
|
@@ -2857,7 +2867,8 @@ static struct super_block *yaffs_interna
|
||||||
|
|
||||||
param->n_reserved_blocks = 5;
|
param->n_reserved_blocks = 5;
|
||||||
param->n_caches = (options.no_cache) ? 0 : 10;
|
param->n_caches = (options.no_cache) ? 0 : 10;
|
||||||
|
@ -80,15 +80,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
if (options.lazy_loading_overridden)
|
if (options.lazy_loading_overridden)
|
||||||
--- a/fs/yaffs2/yaffs_mtdif.c
|
--- a/fs/yaffs2/yaffs_mtdif.c
|
||||||
+++ b/fs/yaffs2/yaffs_mtdif.c
|
+++ b/fs/yaffs2/yaffs_mtdif.c
|
||||||
@@ -16,6 +16,7 @@
|
@@ -278,7 +278,8 @@ struct mtd_info * yaffs_get_mtd_device(d
|
||||||
#include "yaffs_mtdif.h"
|
|
||||||
|
|
||||||
#include "linux/mtd/mtd.h"
|
|
||||||
+#include "uapi/linux/major.h"
|
|
||||||
#include "linux/types.h"
|
|
||||||
#include "linux/time.h"
|
|
||||||
#include "linux/mtd/nand.h"
|
|
||||||
@@ -276,7 +277,8 @@ struct mtd_info * yaffs_get_mtd_device(d
|
|
||||||
return mtd;
|
return mtd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +90,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
{
|
{
|
||||||
if (yaffs_version == 2) {
|
if (yaffs_version == 2) {
|
||||||
if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
|
if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
|
||||||
@@ -295,6 +297,12 @@ int yaffs_verify_mtd(struct mtd_info *mt
|
@@ -297,6 +298,12 @@ int yaffs_verify_mtd(struct mtd_info *mt
|
||||||
);
|
);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
--- a/fs/yaffs2/yaffs_vfs.c
|
||||||
|
+++ b/fs/yaffs2/yaffs_vfs.c
|
||||||
|
@@ -774,7 +774,21 @@ static int yaffs_sync_object(struct file
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
|
||||||
|
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
|
||||||
|
+static const struct file_operations yaffs_file_operations = {
|
||||||
|
+ .read = new_sync_read,
|
||||||
|
+ .read_iter = generic_file_read_iter,
|
||||||
|
+ .write = new_sync_write,
|
||||||
|
+ .write_iter = generic_file_write_iter,
|
||||||
|
+ .mmap = generic_file_mmap,
|
||||||
|
+ .flush = yaffs_file_flush,
|
||||||
|
+ .fsync = yaffs_sync_object,
|
||||||
|
+ .splice_read = generic_file_splice_read,
|
||||||
|
+ .splice_write = iter_file_splice_write,
|
||||||
|
+ .llseek = generic_file_llseek,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
|
||||||
|
static const struct file_operations yaffs_file_operations = {
|
||||||
|
.read = do_sync_read,
|
||||||
|
.write = do_sync_write,
|
|
@ -1,155 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
|
||||||
@@ -329,6 +329,33 @@ static int yaffs_readpage(struct file *f
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
|
|
||||||
+#define YCRED_FSUID() from_kuid(&init_user_ns, current_fsuid())
|
|
||||||
+#define YCRED_FSGID() from_kgid(&init_user_ns, current_fsgid())
|
|
||||||
+#else
|
|
||||||
+#define YCRED_FSUID() YCRED(current)->fsuid
|
|
||||||
+#define YCRED_FSGID() YCRED(current)->fsgid
|
|
||||||
+
|
|
||||||
+static inline uid_t i_uid_read(const struct inode *inode)
|
|
||||||
+{
|
|
||||||
+ return inode->i_uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline gid_t i_gid_read(const struct inode *inode)
|
|
||||||
+{
|
|
||||||
+ return inode->i_gid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void i_uid_write(struct inode *inode, uid_t uid)
|
|
||||||
+{
|
|
||||||
+ inode->i_uid = uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void i_gid_write(struct inode *inode, gid_t gid)
|
|
||||||
+{
|
|
||||||
+ inode->i_gid = gid;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
|
|
||||||
{
|
|
||||||
@@ -1225,9 +1252,9 @@ static int yaffs_mknod(struct inode *dir
|
|
||||||
struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
|
|
||||||
|
|
||||||
int error = -ENOSPC;
|
|
||||||
- uid_t uid = YCRED(current)->fsuid;
|
|
||||||
+ uid_t uid = YCRED_FSUID();
|
|
||||||
gid_t gid =
|
|
||||||
- (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
|
|
||||||
+ (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
|
|
||||||
|
|
||||||
if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
|
|
||||||
mode |= S_ISGID;
|
|
||||||
@@ -1424,9 +1451,9 @@ static int yaffs_symlink(struct inode *d
|
|
||||||
{
|
|
||||||
struct yaffs_obj *obj;
|
|
||||||
struct yaffs_dev *dev;
|
|
||||||
- uid_t uid = YCRED(current)->fsuid;
|
|
||||||
+ uid_t uid = YCRED_FSUID();
|
|
||||||
gid_t gid =
|
|
||||||
- (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
|
|
||||||
+ (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
|
|
||||||
|
|
||||||
yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
|
|
||||||
|
|
||||||
@@ -1829,8 +1856,8 @@ static void yaffs_fill_inode_from_obj(st
|
|
||||||
|
|
||||||
inode->i_ino = obj->obj_id;
|
|
||||||
inode->i_mode = obj->yst_mode;
|
|
||||||
- inode->i_uid = obj->yst_uid;
|
|
||||||
- inode->i_gid = obj->yst_gid;
|
|
||||||
+ i_uid_write(inode, obj->yst_uid);
|
|
||||||
+ i_gid_write(inode, obj->yst_gid);
|
|
||||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
|
|
||||||
inode->i_blksize = inode->i_sb->s_blocksize;
|
|
||||||
#endif
|
|
||||||
@@ -1856,7 +1883,7 @@ static void yaffs_fill_inode_from_obj(st
|
|
||||||
|
|
||||||
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, i_uid_read(inode), i_gid_read(inode),
|
|
||||||
inode->i_size, atomic_read(&inode->i_count));
|
|
||||||
|
|
||||||
switch (obj->yst_mode & S_IFMT) {
|
|
||||||
--- a/fs/yaffs2/yaffs_attribs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_attribs.c
|
|
||||||
@@ -14,6 +14,48 @@
|
|
||||||
#include "yaffs_guts.h"
|
|
||||||
#include "yaffs_attribs.h"
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
|
|
||||||
+static inline uid_t ia_uid_read(const struct iattr *iattr)
|
|
||||||
+{
|
|
||||||
+ return from_kuid(&init_user_ns, iattr->ia_uid);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline gid_t ia_gid_read(const struct iattr *iattr)
|
|
||||||
+{
|
|
||||||
+ return from_kgid(&init_user_ns, iattr->ia_gid);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_uid = make_kuid(&init_user_ns, uid);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_gid = make_kgid(&init_user_ns, gid);
|
|
||||||
+}
|
|
||||||
+#else
|
|
||||||
+static inline uid_t ia_uid_read(const struct iattr *iattr)
|
|
||||||
+{
|
|
||||||
+ return iattr->ia_uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline gid_t ia_gid_read(const struct iattr *inode)
|
|
||||||
+{
|
|
||||||
+ return iattr->ia_gid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_uid = uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_gid = gid;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
|
|
||||||
{
|
|
||||||
obj->yst_uid = oh->yst_uid;
|
|
||||||
@@ -77,9 +119,9 @@ int yaffs_set_attribs(struct yaffs_obj *
|
|
||||||
if (valid & ATTR_MODE)
|
|
||||||
obj->yst_mode = attr->ia_mode;
|
|
||||||
if (valid & ATTR_UID)
|
|
||||||
- obj->yst_uid = attr->ia_uid;
|
|
||||||
+ obj->yst_uid = ia_uid_read(attr);
|
|
||||||
if (valid & ATTR_GID)
|
|
||||||
- obj->yst_gid = attr->ia_gid;
|
|
||||||
+ obj->yst_gid = ia_gid_read(attr);
|
|
||||||
|
|
||||||
if (valid & ATTR_ATIME)
|
|
||||||
obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
|
|
||||||
@@ -103,9 +145,9 @@ int yaffs_get_attribs(struct yaffs_obj *
|
|
||||||
|
|
||||||
attr->ia_mode = obj->yst_mode;
|
|
||||||
valid |= ATTR_MODE;
|
|
||||||
- attr->ia_uid = obj->yst_uid;
|
|
||||||
+ ia_uid_write(attr, obj->yst_uid);
|
|
||||||
valid |= ATTR_UID;
|
|
||||||
- attr->ia_gid = obj->yst_gid;
|
|
||||||
+ ia_gid_write(attr, obj->yst_gid);
|
|
||||||
valid |= ATTR_GID;
|
|
||||||
|
|
||||||
Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
--- a/fs/yaffs2/yaffs_vfs.c
|
||||||
|
+++ b/fs/yaffs2/yaffs_vfs.c
|
||||||
|
@@ -738,7 +738,7 @@ static int yaffs_file_flush(struct file
|
||||||
|
|
||||||
|
yaffs_gross_lock(dev);
|
||||||
|
|
||||||
|
- yaffs_flush_file(obj, 1, 0);
|
||||||
|
+ yaffs_flush_file(obj, 1, 0, 1);
|
||||||
|
|
||||||
|
yaffs_gross_unlock(dev);
|
||||||
|
|
||||||
|
@@ -768,7 +768,7 @@ static int yaffs_sync_object(struct file
|
||||||
|
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, 1);
|
||||||
|
yaffs_gross_unlock(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -2187,7 +2187,7 @@ static void yaffs_flush_inodes(struct su
|
||||||
|
yaffs_trace(YAFFS_TRACE_OS,
|
||||||
|
"flushing obj %d",
|
||||||
|
obj->obj_id);
|
||||||
|
- yaffs_flush_file(obj, 1, 0);
|
||||||
|
+ yaffs_flush_file(obj, 1, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -2200,7 +2200,7 @@ static void yaffs_flush_super(struct sup
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
|
||||||
@@ -3025,6 +3025,7 @@ static DECLARE_FSTYPE(yaffs2_fs_type, "y
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
|
|
||||||
static struct proc_dir_entry *my_proc_entry;
|
|
||||||
|
|
||||||
static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
|
|
||||||
@@ -3398,6 +3399,7 @@ static int yaffs_proc_write(struct file
|
|
||||||
return yaffs_proc_debug_write(file, buf, count, data);
|
|
||||||
return yaffs_proc_write_trace_options(file, buf, count, data);
|
|
||||||
}
|
|
||||||
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) */
|
|
||||||
|
|
||||||
/* Stuff to handle installation of file systems */
|
|
||||||
struct file_system_to_install {
|
|
||||||
@@ -3421,6 +3423,7 @@ static int __init init_yaffs_fs(void)
|
|
||||||
|
|
||||||
mutex_init(&yaffs_context_lock);
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
|
|
||||||
/* Install the proc_fs entries */
|
|
||||||
my_proc_entry = create_proc_entry("yaffs",
|
|
||||||
S_IRUGO | S_IFREG, YPROC_ROOT);
|
|
||||||
@@ -3432,6 +3435,7 @@ static int __init init_yaffs_fs(void)
|
|
||||||
} else {
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
/* Now add the file system entries */
|
|
||||||
|
|
||||||
@@ -3468,7 +3472,9 @@ static void __exit exit_yaffs_fs(void)
|
|
||||||
yaffs_trace(YAFFS_TRACE_ALWAYS,
|
|
||||||
"yaffs built " __DATE__ " " __TIME__ " removing.");
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
|
|
||||||
remove_proc_entry("yaffs", YPROC_ROOT);
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
fsinst = fs_to_install;
|
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
|
||||||
@@ -1701,6 +1701,110 @@ static void yaffs_remove_obj_callback(st
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------*/
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
|
|
||||||
+static int yaffs_readdir(struct file *file, struct dir_context *ctx)
|
|
||||||
+{
|
|
||||||
+ struct yaffs_obj *obj;
|
|
||||||
+ struct yaffs_dev *dev;
|
|
||||||
+ struct yaffs_search_context *sc;
|
|
||||||
+ struct inode *inode = file->f_dentry->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(file->f_dentry);
|
|
||||||
+ dev = obj->my_dev;
|
|
||||||
+
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+
|
|
||||||
+ yaffs_dev_to_lc(dev)->readdir_process = current;
|
|
||||||
+
|
|
||||||
+ offset = ctx->pos;
|
|
||||||
+
|
|
||||||
+ sc = yaffs_new_search(obj);
|
|
||||||
+ if (!sc) {
|
|
||||||
+ ret_val = -ENOMEM;
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ yaffs_trace(YAFFS_TRACE_OS,
|
|
||||||
+ "yaffs_readdir: starting at %d", (int)offset);
|
|
||||||
+
|
|
||||||
+ if (offset == 0) {
|
|
||||||
+ yaffs_trace(YAFFS_TRACE_OS,
|
|
||||||
+ "yaffs_readdir: entry . ino %d",
|
|
||||||
+ (int)inode->i_ino);
|
|
||||||
+ yaffs_gross_unlock(dev);
|
|
||||||
+ if (!dir_emit_dot(file, ctx)) {
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ offset++;
|
|
||||||
+ ctx->pos++;
|
|
||||||
+ }
|
|
||||||
+ if (offset == 1) {
|
|
||||||
+ yaffs_trace(YAFFS_TRACE_OS,
|
|
||||||
+ "yaffs_readdir: entry .. ino %d",
|
|
||||||
+ (int)file->f_dentry->d_parent->d_inode->i_ino);
|
|
||||||
+ yaffs_gross_unlock(dev);
|
|
||||||
+ if (!dir_emit_dotdot(file, ctx)) {
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ offset++;
|
|
||||||
+ ctx->pos++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ curoffs = 1;
|
|
||||||
+
|
|
||||||
+ /* If the directory has changed since the open or last call to
|
|
||||||
+ readdir, rewind to after the 2 canned entries. */
|
|
||||||
+ if (file->f_version != inode->i_version) {
|
|
||||||
+ offset = 2;
|
|
||||||
+ ctx->pos = offset;
|
|
||||||
+ file->f_version = inode->i_version;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ while (sc->next_return) {
|
|
||||||
+ curoffs++;
|
|
||||||
+ l = sc->next_return;
|
|
||||||
+ if (curoffs >= offset) {
|
|
||||||
+ 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(ctx, name, strlen(name),
|
|
||||||
+ this_inode, this_type) < 0) {
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+
|
|
||||||
+ offset++;
|
|
||||||
+ ctx->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;
|
|
||||||
@@ -1807,10 +1911,15 @@ out:
|
|
||||||
|
|
||||||
return ret_val;
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
static const struct file_operations yaffs_dir_operations = {
|
|
||||||
.read = generic_read_dir,
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
|
|
||||||
+ .iterate = yaffs_readdir,
|
|
||||||
+#else
|
|
||||||
.readdir = yaffs_readdir,
|
|
||||||
+#endif
|
|
||||||
.fsync = yaffs_sync_object,
|
|
||||||
.llseek = generic_file_llseek,
|
|
||||||
};
|
|
|
@ -4,7 +4,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
---
|
---
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
--- a/fs/yaffs2/yaffs_vfs.c
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
+++ b/fs/yaffs2/yaffs_vfs.c
|
||||||
@@ -2634,6 +2634,7 @@ static const struct super_operations yaf
|
@@ -2605,6 +2605,7 @@ static const struct super_operations yaf
|
||||||
|
|
||||||
struct yaffs_options {
|
struct yaffs_options {
|
||||||
int inband_tags;
|
int inband_tags;
|
||||||
|
@ -12,7 +12,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
int skip_checkpoint_read;
|
int skip_checkpoint_read;
|
||||||
int skip_checkpoint_write;
|
int skip_checkpoint_write;
|
||||||
int no_cache;
|
int no_cache;
|
||||||
@@ -2673,6 +2674,8 @@ static int yaffs_parse_options(struct ya
|
@@ -2644,6 +2645,8 @@ static int yaffs_parse_options(struct ya
|
||||||
|
|
||||||
if (!strcmp(cur_opt, "inband-tags")) {
|
if (!strcmp(cur_opt, "inband-tags")) {
|
||||||
options->inband_tags = 1;
|
options->inband_tags = 1;
|
||||||
|
@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
} else if (!strcmp(cur_opt, "tags-ecc-off")) {
|
} else if (!strcmp(cur_opt, "tags-ecc-off")) {
|
||||||
options->tags_ecc_on = 0;
|
options->tags_ecc_on = 0;
|
||||||
options->tags_ecc_overridden = 1;
|
options->tags_ecc_overridden = 1;
|
||||||
@@ -2746,7 +2749,6 @@ static struct super_block *yaffs_interna
|
@@ -2717,7 +2720,6 @@ static struct super_block *yaffs_interna
|
||||||
struct yaffs_param *param;
|
struct yaffs_param *param;
|
||||||
|
|
||||||
int read_only = 0;
|
int read_only = 0;
|
||||||
|
@ -29,7 +29,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
|
|
||||||
struct yaffs_options options;
|
struct yaffs_options options;
|
||||||
|
|
||||||
@@ -2786,6 +2788,9 @@ static struct super_block *yaffs_interna
|
@@ -2757,6 +2759,9 @@ static struct super_block *yaffs_interna
|
||||||
|
|
||||||
memset(&options, 0, sizeof(options));
|
memset(&options, 0, sizeof(options));
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
if (yaffs_parse_options(&options, data_str)) {
|
if (yaffs_parse_options(&options, data_str)) {
|
||||||
/* Option parsing failed */
|
/* Option parsing failed */
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2819,17 +2824,22 @@ static struct super_block *yaffs_interna
|
@@ -2790,17 +2795,22 @@ static struct super_block *yaffs_interna
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Added NCB 26/5/2006 for completeness */
|
/* Added NCB 26/5/2006 for completeness */
|
||||||
|
@ -68,7 +68,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* OK, so if we got here, we have an MTD that's NAND and looks
|
/* OK, so if we got here, we have an MTD that's NAND and looks
|
||||||
@@ -2890,7 +2900,8 @@ static struct super_block *yaffs_interna
|
@@ -2857,7 +2867,8 @@ static struct super_block *yaffs_interna
|
||||||
|
|
||||||
param->n_reserved_blocks = 5;
|
param->n_reserved_blocks = 5;
|
||||||
param->n_caches = (options.no_cache) ? 0 : 10;
|
param->n_caches = (options.no_cache) ? 0 : 10;
|
||||||
|
@ -80,15 +80,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
if (options.lazy_loading_overridden)
|
if (options.lazy_loading_overridden)
|
||||||
--- a/fs/yaffs2/yaffs_mtdif.c
|
--- a/fs/yaffs2/yaffs_mtdif.c
|
||||||
+++ b/fs/yaffs2/yaffs_mtdif.c
|
+++ b/fs/yaffs2/yaffs_mtdif.c
|
||||||
@@ -16,6 +16,7 @@
|
@@ -278,7 +278,8 @@ struct mtd_info * yaffs_get_mtd_device(d
|
||||||
#include "yaffs_mtdif.h"
|
|
||||||
|
|
||||||
#include "linux/mtd/mtd.h"
|
|
||||||
+#include "uapi/linux/major.h"
|
|
||||||
#include "linux/types.h"
|
|
||||||
#include "linux/time.h"
|
|
||||||
#include "linux/mtd/nand.h"
|
|
||||||
@@ -276,7 +277,8 @@ struct mtd_info * yaffs_get_mtd_device(d
|
|
||||||
return mtd;
|
return mtd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +90,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
{
|
{
|
||||||
if (yaffs_version == 2) {
|
if (yaffs_version == 2) {
|
||||||
if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
|
if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
|
||||||
@@ -295,6 +297,12 @@ int yaffs_verify_mtd(struct mtd_info *mt
|
@@ -297,6 +298,12 @@ int yaffs_verify_mtd(struct mtd_info *mt
|
||||||
);
|
);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
--- a/fs/yaffs2/yaffs_vfs.c
|
||||||
|
+++ b/fs/yaffs2/yaffs_vfs.c
|
||||||
|
@@ -774,7 +774,21 @@ static int yaffs_sync_object(struct file
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
|
||||||
|
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
|
||||||
|
+static const struct file_operations yaffs_file_operations = {
|
||||||
|
+ .read = new_sync_read,
|
||||||
|
+ .read_iter = generic_file_read_iter,
|
||||||
|
+ .write = new_sync_write,
|
||||||
|
+ .write_iter = generic_file_write_iter,
|
||||||
|
+ .mmap = generic_file_mmap,
|
||||||
|
+ .flush = yaffs_file_flush,
|
||||||
|
+ .fsync = yaffs_sync_object,
|
||||||
|
+ .splice_read = generic_file_splice_read,
|
||||||
|
+ .splice_write = iter_file_splice_write,
|
||||||
|
+ .llseek = generic_file_llseek,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
|
||||||
|
static const struct file_operations yaffs_file_operations = {
|
||||||
|
.read = do_sync_read,
|
||||||
|
.write = do_sync_write,
|
|
@ -1,32 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
|
||||||
@@ -794,15 +794,15 @@ static int yaffs_sync_object(struct file
|
|
||||||
|
|
||||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
|
|
||||||
static const struct file_operations yaffs_file_operations = {
|
|
||||||
- .read = do_sync_read,
|
|
||||||
- .write = do_sync_write,
|
|
||||||
- .aio_read = generic_file_aio_read,
|
|
||||||
- .aio_write = generic_file_aio_write,
|
|
||||||
+ .read = new_sync_read,
|
|
||||||
+ .write = new_sync_write,
|
|
||||||
+ .read_iter = generic_file_read_iter,
|
|
||||||
+ .write_iter = generic_file_write_iter,
|
|
||||||
.mmap = generic_file_mmap,
|
|
||||||
.flush = yaffs_file_flush,
|
|
||||||
.fsync = yaffs_sync_object,
|
|
||||||
.splice_read = generic_file_splice_read,
|
|
||||||
- .splice_write = generic_file_splice_write,
|
|
||||||
+ .splice_write = iter_file_splice_write,
|
|
||||||
.llseek = generic_file_llseek,
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1050,7 +1050,7 @@ static int yaffs_readlink(struct dentry
|
|
||||||
if (!alias)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
- ret = vfs_readlink(dentry, buffer, buflen, alias);
|
|
||||||
+ ret = readlink_copy(buffer, buflen, alias);
|
|
||||||
kfree(alias);
|
|
||||||
return ret;
|
|
||||||
}
|
|
|
@ -1,155 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
|
||||||
@@ -329,6 +329,33 @@ static int yaffs_readpage(struct file *f
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
|
|
||||||
+#define YCRED_FSUID() from_kuid(&init_user_ns, current_fsuid())
|
|
||||||
+#define YCRED_FSGID() from_kgid(&init_user_ns, current_fsgid())
|
|
||||||
+#else
|
|
||||||
+#define YCRED_FSUID() YCRED(current)->fsuid
|
|
||||||
+#define YCRED_FSGID() YCRED(current)->fsgid
|
|
||||||
+
|
|
||||||
+static inline uid_t i_uid_read(const struct inode *inode)
|
|
||||||
+{
|
|
||||||
+ return inode->i_uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline gid_t i_gid_read(const struct inode *inode)
|
|
||||||
+{
|
|
||||||
+ return inode->i_gid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void i_uid_write(struct inode *inode, uid_t uid)
|
|
||||||
+{
|
|
||||||
+ inode->i_uid = uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void i_gid_write(struct inode *inode, gid_t gid)
|
|
||||||
+{
|
|
||||||
+ inode->i_gid = gid;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
|
|
||||||
{
|
|
||||||
@@ -1225,9 +1252,9 @@ static int yaffs_mknod(struct inode *dir
|
|
||||||
struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
|
|
||||||
|
|
||||||
int error = -ENOSPC;
|
|
||||||
- uid_t uid = YCRED(current)->fsuid;
|
|
||||||
+ uid_t uid = YCRED_FSUID();
|
|
||||||
gid_t gid =
|
|
||||||
- (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
|
|
||||||
+ (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
|
|
||||||
|
|
||||||
if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
|
|
||||||
mode |= S_ISGID;
|
|
||||||
@@ -1424,9 +1451,9 @@ static int yaffs_symlink(struct inode *d
|
|
||||||
{
|
|
||||||
struct yaffs_obj *obj;
|
|
||||||
struct yaffs_dev *dev;
|
|
||||||
- uid_t uid = YCRED(current)->fsuid;
|
|
||||||
+ uid_t uid = YCRED_FSUID();
|
|
||||||
gid_t gid =
|
|
||||||
- (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
|
|
||||||
+ (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
|
|
||||||
|
|
||||||
yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
|
|
||||||
|
|
||||||
@@ -1829,8 +1856,8 @@ static void yaffs_fill_inode_from_obj(st
|
|
||||||
|
|
||||||
inode->i_ino = obj->obj_id;
|
|
||||||
inode->i_mode = obj->yst_mode;
|
|
||||||
- inode->i_uid = obj->yst_uid;
|
|
||||||
- inode->i_gid = obj->yst_gid;
|
|
||||||
+ i_uid_write(inode, obj->yst_uid);
|
|
||||||
+ i_gid_write(inode, obj->yst_gid);
|
|
||||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
|
|
||||||
inode->i_blksize = inode->i_sb->s_blocksize;
|
|
||||||
#endif
|
|
||||||
@@ -1856,7 +1883,7 @@ static void yaffs_fill_inode_from_obj(st
|
|
||||||
|
|
||||||
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, i_uid_read(inode), i_gid_read(inode),
|
|
||||||
inode->i_size, atomic_read(&inode->i_count));
|
|
||||||
|
|
||||||
switch (obj->yst_mode & S_IFMT) {
|
|
||||||
--- a/fs/yaffs2/yaffs_attribs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_attribs.c
|
|
||||||
@@ -14,6 +14,48 @@
|
|
||||||
#include "yaffs_guts.h"
|
|
||||||
#include "yaffs_attribs.h"
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
|
|
||||||
+static inline uid_t ia_uid_read(const struct iattr *iattr)
|
|
||||||
+{
|
|
||||||
+ return from_kuid(&init_user_ns, iattr->ia_uid);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline gid_t ia_gid_read(const struct iattr *iattr)
|
|
||||||
+{
|
|
||||||
+ return from_kgid(&init_user_ns, iattr->ia_gid);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_uid = make_kuid(&init_user_ns, uid);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_gid = make_kgid(&init_user_ns, gid);
|
|
||||||
+}
|
|
||||||
+#else
|
|
||||||
+static inline uid_t ia_uid_read(const struct iattr *iattr)
|
|
||||||
+{
|
|
||||||
+ return iattr->ia_uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline gid_t ia_gid_read(const struct iattr *inode)
|
|
||||||
+{
|
|
||||||
+ return iattr->ia_gid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_uid = uid;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
|
|
||||||
+{
|
|
||||||
+ iattr->ia_gid = gid;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
|
|
||||||
{
|
|
||||||
obj->yst_uid = oh->yst_uid;
|
|
||||||
@@ -77,9 +119,9 @@ int yaffs_set_attribs(struct yaffs_obj *
|
|
||||||
if (valid & ATTR_MODE)
|
|
||||||
obj->yst_mode = attr->ia_mode;
|
|
||||||
if (valid & ATTR_UID)
|
|
||||||
- obj->yst_uid = attr->ia_uid;
|
|
||||||
+ obj->yst_uid = ia_uid_read(attr);
|
|
||||||
if (valid & ATTR_GID)
|
|
||||||
- obj->yst_gid = attr->ia_gid;
|
|
||||||
+ obj->yst_gid = ia_gid_read(attr);
|
|
||||||
|
|
||||||
if (valid & ATTR_ATIME)
|
|
||||||
obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
|
|
||||||
@@ -103,9 +145,9 @@ int yaffs_get_attribs(struct yaffs_obj *
|
|
||||||
|
|
||||||
attr->ia_mode = obj->yst_mode;
|
|
||||||
valid |= ATTR_MODE;
|
|
||||||
- attr->ia_uid = obj->yst_uid;
|
|
||||||
+ ia_uid_write(attr, obj->yst_uid);
|
|
||||||
valid |= ATTR_UID;
|
|
||||||
- attr->ia_gid = obj->yst_gid;
|
|
||||||
+ ia_gid_write(attr, obj->yst_gid);
|
|
||||||
valid |= ATTR_GID;
|
|
||||||
|
|
||||||
Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
--- a/fs/yaffs2/yaffs_vfs.c
|
||||||
|
+++ b/fs/yaffs2/yaffs_vfs.c
|
||||||
|
@@ -738,7 +738,7 @@ static int yaffs_file_flush(struct file
|
||||||
|
|
||||||
|
yaffs_gross_lock(dev);
|
||||||
|
|
||||||
|
- yaffs_flush_file(obj, 1, 0);
|
||||||
|
+ yaffs_flush_file(obj, 1, 0, 1);
|
||||||
|
|
||||||
|
yaffs_gross_unlock(dev);
|
||||||
|
|
||||||
|
@@ -768,7 +768,7 @@ static int yaffs_sync_object(struct file
|
||||||
|
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, 1);
|
||||||
|
yaffs_gross_unlock(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -2187,7 +2187,7 @@ static void yaffs_flush_inodes(struct su
|
||||||
|
yaffs_trace(YAFFS_TRACE_OS,
|
||||||
|
"flushing obj %d",
|
||||||
|
obj->obj_id);
|
||||||
|
- yaffs_flush_file(obj, 1, 0);
|
||||||
|
+ yaffs_flush_file(obj, 1, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -2200,7 +2200,7 @@ static void yaffs_flush_super(struct sup
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
|
||||||
@@ -3025,6 +3025,7 @@ static DECLARE_FSTYPE(yaffs2_fs_type, "y
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
|
|
||||||
static struct proc_dir_entry *my_proc_entry;
|
|
||||||
|
|
||||||
static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
|
|
||||||
@@ -3398,6 +3399,7 @@ static int yaffs_proc_write(struct file
|
|
||||||
return yaffs_proc_debug_write(file, buf, count, data);
|
|
||||||
return yaffs_proc_write_trace_options(file, buf, count, data);
|
|
||||||
}
|
|
||||||
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) */
|
|
||||||
|
|
||||||
/* Stuff to handle installation of file systems */
|
|
||||||
struct file_system_to_install {
|
|
||||||
@@ -3421,6 +3423,7 @@ static int __init init_yaffs_fs(void)
|
|
||||||
|
|
||||||
mutex_init(&yaffs_context_lock);
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
|
|
||||||
/* Install the proc_fs entries */
|
|
||||||
my_proc_entry = create_proc_entry("yaffs",
|
|
||||||
S_IRUGO | S_IFREG, YPROC_ROOT);
|
|
||||||
@@ -3432,6 +3435,7 @@ static int __init init_yaffs_fs(void)
|
|
||||||
} else {
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
/* Now add the file system entries */
|
|
||||||
|
|
||||||
@@ -3468,7 +3472,9 @@ static void __exit exit_yaffs_fs(void)
|
|
||||||
yaffs_trace(YAFFS_TRACE_ALWAYS,
|
|
||||||
"yaffs built " __DATE__ " " __TIME__ " removing.");
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
|
|
||||||
remove_proc_entry("yaffs", YPROC_ROOT);
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
fsinst = fs_to_install;
|
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
|
||||||
@@ -1701,6 +1701,110 @@ static void yaffs_remove_obj_callback(st
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------*/
|
|
||||||
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
|
|
||||||
+static int yaffs_readdir(struct file *file, struct dir_context *ctx)
|
|
||||||
+{
|
|
||||||
+ struct yaffs_obj *obj;
|
|
||||||
+ struct yaffs_dev *dev;
|
|
||||||
+ struct yaffs_search_context *sc;
|
|
||||||
+ struct inode *inode = file->f_dentry->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(file->f_dentry);
|
|
||||||
+ dev = obj->my_dev;
|
|
||||||
+
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+
|
|
||||||
+ yaffs_dev_to_lc(dev)->readdir_process = current;
|
|
||||||
+
|
|
||||||
+ offset = ctx->pos;
|
|
||||||
+
|
|
||||||
+ sc = yaffs_new_search(obj);
|
|
||||||
+ if (!sc) {
|
|
||||||
+ ret_val = -ENOMEM;
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ yaffs_trace(YAFFS_TRACE_OS,
|
|
||||||
+ "yaffs_readdir: starting at %d", (int)offset);
|
|
||||||
+
|
|
||||||
+ if (offset == 0) {
|
|
||||||
+ yaffs_trace(YAFFS_TRACE_OS,
|
|
||||||
+ "yaffs_readdir: entry . ino %d",
|
|
||||||
+ (int)inode->i_ino);
|
|
||||||
+ yaffs_gross_unlock(dev);
|
|
||||||
+ if (!dir_emit_dot(file, ctx)) {
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ offset++;
|
|
||||||
+ ctx->pos++;
|
|
||||||
+ }
|
|
||||||
+ if (offset == 1) {
|
|
||||||
+ yaffs_trace(YAFFS_TRACE_OS,
|
|
||||||
+ "yaffs_readdir: entry .. ino %d",
|
|
||||||
+ (int)file->f_dentry->d_parent->d_inode->i_ino);
|
|
||||||
+ yaffs_gross_unlock(dev);
|
|
||||||
+ if (!dir_emit_dotdot(file, ctx)) {
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ offset++;
|
|
||||||
+ ctx->pos++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ curoffs = 1;
|
|
||||||
+
|
|
||||||
+ /* If the directory has changed since the open or last call to
|
|
||||||
+ readdir, rewind to after the 2 canned entries. */
|
|
||||||
+ if (file->f_version != inode->i_version) {
|
|
||||||
+ offset = 2;
|
|
||||||
+ ctx->pos = offset;
|
|
||||||
+ file->f_version = inode->i_version;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ while (sc->next_return) {
|
|
||||||
+ curoffs++;
|
|
||||||
+ l = sc->next_return;
|
|
||||||
+ if (curoffs >= offset) {
|
|
||||||
+ 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(ctx, name, strlen(name),
|
|
||||||
+ this_inode, this_type) < 0) {
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ yaffs_gross_lock(dev);
|
|
||||||
+
|
|
||||||
+ offset++;
|
|
||||||
+ ctx->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;
|
|
||||||
@@ -1807,10 +1911,15 @@ out:
|
|
||||||
|
|
||||||
return ret_val;
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
static const struct file_operations yaffs_dir_operations = {
|
|
||||||
.read = generic_read_dir,
|
|
||||||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
|
|
||||||
+ .iterate = yaffs_readdir,
|
|
||||||
+#else
|
|
||||||
.readdir = yaffs_readdir,
|
|
||||||
+#endif
|
|
||||||
.fsync = yaffs_sync_object,
|
|
||||||
.llseek = generic_file_llseek,
|
|
||||||
};
|
|
|
@ -4,7 +4,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
---
|
---
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
--- a/fs/yaffs2/yaffs_vfs.c
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
+++ b/fs/yaffs2/yaffs_vfs.c
|
||||||
@@ -2634,6 +2634,7 @@ static const struct super_operations yaf
|
@@ -2605,6 +2605,7 @@ static const struct super_operations yaf
|
||||||
|
|
||||||
struct yaffs_options {
|
struct yaffs_options {
|
||||||
int inband_tags;
|
int inband_tags;
|
||||||
|
@ -12,7 +12,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
int skip_checkpoint_read;
|
int skip_checkpoint_read;
|
||||||
int skip_checkpoint_write;
|
int skip_checkpoint_write;
|
||||||
int no_cache;
|
int no_cache;
|
||||||
@@ -2673,6 +2674,8 @@ static int yaffs_parse_options(struct ya
|
@@ -2644,6 +2645,8 @@ static int yaffs_parse_options(struct ya
|
||||||
|
|
||||||
if (!strcmp(cur_opt, "inband-tags")) {
|
if (!strcmp(cur_opt, "inband-tags")) {
|
||||||
options->inband_tags = 1;
|
options->inband_tags = 1;
|
||||||
|
@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
} else if (!strcmp(cur_opt, "tags-ecc-off")) {
|
} else if (!strcmp(cur_opt, "tags-ecc-off")) {
|
||||||
options->tags_ecc_on = 0;
|
options->tags_ecc_on = 0;
|
||||||
options->tags_ecc_overridden = 1;
|
options->tags_ecc_overridden = 1;
|
||||||
@@ -2746,7 +2749,6 @@ static struct super_block *yaffs_interna
|
@@ -2717,7 +2720,6 @@ static struct super_block *yaffs_interna
|
||||||
struct yaffs_param *param;
|
struct yaffs_param *param;
|
||||||
|
|
||||||
int read_only = 0;
|
int read_only = 0;
|
||||||
|
@ -29,7 +29,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
|
|
||||||
struct yaffs_options options;
|
struct yaffs_options options;
|
||||||
|
|
||||||
@@ -2786,6 +2788,9 @@ static struct super_block *yaffs_interna
|
@@ -2757,6 +2759,9 @@ static struct super_block *yaffs_interna
|
||||||
|
|
||||||
memset(&options, 0, sizeof(options));
|
memset(&options, 0, sizeof(options));
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
if (yaffs_parse_options(&options, data_str)) {
|
if (yaffs_parse_options(&options, data_str)) {
|
||||||
/* Option parsing failed */
|
/* Option parsing failed */
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2819,17 +2824,22 @@ static struct super_block *yaffs_interna
|
@@ -2790,17 +2795,22 @@ static struct super_block *yaffs_interna
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Added NCB 26/5/2006 for completeness */
|
/* Added NCB 26/5/2006 for completeness */
|
||||||
|
@ -68,7 +68,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* OK, so if we got here, we have an MTD that's NAND and looks
|
/* OK, so if we got here, we have an MTD that's NAND and looks
|
||||||
@@ -2890,7 +2900,8 @@ static struct super_block *yaffs_interna
|
@@ -2857,7 +2867,8 @@ static struct super_block *yaffs_interna
|
||||||
|
|
||||||
param->n_reserved_blocks = 5;
|
param->n_reserved_blocks = 5;
|
||||||
param->n_caches = (options.no_cache) ? 0 : 10;
|
param->n_caches = (options.no_cache) ? 0 : 10;
|
||||||
|
@ -80,15 +80,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
if (options.lazy_loading_overridden)
|
if (options.lazy_loading_overridden)
|
||||||
--- a/fs/yaffs2/yaffs_mtdif.c
|
--- a/fs/yaffs2/yaffs_mtdif.c
|
||||||
+++ b/fs/yaffs2/yaffs_mtdif.c
|
+++ b/fs/yaffs2/yaffs_mtdif.c
|
||||||
@@ -16,6 +16,7 @@
|
@@ -278,7 +278,8 @@ struct mtd_info * yaffs_get_mtd_device(d
|
||||||
#include "yaffs_mtdif.h"
|
|
||||||
|
|
||||||
#include "linux/mtd/mtd.h"
|
|
||||||
+#include "uapi/linux/major.h"
|
|
||||||
#include "linux/types.h"
|
|
||||||
#include "linux/time.h"
|
|
||||||
#include "linux/mtd/nand.h"
|
|
||||||
@@ -276,7 +277,8 @@ struct mtd_info * yaffs_get_mtd_device(d
|
|
||||||
return mtd;
|
return mtd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +90,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||||
{
|
{
|
||||||
if (yaffs_version == 2) {
|
if (yaffs_version == 2) {
|
||||||
if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
|
if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
|
||||||
@@ -295,6 +297,12 @@ int yaffs_verify_mtd(struct mtd_info *mt
|
@@ -297,6 +298,12 @@ int yaffs_verify_mtd(struct mtd_info *mt
|
||||||
);
|
);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
--- a/fs/yaffs2/yaffs_vfs.c
|
||||||
|
+++ b/fs/yaffs2/yaffs_vfs.c
|
||||||
|
@@ -774,7 +774,21 @@ static int yaffs_sync_object(struct file
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
|
||||||
|
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
|
||||||
|
+static const struct file_operations yaffs_file_operations = {
|
||||||
|
+ .read = new_sync_read,
|
||||||
|
+ .read_iter = generic_file_read_iter,
|
||||||
|
+ .write = new_sync_write,
|
||||||
|
+ .write_iter = generic_file_write_iter,
|
||||||
|
+ .mmap = generic_file_mmap,
|
||||||
|
+ .flush = yaffs_file_flush,
|
||||||
|
+ .fsync = yaffs_sync_object,
|
||||||
|
+ .splice_read = generic_file_splice_read,
|
||||||
|
+ .splice_write = iter_file_splice_write,
|
||||||
|
+ .llseek = generic_file_llseek,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
|
||||||
|
static const struct file_operations yaffs_file_operations = {
|
||||||
|
.read = do_sync_read,
|
||||||
|
.write = do_sync_write,
|
|
@ -1,32 +0,0 @@
|
||||||
--- a/fs/yaffs2/yaffs_vfs.c
|
|
||||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
|
||||||
@@ -794,15 +794,15 @@ static int yaffs_sync_object(struct file
|
|
||||||
|
|
||||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
|
|
||||||
static const struct file_operations yaffs_file_operations = {
|
|
||||||
- .read = do_sync_read,
|
|
||||||
- .write = do_sync_write,
|
|
||||||
- .aio_read = generic_file_aio_read,
|
|
||||||
- .aio_write = generic_file_aio_write,
|
|
||||||
+ .read = new_sync_read,
|
|
||||||
+ .write = new_sync_write,
|
|
||||||
+ .read_iter = generic_file_read_iter,
|
|
||||||
+ .write_iter = generic_file_write_iter,
|
|
||||||
.mmap = generic_file_mmap,
|
|
||||||
.flush = yaffs_file_flush,
|
|
||||||
.fsync = yaffs_sync_object,
|
|
||||||
.splice_read = generic_file_splice_read,
|
|
||||||
- .splice_write = generic_file_splice_write,
|
|
||||||
+ .splice_write = iter_file_splice_write,
|
|
||||||
.llseek = generic_file_llseek,
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1050,7 +1050,7 @@ static int yaffs_readlink(struct dentry
|
|
||||||
if (!alias)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
- ret = vfs_readlink(dentry, buffer, buflen, alias);
|
|
||||||
+ ret = readlink_copy(buffer, buflen, alias);
|
|
||||||
kfree(alias);
|
|
||||||
return ret;
|
|
||||||
}
|
|
Loading…
Reference in New Issue