diff options
Diffstat (limited to 'fs/nfs/inode.c')
| -rw-r--r-- | fs/nfs/inode.c | 119 | 
1 files changed, 106 insertions, 13 deletions
| diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index f649fba8c384..7bb4d13c1cd5 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -39,6 +39,7 @@  #include <linux/slab.h>  #include <linux/compat.h>  #include <linux/freezer.h> +#include <linux/crc32.h>  #include <asm/system.h>  #include <asm/uaccess.h> @@ -51,6 +52,7 @@  #include "fscache.h"  #include "dns_resolve.h"  #include "pnfs.h" +#include "netns.h"  #define NFSDBG_FACILITY		NFSDBG_VFS @@ -388,9 +390,10 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)  		unlock_new_inode(inode);  	} else  		nfs_refresh_inode(inode, fattr); -	dprintk("NFS: nfs_fhget(%s/%Ld ct=%d)\n", +	dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n",  		inode->i_sb->s_id,  		(long long)NFS_FILEID(inode), +		nfs_display_fhandle_hash(fh),  		atomic_read(&inode->i_count));  out: @@ -401,7 +404,7 @@ out_no_inode:  	goto out;  } -#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE) +#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE|ATTR_OPEN)  int  nfs_setattr(struct dentry *dentry, struct iattr *attr) @@ -423,7 +426,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)  	/* Optimization: if the end result is no change, don't RPC */  	attr->ia_valid &= NFS_VALID_ATTRS; -	if ((attr->ia_valid & ~ATTR_FILE) == 0) +	if ((attr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0)  		return 0;  	/* Write all dirty data */ @@ -1044,6 +1047,67 @@ struct nfs_fh *nfs_alloc_fhandle(void)  	return fh;  } +#ifdef NFS_DEBUG +/* + * _nfs_display_fhandle_hash - calculate the crc32 hash for the filehandle + *                             in the same way that wireshark does + * + * @fh: file handle + * + * For debugging only. + */ +u32 _nfs_display_fhandle_hash(const struct nfs_fh *fh) +{ +	/* wireshark uses 32-bit AUTODIN crc and does a bitwise +	 * not on the result */ +	return ~crc32(0xFFFFFFFF, &fh->data[0], fh->size); +} + +/* + * _nfs_display_fhandle - display an NFS file handle on the console + * + * @fh: file handle to display + * @caption: display caption + * + * For debugging only. + */ +void _nfs_display_fhandle(const struct nfs_fh *fh, const char *caption) +{ +	unsigned short i; + +	if (fh == NULL || fh->size == 0) { +		printk(KERN_DEFAULT "%s at %p is empty\n", caption, fh); +		return; +	} + +	printk(KERN_DEFAULT "%s at %p is %u bytes, crc: 0x%08x:\n", +	       caption, fh, fh->size, _nfs_display_fhandle_hash(fh)); +	for (i = 0; i < fh->size; i += 16) { +		__be32 *pos = (__be32 *)&fh->data[i]; + +		switch ((fh->size - i - 1) >> 2) { +		case 0: +			printk(KERN_DEFAULT " %08x\n", +				be32_to_cpup(pos)); +			break; +		case 1: +			printk(KERN_DEFAULT " %08x %08x\n", +				be32_to_cpup(pos), be32_to_cpup(pos + 1)); +			break; +		case 2: +			printk(KERN_DEFAULT " %08x %08x %08x\n", +				be32_to_cpup(pos), be32_to_cpup(pos + 1), +				be32_to_cpup(pos + 2)); +			break; +		default: +			printk(KERN_DEFAULT " %08x %08x %08x %08x\n", +				be32_to_cpup(pos), be32_to_cpup(pos + 1), +				be32_to_cpup(pos + 2), be32_to_cpup(pos + 3)); +		} +	} +} +#endif +  /**   * nfs_inode_attrs_need_update - check if the inode attributes need updating   * @inode - pointer to inode @@ -1211,8 +1275,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)  	unsigned long now = jiffies;  	unsigned long save_cache_validity; -	dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", +	dfprintk(VFS, "NFS: %s(%s/%ld fh_crc=0x%08x ct=%d info=0x%x)\n",  			__func__, inode->i_sb->s_id, inode->i_ino, +			nfs_display_fhandle_hash(NFS_FH(inode)),  			atomic_read(&inode->i_count), fattr->valid);  	if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) @@ -1406,7 +1471,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)  	/*  	 * Big trouble! The inode has become a different object.  	 */ -	printk(KERN_DEBUG "%s: inode %ld mode changed, %07o to %07o\n", +	printk(KERN_DEBUG "NFS: %s: inode %ld mode changed, %07o to %07o\n",  			__func__, inode->i_ino, inode->i_mode, fattr->mode);   out_err:  	/* @@ -1495,7 +1560,7 @@ static void init_once(void *foo)  	INIT_LIST_HEAD(&nfsi->open_files);  	INIT_LIST_HEAD(&nfsi->access_cache_entry_lru);  	INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); -	INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); +	INIT_LIST_HEAD(&nfsi->commit_list);  	nfsi->npages = 0;  	nfsi->ncommit = 0;  	atomic_set(&nfsi->silly_count, 1); @@ -1552,6 +1617,28 @@ static void nfsiod_stop(void)  	destroy_workqueue(wq);  } +int nfs_net_id; +EXPORT_SYMBOL_GPL(nfs_net_id); + +static int nfs_net_init(struct net *net) +{ +	nfs_clients_init(net); +	return nfs_dns_resolver_cache_init(net); +} + +static void nfs_net_exit(struct net *net) +{ +	nfs_dns_resolver_cache_destroy(net); +	nfs_cleanup_cb_ident_idr(net); +} + +static struct pernet_operations nfs_net_ops = { +	.init = nfs_net_init, +	.exit = nfs_net_exit, +	.id   = &nfs_net_id, +	.size = sizeof(struct nfs_net), +}; +  /*   * Initialize NFS   */ @@ -1561,10 +1648,14 @@ static int __init init_nfs_fs(void)  	err = nfs_idmap_init();  	if (err < 0) -		goto out9; +		goto out10;  	err = nfs_dns_resolver_init();  	if (err < 0) +		goto out9; + +	err = register_pernet_subsys(&nfs_net_ops); +	if (err < 0)  		goto out8;  	err = nfs_fscache_register(); @@ -1600,14 +1691,14 @@ static int __init init_nfs_fs(void)  		goto out0;  #ifdef CONFIG_PROC_FS -	rpc_proc_register(&nfs_rpcstat); +	rpc_proc_register(&init_net, &nfs_rpcstat);  #endif  	if ((err = register_nfs_fs()) != 0)  		goto out;  	return 0;  out:  #ifdef CONFIG_PROC_FS -	rpc_proc_unregister("nfs"); +	rpc_proc_unregister(&init_net, "nfs");  #endif  	nfs_destroy_directcache();  out0: @@ -1625,10 +1716,12 @@ out5:  out6:  	nfs_fscache_unregister();  out7: -	nfs_dns_resolver_destroy(); +	unregister_pernet_subsys(&nfs_net_ops);  out8: -	nfs_idmap_quit(); +	nfs_dns_resolver_destroy();  out9: +	nfs_idmap_quit(); +out10:  	return err;  } @@ -1640,12 +1733,12 @@ static void __exit exit_nfs_fs(void)  	nfs_destroy_inodecache();  	nfs_destroy_nfspagecache();  	nfs_fscache_unregister(); +	unregister_pernet_subsys(&nfs_net_ops);  	nfs_dns_resolver_destroy();  	nfs_idmap_quit();  #ifdef CONFIG_PROC_FS -	rpc_proc_unregister("nfs"); +	rpc_proc_unregister(&init_net, "nfs");  #endif -	nfs_cleanup_cb_ident_idr();  	unregister_nfs_fs();  	nfs_fs_proc_exit();  	nfsiod_stop(); | 
