Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
* git://git.linux-nfs.org/pub/linux/nfs-2.6: (103 commits) SUNRPC,RPCSEC_GSS: spkm3--fix config dependencies SUNRPC,RPCSEC_GSS: spkm3: import contexts using NID_cast5_cbc LOCKD: Make nlmsvc_traverse_shares return void LOCKD: nlmsvc_traverse_blocks return is unused SUNRPC,RPCSEC_GSS: fix krb5 sequence numbers. NFSv4: Dont list system.nfs4_acl for filesystems that don't support it. SUNRPC,RPCSEC_GSS: remove unnecessary kmalloc of a checksum SUNRPC: Ensure rpc_call_async() always calls tk_ops->rpc_release() SUNRPC: Fix memory barriers for req->rq_received NFS: Fix a race in nfs_sync_inode() NFS: Clean up nfs_flush_list() NFS: Fix a race with PG_private and nfs_release_page() NFSv4: Ensure the callback daemon flushes signals SUNRPC: Fix a 'Busy inodes' error in rpc_pipefs NFS, NLM: Allow blocking locks to respect signals NFS: Make nfs_fhget() return appropriate error values NFSv4: Fix an oops in nfs4_fill_super lockd: blocks should hold a reference to the nlm_file NFSv4: SETCLIENTID_CONFIRM should handle NFS4ERR_DELAY/NFS4ERR_RESOURCE NFSv4: Send the delegation stateid for SETATTR calls ...
This commit is contained in:
237
fs/nfs/inode.c
237
fs/nfs/inode.c
@@ -26,6 +26,7 @@
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/sunrpc/clnt.h>
|
||||
#include <linux/sunrpc/stats.h>
|
||||
#include <linux/sunrpc/metrics.h>
|
||||
#include <linux/nfs_fs.h>
|
||||
#include <linux/nfs_mount.h>
|
||||
#include <linux/nfs4_mount.h>
|
||||
@@ -42,6 +43,7 @@
|
||||
#include "nfs4_fs.h"
|
||||
#include "callback.h"
|
||||
#include "delegation.h"
|
||||
#include "iostat.h"
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_VFS
|
||||
#define NFS_PARANOIA 1
|
||||
@@ -65,6 +67,7 @@ static void nfs_clear_inode(struct inode *);
|
||||
static void nfs_umount_begin(struct super_block *);
|
||||
static int nfs_statfs(struct super_block *, struct kstatfs *);
|
||||
static int nfs_show_options(struct seq_file *, struct vfsmount *);
|
||||
static int nfs_show_stats(struct seq_file *, struct vfsmount *);
|
||||
static void nfs_zap_acl_cache(struct inode *);
|
||||
|
||||
static struct rpc_program nfs_program;
|
||||
@@ -78,6 +81,7 @@ static struct super_operations nfs_sops = {
|
||||
.clear_inode = nfs_clear_inode,
|
||||
.umount_begin = nfs_umount_begin,
|
||||
.show_options = nfs_show_options,
|
||||
.show_stats = nfs_show_stats,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -133,7 +137,7 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
|
||||
static int
|
||||
nfs_write_inode(struct inode *inode, int sync)
|
||||
{
|
||||
int flags = sync ? FLUSH_WAIT : 0;
|
||||
int flags = sync ? FLUSH_SYNC : 0;
|
||||
int ret;
|
||||
|
||||
ret = nfs_commit_inode(inode, flags);
|
||||
@@ -237,7 +241,6 @@ static struct inode *
|
||||
nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo)
|
||||
{
|
||||
struct nfs_server *server = NFS_SB(sb);
|
||||
struct inode *rooti;
|
||||
int error;
|
||||
|
||||
error = server->rpc_ops->getroot(server, rootfh, fsinfo);
|
||||
@@ -246,10 +249,7 @@ nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *f
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
rooti = nfs_fhget(sb, rootfh, fsinfo->fattr);
|
||||
if (!rooti)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
return rooti;
|
||||
return nfs_fhget(sb, rootfh, fsinfo->fattr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -277,6 +277,10 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
|
||||
|
||||
sb->s_magic = NFS_SUPER_MAGIC;
|
||||
|
||||
server->io_stats = nfs_alloc_iostats();
|
||||
if (server->io_stats == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
root_inode = nfs_get_root(sb, &server->fh, &fsinfo);
|
||||
/* Did getting the root inode fail? */
|
||||
if (IS_ERR(root_inode)) {
|
||||
@@ -290,6 +294,9 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
|
||||
}
|
||||
sb->s_root->d_op = server->rpc_ops->dentry_ops;
|
||||
|
||||
/* mount time stamp, in seconds */
|
||||
server->mount_time = jiffies;
|
||||
|
||||
/* Get some general file system info */
|
||||
if (server->namelen == 0 &&
|
||||
server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
|
||||
@@ -396,6 +403,9 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
|
||||
|
||||
nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans);
|
||||
|
||||
server->retrans_timeo = timeparms.to_initval;
|
||||
server->retrans_count = timeparms.to_retries;
|
||||
|
||||
/* create transport and client */
|
||||
xprt = xprt_create_proto(proto, &server->addr, &timeparms);
|
||||
if (IS_ERR(xprt)) {
|
||||
@@ -579,7 +589,7 @@ nfs_statfs(struct super_block *sb, struct kstatfs *buf)
|
||||
|
||||
}
|
||||
|
||||
static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
|
||||
static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
|
||||
{
|
||||
static struct proc_nfs_info {
|
||||
int flag;
|
||||
@@ -588,28 +598,26 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
|
||||
} nfs_info[] = {
|
||||
{ NFS_MOUNT_SOFT, ",soft", ",hard" },
|
||||
{ NFS_MOUNT_INTR, ",intr", "" },
|
||||
{ NFS_MOUNT_POSIX, ",posix", "" },
|
||||
{ NFS_MOUNT_NOCTO, ",nocto", "" },
|
||||
{ NFS_MOUNT_NOAC, ",noac", "" },
|
||||
{ NFS_MOUNT_NONLM, ",nolock", ",lock" },
|
||||
{ NFS_MOUNT_NONLM, ",nolock", "" },
|
||||
{ NFS_MOUNT_NOACL, ",noacl", "" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
struct proc_nfs_info *nfs_infop;
|
||||
struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
|
||||
char buf[12];
|
||||
char *proto;
|
||||
|
||||
seq_printf(m, ",v%d", nfss->rpc_ops->version);
|
||||
seq_printf(m, ",vers=%d", nfss->rpc_ops->version);
|
||||
seq_printf(m, ",rsize=%d", nfss->rsize);
|
||||
seq_printf(m, ",wsize=%d", nfss->wsize);
|
||||
if (nfss->acregmin != 3*HZ)
|
||||
if (nfss->acregmin != 3*HZ || showdefaults)
|
||||
seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
|
||||
if (nfss->acregmax != 60*HZ)
|
||||
if (nfss->acregmax != 60*HZ || showdefaults)
|
||||
seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
|
||||
if (nfss->acdirmin != 30*HZ)
|
||||
if (nfss->acdirmin != 30*HZ || showdefaults)
|
||||
seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
|
||||
if (nfss->acdirmax != 60*HZ)
|
||||
if (nfss->acdirmax != 60*HZ || showdefaults)
|
||||
seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
|
||||
for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
|
||||
if (nfss->flags & nfs_infop->flag)
|
||||
@@ -629,8 +637,96 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
|
||||
proto = buf;
|
||||
}
|
||||
seq_printf(m, ",proto=%s", proto);
|
||||
seq_printf(m, ",timeo=%lu", 10U * nfss->retrans_timeo / HZ);
|
||||
seq_printf(m, ",retrans=%u", nfss->retrans_count);
|
||||
}
|
||||
|
||||
static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
|
||||
{
|
||||
struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
|
||||
|
||||
nfs_show_mount_options(m, nfss, 0);
|
||||
|
||||
seq_puts(m, ",addr=");
|
||||
seq_escape(m, nfss->hostname, " \t\n\\");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
|
||||
{
|
||||
int i, cpu;
|
||||
struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
|
||||
struct rpc_auth *auth = nfss->client->cl_auth;
|
||||
struct nfs_iostats totals = { };
|
||||
|
||||
seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS);
|
||||
|
||||
/*
|
||||
* Display all mount option settings
|
||||
*/
|
||||
seq_printf(m, "\n\topts:\t");
|
||||
seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw");
|
||||
seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : "");
|
||||
seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : "");
|
||||
seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : "");
|
||||
nfs_show_mount_options(m, nfss, 1);
|
||||
|
||||
seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);
|
||||
|
||||
seq_printf(m, "\n\tcaps:\t");
|
||||
seq_printf(m, "caps=0x%x", nfss->caps);
|
||||
seq_printf(m, ",wtmult=%d", nfss->wtmult);
|
||||
seq_printf(m, ",dtsize=%d", nfss->dtsize);
|
||||
seq_printf(m, ",bsize=%d", nfss->bsize);
|
||||
seq_printf(m, ",namelen=%d", nfss->namelen);
|
||||
|
||||
#ifdef CONFIG_NFS_V4
|
||||
if (nfss->rpc_ops->version == 4) {
|
||||
seq_printf(m, "\n\tnfsv4:\t");
|
||||
seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
|
||||
seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
|
||||
seq_printf(m, ",acl=0x%x", nfss->acl_bitmask);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Display security flavor in effect for this mount
|
||||
*/
|
||||
seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor);
|
||||
if (auth->au_flavor)
|
||||
seq_printf(m, ",pseudoflavor=%d", auth->au_flavor);
|
||||
|
||||
/*
|
||||
* Display superblock I/O counters
|
||||
*/
|
||||
for (cpu = 0; cpu < NR_CPUS; cpu++) {
|
||||
struct nfs_iostats *stats;
|
||||
|
||||
if (!cpu_possible(cpu))
|
||||
continue;
|
||||
|
||||
preempt_disable();
|
||||
stats = per_cpu_ptr(nfss->io_stats, cpu);
|
||||
|
||||
for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
|
||||
totals.events[i] += stats->events[i];
|
||||
for (i = 0; i < __NFSIOS_BYTESMAX; i++)
|
||||
totals.bytes[i] += stats->bytes[i];
|
||||
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
seq_printf(m, "\n\tevents:\t");
|
||||
for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
|
||||
seq_printf(m, "%lu ", totals.events[i]);
|
||||
seq_printf(m, "\n\tbytes:\t");
|
||||
for (i = 0; i < __NFSIOS_BYTESMAX; i++)
|
||||
seq_printf(m, "%Lu ", totals.bytes[i]);
|
||||
seq_printf(m, "\n");
|
||||
|
||||
rpc_print_iostats(m, nfss->client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -660,6 +756,8 @@ static void nfs_zap_caches_locked(struct inode *inode)
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
int mode = inode->i_mode;
|
||||
|
||||
nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
|
||||
|
||||
NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
|
||||
NFS_ATTRTIMEO_UPDATE(inode) = jiffies;
|
||||
|
||||
@@ -751,7 +849,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
|
||||
.fh = fh,
|
||||
.fattr = fattr
|
||||
};
|
||||
struct inode *inode = NULL;
|
||||
struct inode *inode = ERR_PTR(-ENOENT);
|
||||
unsigned long hash;
|
||||
|
||||
if ((fattr->valid & NFS_ATTR_FATTR) == 0)
|
||||
@@ -764,8 +862,11 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
|
||||
|
||||
hash = nfs_fattr_to_ino_t(fattr);
|
||||
|
||||
if (!(inode = iget5_locked(sb, hash, nfs_find_actor, nfs_init_locked, &desc)))
|
||||
inode = iget5_locked(sb, hash, nfs_find_actor, nfs_init_locked, &desc);
|
||||
if (inode == NULL) {
|
||||
inode = ERR_PTR(-ENOMEM);
|
||||
goto out_no_inode;
|
||||
}
|
||||
|
||||
if (inode->i_state & I_NEW) {
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
@@ -834,7 +935,7 @@ out:
|
||||
return inode;
|
||||
|
||||
out_no_inode:
|
||||
printk("nfs_fhget: iget failed\n");
|
||||
dprintk("nfs_fhget: iget failed with error %ld\n", PTR_ERR(inode));
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -847,6 +948,8 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
struct nfs_fattr fattr;
|
||||
int error;
|
||||
|
||||
nfs_inc_stats(inode, NFSIOS_VFSSETATTR);
|
||||
|
||||
if (attr->ia_valid & ATTR_SIZE) {
|
||||
if (!S_ISREG(inode->i_mode) || attr->ia_size == i_size_read(inode))
|
||||
attr->ia_valid &= ~ATTR_SIZE;
|
||||
@@ -859,11 +962,9 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
|
||||
lock_kernel();
|
||||
nfs_begin_data_update(inode);
|
||||
/* Write all dirty data if we're changing file permissions or size */
|
||||
if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE)) != 0) {
|
||||
filemap_write_and_wait(inode->i_mapping);
|
||||
nfs_wb_all(inode);
|
||||
}
|
||||
/* Write all dirty data */
|
||||
filemap_write_and_wait(inode->i_mapping);
|
||||
nfs_wb_all(inode);
|
||||
/*
|
||||
* Return any delegations if we're going to change ACLs
|
||||
*/
|
||||
@@ -902,6 +1003,7 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
if ((attr->ia_valid & ATTR_SIZE) != 0) {
|
||||
nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
|
||||
inode->i_size = attr->ia_size;
|
||||
vmtruncate(inode, attr->ia_size);
|
||||
}
|
||||
@@ -949,7 +1051,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
|
||||
int err;
|
||||
|
||||
/* Flush out writes to the server in order to update c/mtime */
|
||||
nfs_sync_inode(inode, 0, 0, FLUSH_WAIT|FLUSH_NOCOMMIT);
|
||||
nfs_sync_inode_wait(inode, 0, 0, FLUSH_NOCOMMIT);
|
||||
|
||||
/*
|
||||
* We may force a getattr if the user cares about atime.
|
||||
@@ -973,7 +1075,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
|
||||
return err;
|
||||
}
|
||||
|
||||
struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred)
|
||||
static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred)
|
||||
{
|
||||
struct nfs_open_context *ctx;
|
||||
|
||||
@@ -981,6 +1083,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rp
|
||||
if (ctx != NULL) {
|
||||
atomic_set(&ctx->count, 1);
|
||||
ctx->dentry = dget(dentry);
|
||||
ctx->vfsmnt = mntget(mnt);
|
||||
ctx->cred = get_rpccred(cred);
|
||||
ctx->state = NULL;
|
||||
ctx->lockowner = current->files;
|
||||
@@ -1011,6 +1114,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
|
||||
if (ctx->cred != NULL)
|
||||
put_rpccred(ctx->cred);
|
||||
dput(ctx->dentry);
|
||||
mntput(ctx->vfsmnt);
|
||||
kfree(ctx);
|
||||
}
|
||||
}
|
||||
@@ -1019,7 +1123,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
|
||||
* Ensure that mmap has a recent RPC credential for use when writing out
|
||||
* shared pages
|
||||
*/
|
||||
void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
|
||||
static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
|
||||
{
|
||||
struct inode *inode = filp->f_dentry->d_inode;
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
@@ -1051,7 +1155,7 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void nfs_file_clear_open_context(struct file *filp)
|
||||
static void nfs_file_clear_open_context(struct file *filp)
|
||||
{
|
||||
struct inode *inode = filp->f_dentry->d_inode;
|
||||
struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data;
|
||||
@@ -1076,7 +1180,7 @@ int nfs_open(struct inode *inode, struct file *filp)
|
||||
cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
|
||||
if (IS_ERR(cred))
|
||||
return PTR_ERR(cred);
|
||||
ctx = alloc_nfs_open_context(filp->f_dentry, cred);
|
||||
ctx = alloc_nfs_open_context(filp->f_vfsmnt, filp->f_dentry, cred);
|
||||
put_rpccred(cred);
|
||||
if (ctx == NULL)
|
||||
return -ENOMEM;
|
||||
@@ -1185,6 +1289,7 @@ int nfs_attribute_timeout(struct inode *inode)
|
||||
*/
|
||||
int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
|
||||
{
|
||||
nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE);
|
||||
if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
|
||||
&& !nfs_attribute_timeout(inode))
|
||||
return NFS_STALE(inode) ? -ESTALE : 0;
|
||||
@@ -1201,6 +1306,7 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
|
||||
if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
|
||||
nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
|
||||
if (S_ISREG(inode->i_mode))
|
||||
nfs_sync_mapping(mapping);
|
||||
invalidate_inode_pages2(mapping);
|
||||
@@ -1299,27 +1405,25 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
|
||||
if ((fattr->valid & NFS_ATTR_FATTR) == 0)
|
||||
return 0;
|
||||
|
||||
/* Are we in the process of updating data on the server? */
|
||||
data_unstable = nfs_caches_unstable(inode);
|
||||
|
||||
/* Do atomic weak cache consistency updates */
|
||||
nfs_wcc_update_inode(inode, fattr);
|
||||
|
||||
if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
|
||||
nfsi->change_attr != fattr->change_attr) {
|
||||
nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
|
||||
if (!data_unstable)
|
||||
nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
|
||||
}
|
||||
|
||||
/* Has the inode gone and changed behind our back? */
|
||||
if (nfsi->fileid != fattr->fileid
|
||||
|| (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
cur_size = i_size_read(inode);
|
||||
new_isize = nfs_size_to_loff_t(fattr->size);
|
||||
/* Are we in the process of updating data on the server? */
|
||||
data_unstable = nfs_caches_unstable(inode);
|
||||
|
||||
/* Do atomic weak cache consistency updates */
|
||||
nfs_wcc_update_inode(inode, fattr);
|
||||
|
||||
if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0) {
|
||||
if (nfsi->change_attr == fattr->change_attr)
|
||||
goto out;
|
||||
nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
|
||||
if (!data_unstable)
|
||||
nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
|
||||
}
|
||||
|
||||
/* Verify a few of the more important attributes */
|
||||
if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
|
||||
@@ -1327,11 +1431,11 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
|
||||
if (!data_unstable)
|
||||
nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
|
||||
}
|
||||
if (cur_size != new_isize) {
|
||||
nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
|
||||
if (nfsi->npages == 0)
|
||||
nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
|
||||
}
|
||||
|
||||
cur_size = i_size_read(inode);
|
||||
new_isize = nfs_size_to_loff_t(fattr->size);
|
||||
if (cur_size != new_isize && nfsi->npages == 0)
|
||||
nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
|
||||
|
||||
/* Have any file permissions changed? */
|
||||
if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
|
||||
@@ -1343,6 +1447,7 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
|
||||
if (inode->i_nlink != fattr->nlink)
|
||||
nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
|
||||
|
||||
out:
|
||||
if (!timespec_equal(&inode->i_atime, &fattr->atime))
|
||||
nfsi->cache_validity |= NFS_INO_INVALID_ATIME;
|
||||
|
||||
@@ -1481,15 +1586,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
||||
nfsi->cache_change_attribute = jiffies;
|
||||
}
|
||||
|
||||
if ((fattr->valid & NFS_ATTR_FATTR_V4)
|
||||
&& nfsi->change_attr != fattr->change_attr) {
|
||||
dprintk("NFS: change_attr change on server for file %s/%ld\n",
|
||||
inode->i_sb->s_id, inode->i_ino);
|
||||
nfsi->change_attr = fattr->change_attr;
|
||||
invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
|
||||
nfsi->cache_change_attribute = jiffies;
|
||||
}
|
||||
|
||||
/* If ctime has changed we should definitely clear access+acl caches */
|
||||
if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) {
|
||||
invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
|
||||
@@ -1519,8 +1615,20 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
||||
inode->i_blksize = fattr->du.nfs2.blocksize;
|
||||
}
|
||||
|
||||
if ((fattr->valid & NFS_ATTR_FATTR_V4)) {
|
||||
if (nfsi->change_attr != fattr->change_attr) {
|
||||
dprintk("NFS: change_attr change on server for file %s/%ld\n",
|
||||
inode->i_sb->s_id, inode->i_ino);
|
||||
nfsi->change_attr = fattr->change_attr;
|
||||
invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
|
||||
nfsi->cache_change_attribute = jiffies;
|
||||
} else
|
||||
invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA);
|
||||
}
|
||||
|
||||
/* Update attrtimeo value if we're out of the unstable period */
|
||||
if (invalid & NFS_INO_INVALID_ATTR) {
|
||||
nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
|
||||
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
|
||||
nfsi->attrtimeo_timestamp = jiffies;
|
||||
} else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) {
|
||||
@@ -1637,10 +1745,9 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
|
||||
#endif /* CONFIG_NFS_V3 */
|
||||
|
||||
s = ERR_PTR(-ENOMEM);
|
||||
server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
|
||||
server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
|
||||
if (!server)
|
||||
goto out_err;
|
||||
memset(server, 0, sizeof(struct nfs_server));
|
||||
/* Zero out the NFS state stuff */
|
||||
init_nfsv4_state(server);
|
||||
server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
|
||||
@@ -1712,6 +1819,7 @@ static void nfs_kill_super(struct super_block *s)
|
||||
|
||||
rpciod_down(); /* release rpciod */
|
||||
|
||||
nfs_free_iostats(server->io_stats);
|
||||
kfree(server->hostname);
|
||||
kfree(server);
|
||||
}
|
||||
@@ -1738,6 +1846,7 @@ static struct super_operations nfs4_sops = {
|
||||
.clear_inode = nfs4_clear_inode,
|
||||
.umount_begin = nfs_umount_begin,
|
||||
.show_options = nfs_show_options,
|
||||
.show_stats = nfs_show_stats,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1800,6 +1909,9 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
|
||||
|
||||
nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans);
|
||||
|
||||
server->retrans_timeo = timeparms.to_initval;
|
||||
server->retrans_count = timeparms.to_retries;
|
||||
|
||||
clp = nfs4_get_client(&server->addr.sin_addr);
|
||||
if (!clp) {
|
||||
dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
|
||||
@@ -1941,10 +2053,9 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
|
||||
server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
|
||||
if (!server)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
memset(server, 0, sizeof(struct nfs_server));
|
||||
/* Zero out the NFS state stuff */
|
||||
init_nfsv4_state(server);
|
||||
server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
|
||||
@@ -2024,10 +2135,12 @@ static void nfs4_kill_super(struct super_block *sb)
|
||||
|
||||
if (server->client != NULL && !IS_ERR(server->client))
|
||||
rpc_shutdown_client(server->client);
|
||||
rpciod_down(); /* release rpciod */
|
||||
|
||||
destroy_nfsv4_state(server);
|
||||
|
||||
rpciod_down();
|
||||
|
||||
nfs_free_iostats(server->io_stats);
|
||||
kfree(server->hostname);
|
||||
kfree(server);
|
||||
}
|
||||
|
Reference in New Issue
Block a user