UBIFS: add NFS support
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Tue, 22 Jul 2008 13:49:31 +0000 (16:49 +0300)
committerGrazvydas Ignotas <notasas@gmail.com>
Mon, 25 May 2009 14:08:50 +0000 (17:08 +0300)
Implement minimal set of FS export operations to support NFS.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
fs/ubifs/dir.c
fs/ubifs/super.c

index a79e850..320f89a 100644 (file)
@@ -255,12 +255,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
 
 done:
        kfree(dent);
-       /*
-        * Note, d_splice_alias() would be required instead if we supported
-        * NFS.
-        */
-       d_add(dentry, inode);
-       return NULL;
+       return d_splice_alias(inode, dentry);
 
 out:
        kfree(dent);
index 77b2883..8b8f568 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/parser.h>
 #include <linux/seq_file.h>
 #include <linux/mount.h>
+#include <linux/exportfs.h>
 #include "ubifs.h"
 
 /* Slab cache for UBIFS inodes */
@@ -156,7 +157,7 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
        if (err)
                goto out_invalid;
 
-       /* Disable readahead */
+       /* Disable read-ahead */
        inode->i_mapping->backing_dev_info = &c->bdi;
 
        switch (inode->i_mode & S_IFMT) {
@@ -354,7 +355,7 @@ static void ubifs_delete_inode(struct inode *inode)
        if (err)
                /*
                 * Worst case we have a lost orphan inode wasting space, so a
-                * simple error message is ok here.
+                * simple error message is OK here.
                 */
                ubifs_err("can't delete inode %lu, error %d",
                          inode->i_ino, err);
@@ -1590,6 +1591,51 @@ struct super_operations ubifs_super_operations = {
        .sync_fs       = ubifs_sync_fs,
 };
 
+/*
+ * Note, since UBIFS does re-use inode numbers at the moment, we do not check
+ * the generation number in this function.
+ */
+static struct dentry *ubifs_fh_to_dentry(struct super_block *sb,
+                                        struct fid *fid,
+                                        int fh_len, int fh_type)
+{
+       ino_t inum;
+       struct inode *inode;
+       struct dentry *dent;
+
+       switch (fh_type) {
+       case FILEID_INO32_GEN:
+       case FILEID_INO32_GEN_PARENT:
+               inum = fid->i32.ino;
+               break;
+       default:
+               dbg_err("unsupported file handle type %d", fh_type);
+               return ERR_PTR(-EINVAL);
+       }
+
+       inode = ubifs_iget(sb, inum);
+       if (IS_ERR(inode)) {
+               if (PTR_ERR(inode) == -ENOENT)
+                       return ERR_PTR(-ESTALE);
+               return ERR_CAST(inode);
+       }
+
+       dent = d_alloc_anon(inode);
+       if (!dent) {
+               iput(inode);
+               return ERR_PTR(-ENOMEM);
+       }
+       return dent;
+}
+
+/*
+ * Probably NFS support could be faster if other export operations were
+ * implemented, but '->fh_to_dentry()' is enough.
+ */
+static struct export_operations ubifs_export_ops = {
+       .fh_to_dentry = ubifs_fh_to_dentry,
+};
+
 /**
  * open_ubi - parse UBI device name string and open the UBI device.
  * @name: UBI volume name
@@ -1697,10 +1743,10 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
        }
 
        /*
-        * UBIFS provids 'backing_dev_info' in order to disable readahead. For
+        * UBIFS provides 'backing_dev_info' in order to disable read-ahead. For
         * UBIFS, I/O is not deferred, it is done immediately in readpage,
         * which means the user would have to wait not just for their own I/O
-        * but the readahead I/O as well i.e. completely pointless.
+        * but the read-ahead I/O as well i.e. completely pointless.
         *
         * Read-ahead will be disabled because @c->bdi.ra_pages is 0.
         */
@@ -1725,6 +1771,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
        if (c->max_inode_sz > MAX_LFS_FILESIZE)
                sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE;
        sb->s_op = &ubifs_super_operations;
+       sb->s_export_op = &ubifs_export_ops;
 
        mutex_lock(&c->umount_mutex);
        err = mount_ubifs(c);
@@ -1858,10 +1905,11 @@ static void ubifs_kill_sb(struct super_block *sb)
 }
 
 static struct file_system_type ubifs_fs_type = {
-       .name    = "ubifs",
-       .owner   = THIS_MODULE,
-       .get_sb  = ubifs_get_sb,
-       .kill_sb = ubifs_kill_sb
+       .name     = "ubifs",
+       .owner    = THIS_MODULE,
+       .get_sb   = ubifs_get_sb,
+       .kill_sb  = ubifs_kill_sb,
+       .fs_flags = FS_REQUIRES_DEV,
 };
 
 /*