--- /dev/null
+From: Suresh Jayaraman <sjayaraman@suse.de>
+Subject: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
+Date: Tue, 22 Jun 2010 20:53:33 +0530
+Lines: 318
+Message-ID: <1277220214-3597-1-git-send-email-sjayaraman@suse.de>
+References: <yes>
+Cc: linux-cifs@vger.kernel.org, linux-fsdevel@vger.kernel.org,
+ linux-kernel@vger.kernel.org, David Howells <dhowells@redhat.com>
+To: Steve French <smfrench@gmail.com>
+X-From: linux-kernel-owner@vger.kernel.org Tue Jun 22 17:45:30 2010
+Return-path: <linux-kernel-owner@vger.kernel.org>
+Envelope-to: glk-linux-kernel-3@lo.gmane.org
+Received: from vger.kernel.org ([209.132.180.67])
+ by lo.gmane.org with esmtp (Exim 4.69)
+ (envelope-from <linux-kernel-owner@vger.kernel.org>)
+ id 1OR5fF-0000Ka-Na
+ for glk-linux-kernel-3@lo.gmane.org; Tue, 22 Jun 2010 17:45:30 +0200
+Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
+ id S1755952Ab0FVPpP (ORCPT <rfc822;glk-linux-kernel-3@m.gmane.org>);
+ Tue, 22 Jun 2010 11:45:15 -0400
+Received: from victor.provo.novell.com ([137.65.250.26]:59441 "EHLO
+ victor.provo.novell.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
+ with ESMTP id S1751397Ab0FVPoA (ORCPT
+ <rfc822;groupwise-SJayaraman@novell.com:0:0>);
+ Tue, 22 Jun 2010 11:44:00 -0400
+Received: from localhost (prv-ext-foundry1int.gns.novell.com [137.65.251.240])
+ by victor.provo.novell.com with ESMTP; Tue, 22 Jun 2010 09:23:35 -0600
+X-Mailer: git-send-email 1.6.4.2
+In-Reply-To: <yes>
+Sender: linux-kernel-owner@vger.kernel.org
+Precedence: bulk
+List-ID: <linux-kernel.vger.kernel.org>
+X-Mailing-List: linux-kernel@vger.kernel.org
+Archived-At: <http://permalink.gmane.org/gmane.linux.kernel/1001765>
+
+Define inode-level data storage objects (managed by cifsInodeInfo structs).
+Each inode-level object is created in a super-block level object and is itself
+a data storage object in to which pages from the inode are stored.
+
+The inode object is keyed by UniqueId. The coherency data being used is
+LastWriteTime and the file size.
+
+Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
+---
+ fs/cifs/cache.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/cifs/cifsfs.c | 7 ++++
+ fs/cifs/cifsglob.h | 3 +
+ fs/cifs/file.c | 6 +++
+ fs/cifs/fscache.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
+ fs/cifs/fscache.h | 12 +++++++
+ fs/cifs/inode.c | 4 ++
+ 7 files changed, 180 insertions(+)
+
+Index: cifs-2.6/fs/cifs/cache.c
+===================================================================
+--- cifs-2.6.orig/fs/cifs/cache.c
++++ cifs-2.6/fs/cifs/cache.c
+@@ -138,3 +138,83 @@ const struct fscache_cookie_def cifs_fsc
+ .get_key = cifs_super_get_key,
+ };
+
++/*
++ * Auxiliary data attached to CIFS inode within the cache
++ */
++struct cifs_fscache_inode_auxdata {
++ struct timespec last_write_time;
++ loff_t size;
++};
++
++static uint16_t cifs_fscache_inode_get_key(const void *cookie_netfs_data,
++ void *buffer, uint16_t maxbuf)
++{
++ const struct cifsInodeInfo *cifsi = cookie_netfs_data;
++ uint16_t keylen;
++
++ /* use the UniqueId as the key */
++ keylen = sizeof(cifsi->uniqueid);
++ if (keylen > maxbuf)
++ keylen = 0;
++ else
++ memcpy(buffer, &cifsi->uniqueid, keylen);
++
++ return keylen;
++}
++
++static void
++cifs_fscache_inode_get_attr(const void *cookie_netfs_data, uint64_t *size)
++{
++ const struct cifsInodeInfo *cifsi = cookie_netfs_data;
++
++ *size = cifsi->vfs_inode.i_size;
++}
++
++static uint16_t
++cifs_fscache_inode_get_aux(const void *cookie_netfs_data, void *buffer,
++ uint16_t maxbuf)
++{
++ struct cifs_fscache_inode_auxdata auxdata;
++ const struct cifsInodeInfo *cifsi = cookie_netfs_data;
++
++ memset(&auxdata, 0, sizeof(auxdata));
++ auxdata.size = cifsi->vfs_inode.i_size;
++ auxdata.last_write_time = cifsi->vfs_inode.i_ctime;
++
++ if (maxbuf > sizeof(auxdata))
++ maxbuf = sizeof(auxdata);
++
++ memcpy(buffer, &auxdata, maxbuf);
++
++ return maxbuf;
++}
++
++static enum
++fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data,
++ const void *data,
++ uint16_t datalen)
++{
++ struct cifs_fscache_inode_auxdata auxdata;
++ struct cifsInodeInfo *cifsi = cookie_netfs_data;
++
++ if (datalen != sizeof(auxdata))
++ return FSCACHE_CHECKAUX_OBSOLETE;
++
++ memset(&auxdata, 0, sizeof(auxdata));
++ auxdata.size = cifsi->vfs_inode.i_size;
++ auxdata.last_write_time = cifsi->vfs_inode.i_ctime;
++
++ if (memcmp(data, &auxdata, datalen) != 0)
++ return FSCACHE_CHECKAUX_OBSOLETE;
++
++ return FSCACHE_CHECKAUX_OKAY;
++}
++
++const struct fscache_cookie_def cifs_fscache_inode_object_def = {
++ .name = "CIFS.uniqueid",
++ .type = FSCACHE_COOKIE_TYPE_DATAFILE,
++ .get_key = cifs_fscache_inode_get_key,
++ .get_attr = cifs_fscache_inode_get_attr,
++ .get_aux = cifs_fscache_inode_get_aux,
++ .check_aux = cifs_fscache_inode_check_aux,
++};
+Index: cifs-2.6/fs/cifs/cifsfs.c
+===================================================================
+--- cifs-2.6.orig/fs/cifs/cifsfs.c
++++ cifs-2.6/fs/cifs/cifsfs.c
+@@ -330,6 +330,12 @@ cifs_destroy_inode(struct inode *inode)
+ }
+
+ static void
++cifs_clear_inode(struct inode *inode)
++{
++ cifs_fscache_release_inode_cookie(inode);
++}
++
++static void
+ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
+ {
+ seq_printf(s, ",addr=");
+@@ -490,6 +496,7 @@ static const struct super_operations cif
+ .alloc_inode = cifs_alloc_inode,
+ .destroy_inode = cifs_destroy_inode,
+ .drop_inode = cifs_drop_inode,
++ .clear_inode = cifs_clear_inode,
+ /* .delete_inode = cifs_delete_inode, */ /* Do not need above
+ function unless later we add lazy close of inodes or unless the
+ kernel forgets to call us with the same number of releases (closes)
+Index: cifs-2.6/fs/cifs/cifsglob.h
+===================================================================
+--- cifs-2.6.orig/fs/cifs/cifsglob.h
++++ cifs-2.6/fs/cifs/cifsglob.h
+@@ -407,6 +407,9 @@ struct cifsInodeInfo {
+ bool invalid_mapping:1; /* pagecache is invalid */
+ u64 server_eof; /* current file size on server */
+ u64 uniqueid; /* server inode number */
++#ifdef CONFIG_CIFS_FSCACHE
++ struct fscache_cookie *fscache;
++#endif
+ struct inode vfs_inode;
+ };
+
+Index: cifs-2.6/fs/cifs/file.c
+===================================================================
+--- cifs-2.6.orig/fs/cifs/file.c
++++ cifs-2.6/fs/cifs/file.c
+@@ -40,6 +40,7 @@
+ #include "cifs_unicode.h"
+ #include "cifs_debug.h"
+ #include "cifs_fs_sb.h"
++#include "fscache.h"
+
+ static inline int cifs_convert_flags(unsigned int flags)
+ {
+@@ -282,6 +283,9 @@ int cifs_open(struct inode *inode, struc
+ CIFSSMBClose(xid, tcon, netfid);
+ rc = -ENOMEM;
+ }
++
++ cifs_fscache_set_inode_cookie(inode, file);
++
+ goto out;
+ } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
+ if (tcon->ses->serverNOS)
+@@ -373,6 +377,8 @@ int cifs_open(struct inode *inode, struc
+ goto out;
+ }
+
++ cifs_fscache_set_inode_cookie(inode, file);
++
+ if (oplock & CIFS_CREATE_ACTION) {
+ /* time to set mode which we can not set earlier due to
+ problems creating new read-only files */
+Index: cifs-2.6/fs/cifs/fscache.c
+===================================================================
+--- cifs-2.6.orig/fs/cifs/fscache.c
++++ cifs-2.6/fs/cifs/fscache.c
+@@ -62,3 +62,71 @@ void cifs_fscache_release_super_cookie(s
+ tcon->fscache = NULL;
+ }
+
++static void cifs_fscache_enable_inode_cookie(struct inode *inode)
++{
++ struct cifsInodeInfo *cifsi = CIFS_I(inode);
++ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
++
++ if (cifsi->fscache)
++ return;
++
++ cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
++ &cifs_fscache_inode_object_def,
++ cifsi);
++ cFYI(1, "CIFS: got FH cookie (0x%p/0x%p/0x%p)\n",
++ cifs_sb->tcon, cifsi, cifsi->fscache);
++}
++
++void cifs_fscache_release_inode_cookie(struct inode *inode)
++{
++ struct cifsInodeInfo *cifsi = CIFS_I(inode);
++
++ if (cifsi->fscache) {
++ cFYI(1, "CIFS releasing inode cookie (0x%p/0x%p)\n",
++ cifsi, cifsi->fscache);
++ fscache_relinquish_cookie(cifsi->fscache, 0);
++ cifsi->fscache = NULL;
++ }
++}
++
++static void cifs_fscache_disable_inode_cookie(struct inode *inode)
++{
++ struct cifsInodeInfo *cifsi = CIFS_I(inode);
++
++ if (cifsi->fscache) {
++ cFYI(1, "CIFS disabling inode cookie (0x%p/0x%p)\n",
++ cifsi, cifsi->fscache);
++ fscache_relinquish_cookie(cifsi->fscache, 1);
++ cifsi->fscache = NULL;
++ }
++}
++
++void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
++{
++ /* BB: parallel opens - need locking? */
++ if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
++ cifs_fscache_disable_inode_cookie(inode);
++ else {
++ cifs_fscache_enable_inode_cookie(inode);
++ cFYI(1, "CIFS: fscache inode cookie set\n");
++ }
++}
++
++void cifs_fscache_reset_inode_cookie(struct inode *inode)
++{
++ struct cifsInodeInfo *cifsi = CIFS_I(inode);
++ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
++ struct fscache_cookie *old = cifsi->fscache;
++
++ if (cifsi->fscache) {
++ /* retire the current fscache cache and get a new one */
++ fscache_relinquish_cookie(cifsi->fscache, 1);
++
++ cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
++ &cifs_fscache_inode_object_def,
++ cifsi);
++ cFYI(1, "CIFS: new cookie (0x%p/0x%p) oldcookie 0x%p\n",
++ cifsi, cifsi->fscache, old);
++ }
++}
++
+Index: cifs-2.6/fs/cifs/fscache.h
+===================================================================
+--- cifs-2.6.orig/fs/cifs/fscache.h
++++ cifs-2.6/fs/cifs/fscache.h
+@@ -29,6 +29,8 @@
+ extern struct fscache_netfs cifs_fscache_netfs;
+ extern const struct fscache_cookie_def cifs_fscache_server_index_def;
+ extern const struct fscache_cookie_def cifs_fscache_super_index_def;
++extern const struct fscache_cookie_def cifs_fscache_inode_object_def;
++
+
+ extern int cifs_fscache_register(void);
+ extern void cifs_fscache_unregister(void);
+@@ -41,6 +43,10 @@ extern void cifs_fscache_release_client_
+ extern void cifs_fscache_get_super_cookie(struct cifsTconInfo *);
+ extern void cifs_fscache_release_super_cookie(struct cifsTconInfo *);
+
++extern void cifs_fscache_release_inode_cookie(struct inode *);
++extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *);
++extern void cifs_fscache_reset_inode_cookie(struct inode *);
++
+ #else /* CONFIG_CIFS_FSCACHE */
+ static inline int cifs_fscache_register(void) { return 0; }
+ static inline void cifs_fscache_unregister(void) {}
+@@ -53,6 +59,12 @@ static inline void cifs_fscache_get_supe
+ static inline void
+ cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) {}
+
++static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
++static inline void cifs_fscache_set_inode_cookie(struct inode *inode,
++ struct file *filp) {}
++static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {}
++
++
+ #endif /* CONFIG_CIFS_FSCACHE */
+
+ #endif /* _CIFS_FSCACHE_H */
+Index: cifs-2.6/fs/cifs/inode.c
+===================================================================
+--- cifs-2.6.orig/fs/cifs/inode.c
++++ cifs-2.6/fs/cifs/inode.c
+@@ -29,6 +29,7 @@
+ #include "cifsproto.h"
+ #include "cifs_debug.h"
+ #include "cifs_fs_sb.h"
++#include "fscache.h"
+
+
+ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
+@@ -776,6 +777,8 @@ retry_iget5_locked:
+ inode->i_flags |= S_NOATIME | S_NOCMTIME;
+ if (inode->i_state & I_NEW) {
+ inode->i_ino = hash;
++ /* initialize per-inode cache cookie pointer */
++ CIFS_I(inode)->fscache = NULL;
+ unlock_new_inode(inode);
+ }
+ }
+@@ -1568,6 +1571,7 @@ cifs_invalidate_mapping(struct inode *in
+ cifs_i->write_behind_rc = rc;
+ }
+ invalidate_remote_inode(inode);
++ cifs_fscache_reset_inode_cookie(inode);
+ }
+
+ int cifs_revalidate_file(struct file *filp)
+
+