X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;f=yaffs_fs.c;h=6a2ddb3833f3c1ac20e80377a4cab92cc0ed7271;hb=3f107ebf545c27322a15a458198a3cd5dbc876f3;hp=c3f57d7723bc2757030bdd3ef993fc47e9fd37b7;hpb=11b48ba07062b2975286d468b9a75f7d06293d78;p=yaffs%2F.git diff --git a/yaffs_fs.c b/yaffs_fs.c index c3f57d7..6a2ddb3 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -83,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_readpage(struct file*,struct page * -static struct address_space_operations yaffs_address_ops = { -// readpage: yaffs_readpage, +static int yaffs_readlink(struct dentry *dentry, char *buffer, int buflen); +static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); + + + + + +static struct address_space_operations yaffs_file_address_operations = { + readpage: yaffs_readpage, // prepare_write: yaffs_prepare_write, // commit_write: yaffs_commit_write }; @@ -96,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, }; @@ -106,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 = { @@ -126,6 +133,13 @@ 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, @@ -137,6 +151,39 @@ static struct super_operations yaffs_super_ops = { }; + + + +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); /* @@ -152,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)); @@ -185,15 +234,52 @@ static void yaffs_put_inode(struct inode *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")); @@ -227,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; @@ -240,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; } @@ -458,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; @@ -521,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)