put_rpccred(cred);
delegation->cred = get_rpccred(cred);
delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM;
+ NFS_I(inode)->delegation_state = delegation->type;
+ smp_wmb();
}
/*
if (nfsi->delegation == NULL) {
list_add(&delegation->super_list, &clp->cl_delegations);
nfsi->delegation = delegation;
+ nfsi->delegation_state = delegation->type;
delegation = NULL;
} else {
if (memcmp(&delegation->stateid, &nfsi->delegation->stateid,
if (delegation != NULL) {
list_del_init(&delegation->super_list);
nfsi->delegation = NULL;
+ nfsi->delegation_state = 0;
}
spin_unlock(&clp->cl_lock);
nfs_delegation_claim_opens(inode);
sizeof(delegation->stateid.data)) == 0) {
list_del_init(&delegation->super_list);
nfsi->delegation = NULL;
+ nfsi->delegation_state = 0;
args->result = 0;
} else {
delegation = NULL;
continue;
list_move(&delegation->super_list, &head);
NFS_I(delegation->inode)->delegation = NULL;
+ NFS_I(delegation->inode)->delegation_state = 0;
}
spin_unlock(&clp->cl_lock);
while(!list_empty(&head)) {
#ifndef FS_NFS_DELEGATION_H
#define FS_NFS_DELEGATION_H
+#if defined(CONFIG_NFS_V4)
/*
* NFSv4 delegation
*/
int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
+static inline int nfs_have_delegation(struct inode *inode, int flags)
+{
+ flags &= FMODE_READ|FMODE_WRITE;
+ smp_rmb();
+ if ((NFS_I(inode)->delegation_state & flags) == flags)
+ return 1;
+ return 0;
+}
+#else
+static inline int nfs_have_delegation(struct inode *inode, int flags)
+{
+ return 0;
+}
+#endif
+
#endif
#include <linux/smp_lock.h>
#include <linux/namei.h>
+#include "delegation.h"
+
#define NFS_PARANOIA 1
/* #define NFS_DEBUG_VERBOSE 1 */
return ret;
no_open:
dput(parent);
+ if (inode != NULL && nfs_have_delegation(inode, FMODE_READ))
+ return 1;
return nfs_lookup_revalidate(dentry, nd);
}
#endif /* CONFIG_NFSV4 */
#include <asm/uaccess.h>
#include <asm/system.h>
+#include "delegation.h"
+
#define NFSDBG_FACILITY NFSDBG_FILE
static int nfs_file_open(struct inode *, struct file *);
if (!status) {
status = ctx->error;
ctx->error = 0;
- if (!status)
+ if (!status && !nfs_have_delegation(inode, FMODE_READ))
__nfs_revalidate_inode(NFS_SERVER(inode), inode);
}
unlock_kernel();
#include <asm/system.h>
#include <asm/uaccess.h>
+#include "delegation.h"
+
#define NFSDBG_FACILITY NFSDBG_VFS
#define NFS_PARANOIA 1
return status;
}
+int nfs_attribute_timeout(struct inode *inode)
+{
+ struct nfs_inode *nfsi = NFS_I(inode);
+
+ if (nfs_have_delegation(inode, FMODE_READ))
+ return 0;
+ return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo);
+}
+
+/**
+ * nfs_revalidate_inode - Revalidate the inode attributes
+ * @server - pointer to nfs_server struct
+ * @inode - pointer to inode struct
+ *
+ * Updates inode attribute information by retrieving the data from the server.
+ */
+int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+{
+ if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
+ && !nfs_attribute_timeout(inode))
+ return NFS_STALE(inode) ? -ESTALE : 0;
+ return __nfs_revalidate_inode(server, inode);
+}
+
/**
* nfs_begin_data_update
* @inode - pointer to inode
{
struct nfs_inode *nfsi = NFS_I(inode);
- /* Mark the attribute cache for revalidation */
- nfsi->flags |= NFS_INO_INVALID_ATTR;
- /* Directories and symlinks: invalidate page cache too */
- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
- nfsi->flags |= NFS_INO_INVALID_DATA;
+ if (!nfs_have_delegation(inode, FMODE_READ)) {
+ /* Mark the attribute cache for revalidation */
+ nfsi->flags |= NFS_INO_INVALID_ATTR;
+ /* Directories and symlinks: invalidate page cache too */
+ if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+ nfsi->flags |= NFS_INO_INVALID_DATA;
+ }
nfsi->cache_change_attribute ++;
atomic_dec(&nfsi->data_updates);
}
loff_t cur_size, new_isize;
int data_unstable;
+ /* Do we hold a delegation? */
+ if (nfs_have_delegation(inode, FMODE_READ))
+ return 0;
+
/* Are we in the process of updating data on the server? */
data_unstable = nfs_caches_unstable(inode);
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
|| S_ISLNK(inode->i_mode)))
invalid &= ~NFS_INO_INVALID_DATA;
- nfsi->flags |= invalid;
+ if (!nfs_have_delegation(inode, FMODE_READ))
+ nfsi->flags |= invalid;
return 0;
out_changed:
#ifdef CONFIG_NFS_V4
-#include "delegation.h"
-
static void nfs4_clear_inode(struct inode *);
do { \
INIT_LIST_HEAD(&(nfsi)->open_states); \
nfsi->delegation = NULL; \
+ nfsi->delegation_state = 0; \
init_rwsem(&nfsi->rwsem); \
} while(0)
#define register_nfs4fs() register_filesystem(&nfs4_fs_type)
#include <linux/smp_lock.h>
#include <linux/mempool.h>
+#include "delegation.h"
+
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
#define MIN_POOL_WRITE (32)
/*
* Insert a write request into an inode
*/
-static inline int
-nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
+static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
{
struct nfs_inode *nfsi = NFS_I(inode);
int error;
if (!nfsi->npages) {
igrab(inode);
nfs_begin_data_update(inode);
+ if (nfs_have_delegation(inode, FMODE_WRITE))
+ nfsi->change_attr++;
}
nfsi->npages++;
atomic_inc(&req->wb_count);
/* NFSv4 state */
struct list_head open_states;
struct nfs_delegation *delegation;
+ int delegation_state;
struct rw_semaphore rwsem;
#endif /* CONFIG_NFS_V4*/
extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);
extern int nfs_open(struct inode *, struct file *);
extern int nfs_release(struct inode *, struct file *);
+extern int nfs_attribute_timeout(struct inode *inode);
+extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
extern int nfs_setattr(struct dentry *, struct iattr *);
extern void nfs_begin_attr_update(struct inode *);
* inline functions
*/
-static inline int nfs_attribute_timeout(struct inode *inode)
-{
- struct nfs_inode *nfsi = NFS_I(inode);
-
- return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo);
-}
-
-/**
- * nfs_revalidate_inode - Revalidate the inode attributes
- * @server - pointer to nfs_server struct
- * @inode - pointer to inode struct
- *
- * Updates inode attribute information by retrieving the data from the server.
- */
-static inline int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
-{
- if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
- && !nfs_attribute_timeout(inode))
- return NFS_STALE(inode) ? -ESTALE : 0;
- return __nfs_revalidate_inode(server, inode);
-}
-
static inline loff_t
nfs_size_to_loff_t(__u64 size)
{