*** empty log message ***
[yaffs/.git] / yaffs_fs.c
index c3f57d7723bc2757030bdd3ef993fc47e9fd37b7..6a2ddb3833f3c1ac20e80377a4cab92cc0ed7271 100644 (file)
@@ -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)