X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;f=yaffs_fs.c;h=6a2ddb3833f3c1ac20e80377a4cab92cc0ed7271;hb=3f107ebf545c27322a15a458198a3cd5dbc876f3;hp=de71211a985bd43d4c61ce7abaeeae511326bfa3;hpb=47e27ba76801d146d5b2ae8edc88a98aab8cc1e8;p=yaffs%2F.git diff --git a/yaffs_fs.c b/yaffs_fs.c index de71211..6a2ddb3 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -60,6 +60,8 @@ +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); @@ -81,11 +83,18 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf); 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 }; @@ -94,7 +103,7 @@ static struct address_space_operations yaffs_address_ops = { 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, }; @@ -104,11 +113,11 @@ static struct inode_operations yaffs_file_inode_operations = { }; - -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 = { @@ -124,16 +133,57 @@ 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); /* @@ -149,6 +199,8 @@ static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry) 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)); @@ -177,17 +229,57 @@ static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry) 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")); @@ -221,7 +313,6 @@ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj) 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; @@ -234,18 +325,19 @@ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj) 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; } @@ -452,16 +544,13 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int d 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; @@ -515,36 +604,52 @@ static int yaffs_unlink(struct inode * dir, struct dentry *dentry) /* - * 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) @@ -626,6 +731,34 @@ static void yaffs_read_inode (struct inode *inode) } +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; @@ -653,7 +786,7 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl 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); @@ -675,6 +808,7 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl dev->readChunkFromNAND = nandemul_ReadChunkFromNAND; dev->eraseBlockInNAND = nandemul_EraseBlockInNAND; dev->initialiseNAND = nandemul_InitialiseNAND; + #endif } @@ -755,6 +889,7 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND; dev->initialiseNAND = nandmtd_InitialiseNAND; + dev->putSuperFunc = yaffs_MTDPutSuper; #endif }