diff options
Diffstat (limited to 'fs/inode.c')
| -rw-r--r-- | fs/inode.c | 88 | 
1 files changed, 81 insertions, 7 deletions
diff --git a/fs/inode.c b/fs/inode.c index 6b80a51129d5..63324df6fa27 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -67,11 +67,6 @@ const struct address_space_operations empty_aops = {  };  EXPORT_SYMBOL(empty_aops); -/* - * Statistics gathering.. - */ -struct inodes_stat_t inodes_stat; -  static DEFINE_PER_CPU(unsigned long, nr_inodes);  static DEFINE_PER_CPU(unsigned long, nr_unused); @@ -106,13 +101,43 @@ long get_nr_dirty_inodes(void)   * Handle nr_inode sysctl   */  #ifdef CONFIG_SYSCTL -int proc_nr_inodes(struct ctl_table *table, int write, -		   void *buffer, size_t *lenp, loff_t *ppos) +/* + * Statistics gathering.. + */ +static struct inodes_stat_t inodes_stat; + +static int proc_nr_inodes(struct ctl_table *table, int write, void *buffer, +			  size_t *lenp, loff_t *ppos)  {  	inodes_stat.nr_inodes = get_nr_inodes();  	inodes_stat.nr_unused = get_nr_inodes_unused();  	return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);  } + +static struct ctl_table inodes_sysctls[] = { +	{ +		.procname	= "inode-nr", +		.data		= &inodes_stat, +		.maxlen		= 2*sizeof(long), +		.mode		= 0444, +		.proc_handler	= proc_nr_inodes, +	}, +	{ +		.procname	= "inode-state", +		.data		= &inodes_stat, +		.maxlen		= 7*sizeof(long), +		.mode		= 0444, +		.proc_handler	= proc_nr_inodes, +	}, +	{ } +}; + +static int __init init_fs_inode_sysctls(void) +{ +	register_sysctl_init("fs", inodes_sysctls); +	return 0; +} +early_initcall(init_fs_inode_sysctls);  #endif  static int no_open(struct inode *inode, struct file *file) @@ -526,6 +551,55 @@ void __remove_inode_hash(struct inode *inode)  }  EXPORT_SYMBOL(__remove_inode_hash); +void dump_mapping(const struct address_space *mapping) +{ +	struct inode *host; +	const struct address_space_operations *a_ops; +	struct hlist_node *dentry_first; +	struct dentry *dentry_ptr; +	struct dentry dentry; +	unsigned long ino; + +	/* +	 * If mapping is an invalid pointer, we don't want to crash +	 * accessing it, so probe everything depending on it carefully. +	 */ +	if (get_kernel_nofault(host, &mapping->host) || +	    get_kernel_nofault(a_ops, &mapping->a_ops)) { +		pr_warn("invalid mapping:%px\n", mapping); +		return; +	} + +	if (!host) { +		pr_warn("aops:%ps\n", a_ops); +		return; +	} + +	if (get_kernel_nofault(dentry_first, &host->i_dentry.first) || +	    get_kernel_nofault(ino, &host->i_ino)) { +		pr_warn("aops:%ps invalid inode:%px\n", a_ops, host); +		return; +	} + +	if (!dentry_first) { +		pr_warn("aops:%ps ino:%lx\n", a_ops, ino); +		return; +	} + +	dentry_ptr = container_of(dentry_first, struct dentry, d_u.d_alias); +	if (get_kernel_nofault(dentry, dentry_ptr)) { +		pr_warn("aops:%ps ino:%lx invalid dentry:%px\n", +				a_ops, ino, dentry_ptr); +		return; +	} + +	/* +	 * if dentry is corrupted, the %pd handler may still crash, +	 * but it's unlikely that we reach here with a corrupt mapping +	 */ +	pr_warn("aops:%ps ino:%lx dentry name:\"%pd\"\n", a_ops, ino, &dentry); +} +  void clear_inode(struct inode *inode)  {  	/*  |