Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9451a9a5 authored by Suresh Jayaraman's avatar Suresh Jayaraman Committed by Steve French
Browse files

cifs: define inode-level cache object and register them



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, LastChangeTime and end of file reported by the server.

Signed-off-by: default avatarSuresh Jayaraman <sjayaraman@suse.de>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent d03382ce
Loading
Loading
Loading
Loading
+83 −0
Original line number Diff line number Diff line
@@ -215,3 +215,86 @@ const struct fscache_cookie_def cifs_fscache_super_index_def = {
	.check_aux = cifs_fscache_super_check_aux,
};

/*
 * Auxiliary data attached to CIFS inode within the cache
 */
struct cifs_fscache_inode_auxdata {
	struct timespec	last_write_time;
	struct timespec	last_change_time;
	u64		eof;
};

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.eof = cifsi->server_eof;
	auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
	auxdata.last_change_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.eof = cifsi->server_eof;
	auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
	auxdata.last_change_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,
};
+7 −0
Original line number Diff line number Diff line
@@ -329,6 +329,12 @@ cifs_destroy_inode(struct inode *inode)
	kmem_cache_free(cifs_inode_cachep, CIFS_I(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)
{
@@ -490,6 +496,7 @@ static const struct super_operations cifs_super_ops = {
	.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)
+3 −0
Original line number Diff line number Diff line
@@ -390,6 +390,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;
};

+6 −0
Original line number Diff line number Diff line
@@ -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, struct file *file)
				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, struct file *file)
		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 */
+68 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include "fscache.h"
#include "cifsglob.h"
#include "cifs_debug.h"
#include "cifs_fs_sb.h"

void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
{
@@ -56,3 +57,70 @@ void cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon)
	fscache_relinquish_cookie(tcon->fscache, 0);
	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)",
			cifs_sb->tcon->fscache, 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)",
				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)",
				cifsi->fscache);
		fscache_relinquish_cookie(cifsi->fscache, 1);
		cifsi->fscache = NULL;
	}
}

void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
{
	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");
	}
}

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 oldcookie 0x%p",
				cifsi->fscache, old);
	}
}
Loading