* This is the file system front-end to YAFFS that hooks it up to
* the VFS.
*
- * Special notes:
+ * Special notes:
* >> sb->u.generic_sbp points to the yaffs_Device associated with this superblock
* >> inode->u.generic_ip points to the associated yaffs_Object.
*/
#include "yaffs_guts.h"
#ifdef YAFFS_RAM_ENABLED
-#include "yaffs_nandemul.h"
+#include "yaffs_nandemul.h"
// 2 MB of RAM for emulation
#define YAFFS_RAM_EMULATION_SIZE 0x200000
#endif // YAFFS_RAM_ENABLED
create: yaffs_create,
lookup: yaffs_lookup,
link: yaffs_link,
- unlink: yaffs_unlink,
+ unlink: yaffs_unlink,
symlink: yaffs_symlink,
mkdir: yaffs_mkdir,
rmdir: yaffs_unlink,
{
yaffs_Object *obj;
struct inode *inode;
-
-
+
+
T((KERN_DEBUG"yaffs_lookup for %d:%s\n",yaffs_InodeToObject(dir)->objectId,dentry->d_name.name));
-
+
obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir),dentry->d_name.name);
-
+
if(obj)
{
T((KERN_DEBUG"yaffs_lookup found %d\n",obj->objectId));
-
+
inode = yaffs_get_inode(dir->i_sb, obj->st_mode,0,obj);
-
+
if(inode)
{
T((KERN_DEBUG"yaffs_loookup looks good\n"));
else
{
T((KERN_DEBUG"yaffs_lookup not found\n"));
-
+
}
return NULL;
-
+
}
// For now put inode is just for debugging
static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj)
{
- if (inode && obj)
+ if (inode && obj)
{
inode->i_ino = obj->objectId;
inode->i_mode = obj->st_mode;
inode->i_ctime = obj->st_ctime;
inode->i_size = yaffs_GetObjectFileLength(obj);
inode->i_nlink = yaffs_GetObjectLinkCount(obj);
-
+
T((KERN_DEBUG"yaffs_FillInode mode %x uid %d gid %d size %d count %d\n",
inode->i_mode, inode->i_uid, inode->i_gid, (int)inode->i_size, atomic_read(&inode->i_count)));
-
- switch (obj->st_mode & S_IFMT)
+
+ switch (obj->st_mode & S_IFMT)
{
default:
// init_special_inode(inode, mode, dev);
break;
- case S_IFREG: // file
+ case S_IFREG: // file
inode->i_op = &yaffs_file_inode_operations;
inode->i_fop = &yaffs_file_operations;
break;
inode->i_op = &page_symlink_inode_operations;
break;
}
-
-
+
+
inode->u.generic_ip = obj;
-
+
}
else
{
struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj)
{
struct inode * inode;
-
+
T((KERN_DEBUG"yaffs_get_inode for object %d\n",obj->objectId));
inode = iget(sb,obj->objectId);
yaffs_Object *obj;
int nRead,ipos;
struct inode *inode;
-
+
T((KERN_DEBUG"yaffs_file_read\n"));
obj = yaffs_DentryToObject(f->f_dentry);
inode = f->f_dentry->d_inode;
-
- if (*pos < inode->i_size)
+
+ if (*pos < inode->i_size)
{
if (*pos + n > inode->i_size)
{
{
n = 0;
}
-
+
nRead = yaffs_ReadDataFromFile(obj,buf,*pos,n);
if(nRead > 0)
{
ipos = *pos;
T((KERN_DEBUG"yaffs_file_read read %d bytes, %d read at %d\n",n,nRead,ipos));
return nRead;
-
+
}
static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t *pos)
yaffs_Object *obj;
int nWritten,ipos;
struct inode *inode;
-
+
obj = yaffs_DentryToObject(f->f_dentry);
inode = f->f_dentry->d_inode;
nWritten = yaffs_WriteDataToFile(obj,buf,*pos,n);
inode->i_size = *pos;
T((KERN_DEBUG"yaffs_file_write size updated to %d\n",ipos));
}
-
+
}
- return nWritten;
+ return nWritten;
}
yaffs_Object *obj;
struct inode *inode = f->f_dentry->d_inode;
unsigned long offset, curoffs;
- struct list_head *i;
+ struct list_head *i;
yaffs_Object *l;
-
+
char name[YAFFS_MAX_NAME_LENGTH +1];
-
+
obj = yaffs_DentryToObject(f->f_dentry);
-
+
offset = f->f_pos;
-
+
T(("yaffs_readdir: starting at %d\n",(int)offset));
-
+
if(offset == 0)
{
T((KERN_DEBUG"yaffs_readdir: entry . ino %d \n",(int)inode->i_ino));
offset++;
f->f_pos++;
}
-
+
curoffs = 1;
-
+
//down(&obj->sem);
-
+
list_for_each(i,&obj->variant.directoryVariant.children)
{
curoffs++;
if(curoffs >= offset)
- {
+ {
l = list_entry(i, yaffs_Object,siblings);
-
- yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
+
+ yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
T((KERN_DEBUG"yaffs_readdir: %s inode %d\n",name,yaffs_GetObjectInode(l)));
-
+
if(filldir(dirent,
name,
strlen(name),
{
goto up_and_out;
}
-
+
offset++;
- f->f_pos++;
+ f->f_pos++;
}
}
up_and_out:
//up(&obj->sem);
-
+
out:
return 0;
}
static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
{
struct inode *inode;
-
+
yaffs_Object *obj = NULL;
yaffs_Object *parent = yaffs_InodeToObject(dir);
-
+
int error = -ENOSPC;
if(parent)
T((KERN_DEBUG"yaffs_mknod: could not get parent object\n"));
return -EPERM;
}
-
+
T(("yaffs_mknod: making oject for %s, mode %x\n",
dentry->d_name.name, mode));
- switch (mode & S_IFMT)
+ switch (mode & S_IFMT)
{
default:
-
+
break;
- case S_IFREG: // file
+ case S_IFREG: // file
T((KERN_DEBUG"yaffs_mknod: making file\n"));
obj = yaffs_MknodFile(parent,dentry->d_name.name,mode,current->uid, current->gid);
break;
obj = NULL; // Todo
break;
}
-
+
if(obj)
{
inode = yaffs_get_inode(dir->i_sb, mode, dev, obj);
T((KERN_DEBUG"yaffs_mknod failed making object\n"));
error = -ENOMEM;
}
-
+
return error;
}
static int yaffs_unlink(struct inode * dir, struct dentry *dentry)
{
-
+
T((KERN_DEBUG"yaffs_unlink\n"));
-
+
if(yaffs_Unlink(yaffs_InodeToObject(dir),dentry->d_name.name) == YAFFS_OK)
{
return 0;
static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry)
{
struct inode *inode = old_dentry->d_inode;
-
+
T((KERN_DEBUG"yaffs_link\n"));
-
+
return -EPERM; //Todo
-
+
if (S_ISDIR(inode->i_mode))
return -EPERM;
static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
{
int error;
-
+
T((KERN_DEBUG"yaffs_symlink\n"));
-
+
return -ENOMEM; //Todo
error = yaffs_mknod(dir, dentry, S_IFLNK | S_IRWXUGO, 0);
*/
static int yaffs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry)
{
-
-
+
+
if( yaffs_RenameObject(yaffs_InodeToObject(old_dir),old_dentry->d_name.name,
yaffs_InodeToObject(new_dir),new_dentry->d_name.name) == YAFFS_OK)
{
{
return -ENOTEMPTY;
}
-
+
}
{
struct inode *inode = dentry->d_inode;
int error;
-
+
T((KERN_DEBUG"yaffs_setattr\n"));
-
+
if((error = inode_change_ok(inode,attr)) == 0)
{
-
+
if(yaffs_SetAttributes(yaffs_InodeToObject(inode),attr) == YAFFS_OK)
{
error = 0;
static void yaffs_read_inode (struct inode *inode)
{
- yaffs_Object *obj ;
-
+ yaffs_Object *obj ;
+
T((KERN_DEBUG"yaffs_read_inode for %d\n",(int)inode->i_ino));
obj = yaffs_FindObjectByNumber(yaffs_SuperToDevice(inode->i_sb),inode->i_ino);
-
+
yaffs_FillInodeFromObject(inode,obj);
}
struct inode * inode;
struct dentry * root;
yaffs_Device *dev;
+
-
- T(("yaffs_read_super:\n"));
+ T(("yaffs_read_super: %s\n", useRam ? "RAM" : "MTD"));
sb->s_blocksize = YAFFS_BYTES_PER_CHUNK;
sb->s_blocksize_bits = YAFFS_CHUNK_SIZE_SHIFT;
sb->s_magic = YAFFS_MAGIC;
sb->s_op = &yaffs_super_ops;
-
+
if(!sb)
- printk(KERN_INFO"sb is NULL\n");
+ printk(KERN_INFO"yaffs: sb is NULL\n");
else if(!sb->s_dev)
- printk(KERN_INFO"sb->s_dev is NULL\n");
+ printk(KERN_INFO"yaffs: sb->s_dev is NULL\n");
else if(! kdevname(sb->s_dev))
- printk(KERN_INFO"kdevname is NULL\n");
+ printk(KERN_INFO"yaffs: kdevname is NULL\n");
else
- printk(KERN_INFO"dev is %d name is \"%s\"\n", sb->s_dev, kdevname(sb->s_dev));
-
+ printk(KERN_INFO"yaffs: dev is %d name is \"%s\"\n", sb->s_dev, kdevname(sb->s_dev));
+
+
if(useRam)
{
}
else
- {
+ {
#ifdef YAFFS_MTD_ENABLED
struct mtd_info *mtd;
-
+
+ printk(KERN_DEBUG "yaffs: Attempting MTD mount on %u.%u, \"%s\"\n",
+ MAJOR(sb->s_dev),MINOR(sb->s_dev),kdevname(sb->s_dev));
+
// Hope it's a NAND mtd
mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
- if (!mtd)
+ if (!mtd)
{
printk(KERN_DEBUG "yaffs: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev));
return NULL;
}
+
if(mtd->type != MTD_NANDFLASH)
{
printk(KERN_DEBUG "yaffs: MTD device is not NAND it's type %d\n", mtd->type);
return NULL;
}
+ printk(KERN_DEBUG" erase %x\n",mtd->erase);
+ printk(KERN_DEBUG" read %x\n",mtd->read);
+ printk(KERN_DEBUG" write %x\n",mtd->write);
+ printk(KERN_DEBUG" readoob %x\n",mtd->read_oob);
+ printk(KERN_DEBUG" writeoob %x\n",mtd->write_oob);
+ printk(KERN_DEBUG" oobblock %x\n",mtd->oobblock);
+ printk(KERN_DEBUG" oobsize %x\n",mtd->oobsize);
+
+
if(!mtd->erase ||
!mtd->read ||
!mtd->write ||
printk(KERN_DEBUG "yaffs: MTD device does not support required functions\n");
return NULL;
}
-
+
if(mtd->oobblock != YAFFS_BYTES_PER_CHUNK ||
mtd->oobsize != YAFFS_BYTES_PER_SPARE)
{
printk(KERN_DEBUG "yaffs: MTD device does not support have the right page sizes\n");
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
// like it has the right capabilities
// Set the yaffs_Device up for ram emulation
}
memset(dev,0,sizeof(yaffs_Device));
- dev->genericDevice = mtd;
+ dev->genericDevice = mtd;
// Set up the memory size parameters....
-
- dev->nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
+
+ dev->nBlocks = YAFFS_RAM_EMULATION_SIZE / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
dev->startBlock = 1; // Don't use block 0
dev->endBlock = dev->nBlocks - 1;
dev->readChunkFromNAND = nandmtd_ReadChunkFromNAND;
dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND;
dev->initialiseNAND = nandmtd_InitialiseNAND;
-
+
#endif
}
return NULL;
T(("yaffs_read_super: got root inode\n"));
-
+
root = d_alloc_root(inode);
if (offset > 0) return 0;
/* Fill the buffer and get its length */
- sprintf( my_buffer,
+ sprintf( my_buffer,
"YAFFS built:"__DATE__ " "__TIME__"\n"
-
+
);
strcpy(page,my_buffer);
static int __init init_yaffs_fs(void)
{
int error = 0;
-
+
printk(KERN_DEBUG "yaffs " __DATE__ " " __TIME__ " Initialisation\n");
/* Install the proc_fs entry */
my_proc_entry = create_proc_read_entry("yaffs",
printk(KERN_DEBUG "yaffs " __DATE__ " " __TIME__ " Clean up\n");
remove_proc_entry("yaffs",&proc_root);
-
+
#ifdef YAFFS_RAM_ENABLED
- unregister_filesystem(&yaffs_ram_fs_type);
+ unregister_filesystem(&yaffs_fs_type);
#endif
#ifdef YAFFS_MTD_ENABLED
- unregister_filesystem(&yaffs_fs_type);
+ unregister_filesystem(&yaffs_ram_fs_type);
#endif
}