|
@@ -146,3 +146,126 @@ const struct fscache_cookie_def nfs_fscache_super_index_def = {
|
|
|
.type = FSCACHE_COOKIE_TYPE_INDEX,
|
|
|
.get_key = nfs_super_get_key,
|
|
|
};
|
|
|
+
|
|
|
+/*
|
|
|
+ * Definition of the auxiliary data attached to NFS inode storage objects
|
|
|
+ * within the cache.
|
|
|
+ *
|
|
|
+ * The contents of this struct are recorded in the on-disk local cache in the
|
|
|
+ * auxiliary data attached to the data storage object backing an inode. This
|
|
|
+ * permits coherency to be managed when a new inode binds to an already extant
|
|
|
+ * cache object.
|
|
|
+ */
|
|
|
+struct nfs_fscache_inode_auxdata {
|
|
|
+ struct timespec mtime;
|
|
|
+ struct timespec ctime;
|
|
|
+ loff_t size;
|
|
|
+ u64 change_attr;
|
|
|
+};
|
|
|
+
|
|
|
+/*
|
|
|
+ * Generate a key to describe an NFS inode in an NFS server's index
|
|
|
+ */
|
|
|
+static uint16_t nfs_fscache_inode_get_key(const void *cookie_netfs_data,
|
|
|
+ void *buffer, uint16_t bufmax)
|
|
|
+{
|
|
|
+ const struct nfs_inode *nfsi = cookie_netfs_data;
|
|
|
+ uint16_t nsize;
|
|
|
+
|
|
|
+ /* use the inode's NFS filehandle as the key */
|
|
|
+ nsize = nfsi->fh.size;
|
|
|
+ memcpy(buffer, nfsi->fh.data, nsize);
|
|
|
+ return nsize;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Get certain file attributes from the netfs data
|
|
|
+ * - This function can be absent for an index
|
|
|
+ * - Not permitted to return an error
|
|
|
+ * - The netfs data from the cookie being used as the source is presented
|
|
|
+ */
|
|
|
+static void nfs_fscache_inode_get_attr(const void *cookie_netfs_data,
|
|
|
+ uint64_t *size)
|
|
|
+{
|
|
|
+ const struct nfs_inode *nfsi = cookie_netfs_data;
|
|
|
+
|
|
|
+ *size = nfsi->vfs_inode.i_size;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Get the auxiliary data from netfs data
|
|
|
+ * - This function can be absent if the index carries no state data
|
|
|
+ * - Should store the auxiliary data in the buffer
|
|
|
+ * - Should return the amount of amount stored
|
|
|
+ * - Not permitted to return an error
|
|
|
+ * - The netfs data from the cookie being used as the source is presented
|
|
|
+ */
|
|
|
+static uint16_t nfs_fscache_inode_get_aux(const void *cookie_netfs_data,
|
|
|
+ void *buffer, uint16_t bufmax)
|
|
|
+{
|
|
|
+ struct nfs_fscache_inode_auxdata auxdata;
|
|
|
+ const struct nfs_inode *nfsi = cookie_netfs_data;
|
|
|
+
|
|
|
+ memset(&auxdata, 0, sizeof(auxdata));
|
|
|
+ auxdata.size = nfsi->vfs_inode.i_size;
|
|
|
+ auxdata.mtime = nfsi->vfs_inode.i_mtime;
|
|
|
+ auxdata.ctime = nfsi->vfs_inode.i_ctime;
|
|
|
+
|
|
|
+ if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
|
|
|
+ auxdata.change_attr = nfsi->change_attr;
|
|
|
+
|
|
|
+ if (bufmax > sizeof(auxdata))
|
|
|
+ bufmax = sizeof(auxdata);
|
|
|
+
|
|
|
+ memcpy(buffer, &auxdata, bufmax);
|
|
|
+ return bufmax;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Consult the netfs about the state of an object
|
|
|
+ * - This function can be absent if the index carries no state data
|
|
|
+ * - The netfs data from the cookie being used as the target is
|
|
|
+ * presented, as is the auxiliary data
|
|
|
+ */
|
|
|
+static
|
|
|
+enum fscache_checkaux nfs_fscache_inode_check_aux(void *cookie_netfs_data,
|
|
|
+ const void *data,
|
|
|
+ uint16_t datalen)
|
|
|
+{
|
|
|
+ struct nfs_fscache_inode_auxdata auxdata;
|
|
|
+ struct nfs_inode *nfsi = cookie_netfs_data;
|
|
|
+
|
|
|
+ if (datalen != sizeof(auxdata))
|
|
|
+ return FSCACHE_CHECKAUX_OBSOLETE;
|
|
|
+
|
|
|
+ memset(&auxdata, 0, sizeof(auxdata));
|
|
|
+ auxdata.size = nfsi->vfs_inode.i_size;
|
|
|
+ auxdata.mtime = nfsi->vfs_inode.i_mtime;
|
|
|
+ auxdata.ctime = nfsi->vfs_inode.i_ctime;
|
|
|
+
|
|
|
+ if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
|
|
|
+ auxdata.change_attr = nfsi->change_attr;
|
|
|
+
|
|
|
+ if (memcmp(data, &auxdata, datalen) != 0)
|
|
|
+ return FSCACHE_CHECKAUX_OBSOLETE;
|
|
|
+
|
|
|
+ return FSCACHE_CHECKAUX_OKAY;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Define the inode object for FS-Cache. This is used to describe an inode
|
|
|
+ * object to fscache_acquire_cookie(). It is keyed by the NFS file handle for
|
|
|
+ * an inode.
|
|
|
+ *
|
|
|
+ * Coherency is managed by comparing the copies of i_size, i_mtime and i_ctime
|
|
|
+ * held in the cache auxiliary data for the data storage object with those in
|
|
|
+ * the inode struct in memory.
|
|
|
+ */
|
|
|
+const struct fscache_cookie_def nfs_fscache_inode_object_def = {
|
|
|
+ .name = "NFS.fh",
|
|
|
+ .type = FSCACHE_COOKIE_TYPE_DATAFILE,
|
|
|
+ .get_key = nfs_fscache_inode_get_key,
|
|
|
+ .get_attr = nfs_fscache_inode_get_attr,
|
|
|
+ .get_aux = nfs_fscache_inode_get_aux,
|
|
|
+ .check_aux = nfs_fscache_inode_check_aux,
|
|
|
+};
|