Merge git://git.infradead.org/mtd-2.6
[linux-drm-fsl-dcu.git] / fs / libfs.c
index 7d487047dbb8814ea1d5f0a01c9e30c630d9a322..5294de1f40c41ba3c2dfcd992c725202967b0dce 100644 (file)
@@ -159,7 +159,10 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
                                        continue;
 
                                spin_unlock(&dcache_lock);
-                               if (filldir(dirent, next->d_name.name, next->d_name.len, filp->f_pos, next->d_inode->i_ino, dt_type(next->d_inode)) < 0)
+                               if (filldir(dirent, next->d_name.name, 
+                                           next->d_name.len, filp->f_pos, 
+                                           next->d_inode->i_ino, 
+                                           dt_type(next->d_inode)) < 0)
                                        return 0;
                                spin_lock(&dcache_lock);
                                /* next is still alive */
@@ -190,6 +193,10 @@ const struct inode_operations simple_dir_inode_operations = {
        .lookup         = simple_lookup,
 };
 
+static const struct super_operations simple_super_operations = {
+       .statfs         = simple_statfs,
+};
+
 /*
  * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
  * will never be mountable)
@@ -199,7 +206,6 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name,
        struct vfsmount *mnt)
 {
        struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
-       static const struct super_operations default_ops = {.statfs = simple_statfs};
        struct dentry *dentry;
        struct inode *root;
        struct qstr d_name = {.name = name, .len = strlen(name)};
@@ -212,11 +218,17 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name,
        s->s_blocksize = 1024;
        s->s_blocksize_bits = 10;
        s->s_magic = magic;
-       s->s_op = ops ? ops : &default_ops;
+       s->s_op = ops ? ops : &simple_super_operations;
        s->s_time_gran = 1;
        root = new_inode(s);
        if (!root)
                goto Enomem;
+       /*
+        * since this is the first inode, make it number 1. New inodes created
+        * after this must take care not to collide with it (by passing
+        * max_reserved of 1 to iunique).
+        */
+       root->i_ino = 1;
        root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
        root->i_uid = root->i_gid = 0;
        root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
@@ -335,17 +347,18 @@ int simple_prepare_write(struct file *file, struct page *page,
                        flush_dcache_page(page);
                        kunmap_atomic(kaddr, KM_USER0);
                }
-               SetPageUptodate(page);
        }
        return 0;
 }
 
 int simple_commit_write(struct file *file, struct page *page,
-                       unsigned offset, unsigned to)
+                       unsigned from, unsigned to)
 {
        struct inode *inode = page->mapping->host;
        loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 
+       if (!PageUptodate(page))
+               SetPageUptodate(page);
        /*
         * No need to use i_size_read() here, the i_size
         * cannot change under us because we hold the i_mutex.
@@ -356,9 +369,13 @@ int simple_commit_write(struct file *file, struct page *page,
        return 0;
 }
 
+/*
+ * the inodes created here are not hashed. If you use iunique to generate
+ * unique inode values later for this filesystem, then you must take care
+ * to pass it an appropriate max_reserved value to avoid collisions.
+ */
 int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
 {
-       static struct super_operations s_ops = {.statfs = simple_statfs};
        struct inode *inode;
        struct dentry *root;
        struct dentry *dentry;
@@ -367,12 +384,17 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
        s->s_blocksize = PAGE_CACHE_SIZE;
        s->s_blocksize_bits = PAGE_CACHE_SHIFT;
        s->s_magic = magic;
-       s->s_op = &s_ops;
+       s->s_op = &simple_super_operations;
        s->s_time_gran = 1;
 
        inode = new_inode(s);
        if (!inode)
                return -ENOMEM;
+       /*
+        * because the root inode is 1, the files array must not contain an
+        * entry at index 1
+        */
+       inode->i_ino = 1;
        inode->i_mode = S_IFDIR | 0755;
        inode->i_uid = inode->i_gid = 0;
        inode->i_blocks = 0;
@@ -388,6 +410,13 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
        for (i = 0; !files->name || files->name[0]; i++, files++) {
                if (!files->name)
                        continue;
+
+               /* warn if it tries to conflict with the root inode */
+               if (unlikely(i == 1))
+                       printk(KERN_WARNING "%s: %s passed in a files array"
+                               "with an index of 1!\n", __func__,
+                               s->s_type->name);
+
                dentry = d_alloc_name(root, files->name);
                if (!dentry)
                        goto out;