#include "yaffs_nandemul.h"
// 2 MB of RAM for emulation
#define YAFFS_RAM_EMULATION_SIZE 0x200000
-#endif // YAFFS_RAM_ENABLED
+#endif //YAFFS_RAM_ENABLED
#ifdef YAFFS_MTD_ENABLED
#include <linux/mtd/mtd.h>
+static void yaffs_put_super(struct super_block *sb);
+
static ssize_t yaffs_file_read(struct file *f, char *buf, size_t n, loff_t *pos);
static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t *pos);
static void yaffs_read_inode (struct inode *inode);
static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent);
static void yaffs_put_inode (struct inode *inode);
+static int yaffs_readpage(struct file *file, struct page * page);
+
+
+static int yaffs_readlink(struct dentry *dentry, char *buffer, int buflen);
+static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);
+
+
-//static int yaffs_readpage(struct file*,struct page *
-static struct address_space_operations yaffs_address_ops = {
-// readpage: yaffs_readpage,
+
+static struct address_space_operations yaffs_file_address_operations = {
+ readpage: yaffs_readpage,
// prepare_write: yaffs_prepare_write,
// commit_write: yaffs_commit_write
};
static struct file_operations yaffs_file_operations = {
read: yaffs_file_read,
write: yaffs_file_write,
-// mmap: generic_file_mmap,
+ mmap: generic_file_mmap,
fsync: yaffs_sync_object,
};
};
-
-static struct file_operations yaffs_dir_operations = {
- read: generic_read_dir,
- readdir: yaffs_readdir,
- fsync: yaffs_sync_object,
+struct inode_operations yaffs_symlink_inode_operations =
+{
+ readlink: yaffs_readlink,
+ follow_link: yaffs_follow_link,
+ setattr: yaffs_setattr
};
static struct inode_operations yaffs_dir_inode_operations = {
setattr: yaffs_setattr,
};
+static struct file_operations yaffs_dir_operations = {
+ read: generic_read_dir,
+ readdir: yaffs_readdir,
+ fsync: yaffs_sync_object,
+};
+
+
static struct super_operations yaffs_super_ops = {
statfs: yaffs_statfs,
read_inode: yaffs_read_inode,
put_inode: yaffs_put_inode,
+ put_super: yaffs_put_super,
// read_inode:
// remount_fs:
// clear_inode:
};
+
+
+
+static int yaffs_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+ unsigned char *alias;
+ int ret;
+
+ alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
+
+ if(!alias)
+ return -ENOMEM;
+
+ ret = vfs_readlink(dentry, buffer, buflen, alias);
+ kfree(alias);
+ return ret;
+}
+
+static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ unsigned char *alias;
+ int ret;
+ alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
+
+ if(!alias)
+ return -ENOMEM;
+
+ ret = vfs_follow_link(nd,alias);
+ kfree(alias);
+ return ret;
+}
+
+
struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj);
/*
obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir),dentry->d_name.name);
+ obj = yaffs_GetEquivalentObject(obj); // in case it was a hardlink
+
if(obj)
{
T((KERN_DEBUG"yaffs_lookup found %d\n",obj->objectId));
static void yaffs_put_inode(struct inode *inode)
{
T(("yaffs_put_inode: ino %d, count %d\n",(int)inode->i_ino, atomic_read(&inode->i_count)));
+
+ yaffs_FlushFile(yaffs_InodeToObject(inode));
+
}
-#ifdef YAFFS_ADDRESS_OPS
-static int yaffs_readpage(struct file *file, struct page * page)
+
+
+static int yaffs_readpage(struct file *f, struct page * pg)
{
- T((KERN_DEBUG"yaffs_readpage\n"));
+ struct yaffs_Object *obj;
+ unsigned char *pg_buf;
+ int ret;
+
+ T((KERN_DEBUG"yaffs_readpage at %08x, size %08x\n",
+ pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE));
- // TODO
- return 0;
+ obj = yaffs_DentryToObject(f->f_dentry);
+
+ //down(obj->sem);
+
+ if (!PageLocked(pg))
+ PAGE_BUG(pg);
+
+ pg_buf = kmap(pg);
+ /* FIXME: Can kmap fail? */
+
+ ret = yaffs_ReadDataFromFile(obj,pg_buf, pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE);
+
+ if(ret >= 0) ret = 0;
+
+ if (ret) {
+ ClearPageUptodate(pg);
+ SetPageError(pg);
+ } else {
+ SetPageUptodate(pg);
+ ClearPageError(pg);
+ }
+
+ flush_dcache_page(pg);
+ kunmap(pg);
+
+ UnlockPage(pg);
+
+ //up(&obj->sem);
+
+ T((KERN_DEBUG"yaffs_readpage done\n"));
+ return ret;
}
+#ifdef YAFFS_ADDRESS_OPS
+
static int yaffs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
{
T((KERN_DEBUG"yaffs_prepare_write\n"));
inode->i_blksize = YAFFS_BYTES_PER_CHUNK;
inode->i_blocks = 0;
inode->i_rdev = NODEV;
- inode->i_mapping->a_ops = &yaffs_address_ops;
inode->i_atime = obj->st_atime;
inode->i_mtime = obj->st_mtime;
inode->i_ctime = obj->st_ctime;
switch (obj->st_mode & S_IFMT)
{
default:
- // init_special_inode(inode, mode, dev);
+ // init_special_inode(inode, mode, dev);
break;
case S_IFREG: // file
inode->i_op = &yaffs_file_inode_operations;
inode->i_fop = &yaffs_file_operations;
+ inode->i_mapping->a_ops = &yaffs_file_address_operations;
break;
case S_IFDIR: // directory
inode->i_op = &yaffs_dir_inode_operations;
inode->i_fop = &yaffs_dir_operations;
break;
case S_IFLNK: // symlink
- inode->i_op = &page_symlink_inode_operations;
+ inode->i_op = &yaffs_symlink_inode_operations;
break;
}
break;
case S_IFLNK: // symlink
T((KERN_DEBUG"yaffs_mknod: making file\n"));
- obj = NULL; // Todo
+ obj = NULL; // Do we ever get here?
break;
}
if(obj)
{
inode = yaffs_get_inode(dir->i_sb, mode, dev, obj);
-
-// did not fix dir bug if((mode & S_IFMT) == S_IFDIR) atomic_inc(&inode->i_count);
-
d_instantiate(dentry, inode);
T((KERN_DEBUG"yaffs_mknod created object %d count = %d\n",obj->objectId,atomic_read(&inode->i_count)));
error = 0;
/*
- * Link a file..
+ * Create a link...
*/
static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry)
{
struct inode *inode = old_dentry->d_inode;
+ yaffs_Object *obj = NULL;
+ yaffs_Object *link=NULL;
T((KERN_DEBUG"yaffs_link\n"));
- return -EPERM; //Todo
+ obj = yaffs_InodeToObject(inode);
-
- if (S_ISDIR(inode->i_mode))
- return -EPERM;
-
-
- return 0;
+ link = yaffs_Link(yaffs_InodeToObject(dir),dentry->d_name.name,obj);
+
+ if(link)
+ {
+ return 0;
+ }
+
+
+ return -EPERM;
}
static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
{
- int error;
+ yaffs_Object *obj;
T((KERN_DEBUG"yaffs_symlink\n"));
-
- return -ENOMEM; //Todo
+ obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name,
+ S_IFLNK | S_IRWXUGO, current->uid, current->gid,
+ symname);
- error = yaffs_mknod(dir, dentry, S_IFLNK | S_IRWXUGO, 0);
- return error;
+ if(obj)
+ {
+ T((KERN_DEBUG"symlink created OK\n"));
+ return 0;
+ }
+ else
+ {
+ T((KERN_DEBUG"symlink not created\n"));
+
+ }
+
+ return -ENOMEM;
}
static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync)
}
+static void yaffs_put_super(struct super_block *sb)
+{
+ yaffs_Device *dev = yaffs_SuperToDevice(sb);
+
+ if(dev->putSuperFunc)
+ {
+ dev->putSuperFunc(sb);
+ }
+}
+
+
+#ifdef YAFFS_MTD_ENABLED
+
+static void yaffs_MTDPutSuper(struct super_block *sb)
+{
+
+ struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice;
+
+ if(mtd->sync)
+ {
+ mtd->sync(mtd);
+ }
+
+ put_mtd_device(mtd);
+}
+
+#endif
+
static struct super_block *yaffs_internal_read_super(int useRam, struct super_block * sb, void * data, int silent)
{
struct inode * inode;
if(useRam)
{
-#if YAFFS_RAM_ENABLED
+#ifdef YAFFS_RAM_ENABLED
// Set the yaffs_Device up for ram emulation
sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL);
dev->readChunkFromNAND = nandemul_ReadChunkFromNAND;
dev->eraseBlockInNAND = nandemul_EraseBlockInNAND;
dev->initialiseNAND = nandemul_InitialiseNAND;
+
#endif
}
dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND;
dev->initialiseNAND = nandmtd_InitialiseNAND;
+ dev->putSuperFunc = yaffs_MTDPutSuper;
#endif
}
remove_proc_entry("yaffs",&proc_root);
#ifdef YAFFS_RAM_ENABLED
-// NCB unregister_filesystem(&yaffs_fs_type);
unregister_filesystem(&yaffs_ram_fs_type);
#endif
#ifdef YAFFS_MTD_ENABLED
-// NCB unregister_filesystem(&yaffs_ram_fs_type);
unregister_filesystem(&yaffs_fs_type);
#endif