diff options
| author | Frederic Weisbecker <fweisbec@gmail.com> | 2013-05-02 17:37:49 +0200 | 
|---|---|---|
| committer | Frederic Weisbecker <fweisbec@gmail.com> | 2013-05-02 17:54:19 +0200 | 
| commit | c032862fba51a3ca504752d3a25186b324c5ce83 (patch) | |
| tree | 955dc2ba4ab3df76ecc2bb780ee84aca04967e8d /fs/proc/generic.c | |
| parent | fda76e074c7737fc57855dd17c762e50ed526052 (diff) | |
| parent | 8700c95adb033843fc163d112b9d21d4fda78018 (diff) | |
| download | olio-linux-3.10-c032862fba51a3ca504752d3a25186b324c5ce83.tar.xz olio-linux-3.10-c032862fba51a3ca504752d3a25186b324c5ce83.zip  | |
Merge commit '8700c95adb03' into timers/nohz
The full dynticks tree needs the latest RCU and sched
upstream updates in order to fix some dependencies.
Merge a common upstream merge point that has these
updates.
Conflicts:
	include/linux/perf_event.h
	kernel/rcutree.h
	kernel/rcutree_plugin.h
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'fs/proc/generic.c')
| -rw-r--r-- | fs/proc/generic.c | 119 | 
1 files changed, 89 insertions, 30 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 4b3b3ffb52f..21e1a8f1659 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -755,37 +755,8 @@ void pde_put(struct proc_dir_entry *pde)  		free_proc_entry(pde);  } -/* - * Remove a /proc entry and free it if it's not currently in use. - */ -void remove_proc_entry(const char *name, struct proc_dir_entry *parent) +static void entry_rundown(struct proc_dir_entry *de)  { -	struct proc_dir_entry **p; -	struct proc_dir_entry *de = NULL; -	const char *fn = name; -	unsigned int len; - -	spin_lock(&proc_subdir_lock); -	if (__xlate_proc_name(name, &parent, &fn) != 0) { -		spin_unlock(&proc_subdir_lock); -		return; -	} -	len = strlen(fn); - -	for (p = &parent->subdir; *p; p=&(*p)->next ) { -		if (proc_match(len, fn, *p)) { -			de = *p; -			*p = de->next; -			de->next = NULL; -			break; -		} -	} -	spin_unlock(&proc_subdir_lock); -	if (!de) { -		WARN(1, "name '%s'\n", name); -		return; -	} -  	spin_lock(&de->pde_unload_lock);  	/*  	 * Stop accepting new callers into module. If you're @@ -817,6 +788,40 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)  		spin_lock(&de->pde_unload_lock);  	}  	spin_unlock(&de->pde_unload_lock); +} + +/* + * Remove a /proc entry and free it if it's not currently in use. + */ +void remove_proc_entry(const char *name, struct proc_dir_entry *parent) +{ +	struct proc_dir_entry **p; +	struct proc_dir_entry *de = NULL; +	const char *fn = name; +	unsigned int len; + +	spin_lock(&proc_subdir_lock); +	if (__xlate_proc_name(name, &parent, &fn) != 0) { +		spin_unlock(&proc_subdir_lock); +		return; +	} +	len = strlen(fn); + +	for (p = &parent->subdir; *p; p=&(*p)->next ) { +		if (proc_match(len, fn, *p)) { +			de = *p; +			*p = de->next; +			de->next = NULL; +			break; +		} +	} +	spin_unlock(&proc_subdir_lock); +	if (!de) { +		WARN(1, "name '%s'\n", name); +		return; +	} + +	entry_rundown(de);  	if (S_ISDIR(de->mode))  		parent->nlink--; @@ -827,3 +832,57 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)  	pde_put(de);  }  EXPORT_SYMBOL(remove_proc_entry); + +int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) +{ +	struct proc_dir_entry **p; +	struct proc_dir_entry *root = NULL, *de, *next; +	const char *fn = name; +	unsigned int len; + +	spin_lock(&proc_subdir_lock); +	if (__xlate_proc_name(name, &parent, &fn) != 0) { +		spin_unlock(&proc_subdir_lock); +		return -ENOENT; +	} +	len = strlen(fn); + +	for (p = &parent->subdir; *p; p=&(*p)->next ) { +		if (proc_match(len, fn, *p)) { +			root = *p; +			*p = root->next; +			root->next = NULL; +			break; +		} +	} +	if (!root) { +		spin_unlock(&proc_subdir_lock); +		return -ENOENT; +	} +	de = root; +	while (1) { +		next = de->subdir; +		if (next) { +			de->subdir = next->next; +			next->next = NULL; +			de = next; +			continue; +		} +		spin_unlock(&proc_subdir_lock); + +		entry_rundown(de); +		next = de->parent; +		if (S_ISDIR(de->mode)) +			next->nlink--; +		de->nlink = 0; +		if (de == root) +			break; +		pde_put(de); + +		spin_lock(&proc_subdir_lock); +		de = next; +	} +	pde_put(root); +	return 0; +} +EXPORT_SYMBOL(remove_proc_subtree);  |