- explanation of how to make filesystems exportable.
 Locking
        - info on locking rules as they pertain to Linux VFS.
+9p.txt
+       - 9p (v9fs) is an implementation of the Plan 9 remote fs protocol.
 adfs.txt
        - info and mount options for the Acorn Advanced Disc Filing System.
 afs.txt
        - info and mount options for the UDF filesystem.
 ufs.txt
        - info on the ufs filesystem.
-v9fs.txt
-       - v9fs is a Unix implementation of the Plan 9 9p remote fs protocol.
 vfat.txt
        - info on using the VFAT filesystem used in Windows NT and Windows 95
 vfs.txt
 
   aname=name   aname specifies the file tree to access when the server is
                offering several exported file systems.
 
+  cache=mode   specifies a cacheing policy.  By default, no caches are used.
+                       loose = no attempts are made at consistency,
+                                intended for exclusive, read-only mounts
+
   debug=n      specifies debug level.  The debug level is a bitmask.
                        0x01 = display verbose error messages
                        0x02 = developer debug (DEBUG_CURRENT)
 
 }
 
 /**
- * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and release it
+ * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and
+ *                     release it
  * @dentry: dentry to look for fid in
  *
  * find a fid in the dentry and then clone to a new private fid
 
        Opt_uname, Opt_remotename,
        /* Options that take no arguments */
        Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd,
+       /* Cache options */
+       Opt_cache_loose,
        /* Error token */
        Opt_err
 };
        {Opt_fd, "fd"},
        {Opt_legacy, "noextend"},
        {Opt_nodevmap, "nodevmap"},
+       {Opt_cache_loose, "cache=loose"},
+       {Opt_cache_loose, "loose"},
        {Opt_err, NULL}
 };
 
        v9ses->debug = 0;
        v9ses->rfdno = ~0;
        v9ses->wfdno = ~0;
+       v9ses->cache = 0;
 
        if (!options)
                return;
                                        "integer field, but no integer?\n");
                                continue;
                        }
-
                }
                switch (token) {
                case Opt_port:
                case Opt_nodevmap:
                        v9ses->nodev = 1;
                        break;
+               case Opt_cache_loose:
+                       v9ses->cache = CACHE_LOOSE;
+                       break;
                default:
                        continue;
                }
 
        unsigned int afid;      /* authentication fid */
        unsigned int rfdno;     /* read file descriptor number */
        unsigned int wfdno;     /* write file descriptor number */
-
+       unsigned int cache;     /* cache mode */
 
        char *name;             /* user name to mount as */
        char *remotename;       /* name of remote hierarchy being mounted */
        PROTO_FD,
 };
 
+/* possible values of ->cache */
+/* eventually support loose, tight, time, session, default always none */
+enum {
+       CACHE_NONE,             /* default */
+       CACHE_LOOSE,            /* no consistency */
+};
+
 extern struct dentry *v9fs_debugfs_root;
 
 int v9fs_session_init(struct v9fs_session_info *, const char *, char *);
 
 extern struct file_system_type v9fs_fs_type;
 extern const struct address_space_operations v9fs_addr_operations;
 extern const struct file_operations v9fs_file_operations;
+extern const struct file_operations v9fs_cached_file_operations;
 extern const struct file_operations v9fs_dir_operations;
 extern struct dentry_operations v9fs_dentry_operations;
+extern struct dentry_operations v9fs_cached_dentry_operations;
 
 struct inode *v9fs_get_inode(struct super_block *sb, int mode);
 ino_t v9fs_qid2ino(struct v9fs_qid *qid);
 
        int total = 0;
        int result = 0;
 
+       dprintk(DEBUG_VFS, "\n");
+
        buffer = kmap(page);
        do {
                if (count < rsize)
 
 static int v9fs_dentry_delete(struct dentry *dentry)
 {
        dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+
        return 1;
 }
 
+/**
+ * v9fs_cached_dentry_delete - called when dentry refcount equals 0
+ * @dentry:  dentry in question
+ *
+ * Only return 1 if our inode is invalid.  Only non-synthetic files
+ * (ones without mtime == 0) should be calling this function.
+ *
+ */
+
+static int v9fs_cached_dentry_delete(struct dentry *dentry)
+{
+       struct inode *inode = dentry->d_inode;
+       dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+
+       if(!inode)
+               return 1;
+
+       return 0;
+}
+
 /**
  * v9fs_dentry_release - called when dentry is going to be freed
  * @dentry:  dentry that is being release
        }
 }
 
+struct dentry_operations v9fs_cached_dentry_operations = {
+       .d_delete = v9fs_cached_dentry_delete,
+       .d_release = v9fs_dentry_release,
+};
+
 struct dentry_operations v9fs_dentry_operations = {
        .d_delete = v9fs_dentry_delete,
        .d_release = v9fs_dentry_release,
 
        vfid->filp = file;
        kfree(fcall);
 
+       if((vfid->qid.version) && (v9ses->cache)) {
+               dprintk(DEBUG_VFS, "cached");
+               /* enable cached file options */
+               if(file->f_op == &v9fs_file_operations)
+                       file->f_op = &v9fs_cached_file_operations;
+       }
+
        return 0;
 
 Clunk_Fid:
        return total;
 }
 
+const struct file_operations v9fs_cached_file_operations = {
+       .llseek = generic_file_llseek,
+       .read = do_sync_read,
+       .aio_read = generic_file_aio_read,
+       .write = v9fs_file_write,
+       .open = v9fs_file_open,
+       .release = v9fs_dir_release,
+       .lock = v9fs_file_lock,
+       .mmap = generic_file_mmap,
+};
+
 const struct file_operations v9fs_file_operations = {
        .llseek = generic_file_llseek,
        .read = v9fs_file_read,
 
                goto error;
        }
 
-       dentry->d_op = &v9fs_dentry_operations;
+       if(v9ses->cache)
+               dentry->d_op = &v9fs_cached_dentry_operations;
+       else
+               dentry->d_op = &v9fs_dentry_operations;
        d_instantiate(dentry, inode);
 
        if (nd && nd->flags & LOOKUP_OPEN) {
                goto error;
        }
 
-       dentry->d_op = &v9fs_dentry_operations;
+       if(v9ses->cache)
+               dentry->d_op = &v9fs_cached_dentry_operations;
+       else
+               dentry->d_op = &v9fs_dentry_operations;
        d_instantiate(dentry, inode);
        return 0;
 
 
        sb = dir->i_sb;
        v9ses = v9fs_inode2v9ses(dir);
-       dentry->d_op = &v9fs_dentry_operations;
        dirfid = v9fs_fid_lookup(dentry->d_parent);
 
        if(IS_ERR(dirfid))
 
        fid->qid = fcall->params.rstat.stat.qid;
        v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
+       if((fid->qid.version)&&(v9ses->cache))
+               dentry->d_op = &v9fs_cached_dentry_operations;
+       else
+               dentry->d_op = &v9fs_dentry_operations;
 
        d_add(dentry, inode);
        kfree(fcall);
                goto free_vfid;
        }
 
-       dentry->d_op = &v9fs_dentry_operations;
+       if(v9ses->cache)
+               dentry->d_op = &v9fs_cached_dentry_operations;
+       else
+               dentry->d_op = &v9fs_dentry_operations;
        d_instantiate(dentry, inode);
        return 0;