diff options
Diffstat (limited to 'fs/proc/generic.c')
-rw-r--r-- | fs/proc/generic.c | 83 |
1 files changed, 3 insertions, 80 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index a6a1cb5d589d..bec58323629c 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -39,7 +39,7 @@ static int proc_match(unsigned int len, const char *name, struct proc_dir_entry | |||
39 | /* buffer size is one page but our output routines use some slack for overruns */ | 39 | /* buffer size is one page but our output routines use some slack for overruns */ |
40 | #define PROC_BLOCK_SIZE (PAGE_SIZE - 1024) | 40 | #define PROC_BLOCK_SIZE (PAGE_SIZE - 1024) |
41 | 41 | ||
42 | static ssize_t | 42 | ssize_t |
43 | __proc_file_read(struct file *file, char __user *buf, size_t nbytes, | 43 | __proc_file_read(struct file *file, char __user *buf, size_t nbytes, |
44 | loff_t *ppos) | 44 | loff_t *ppos) |
45 | { | 45 | { |
@@ -171,48 +171,6 @@ __proc_file_read(struct file *file, char __user *buf, size_t nbytes, | |||
171 | return retval; | 171 | return retval; |
172 | } | 172 | } |
173 | 173 | ||
174 | static ssize_t | ||
175 | proc_file_read(struct file *file, char __user *buf, size_t nbytes, | ||
176 | loff_t *ppos) | ||
177 | { | ||
178 | struct proc_dir_entry *pde = PDE(file_inode(file)); | ||
179 | ssize_t rv = -EIO; | ||
180 | |||
181 | spin_lock(&pde->pde_unload_lock); | ||
182 | if (!pde->proc_fops) { | ||
183 | spin_unlock(&pde->pde_unload_lock); | ||
184 | return rv; | ||
185 | } | ||
186 | pde->pde_users++; | ||
187 | spin_unlock(&pde->pde_unload_lock); | ||
188 | |||
189 | rv = __proc_file_read(file, buf, nbytes, ppos); | ||
190 | |||
191 | pde_users_dec(pde); | ||
192 | return rv; | ||
193 | } | ||
194 | |||
195 | static loff_t | ||
196 | proc_file_lseek(struct file *file, loff_t offset, int orig) | ||
197 | { | ||
198 | loff_t retval = -EINVAL; | ||
199 | switch (orig) { | ||
200 | case 1: | ||
201 | offset += file->f_pos; | ||
202 | /* fallthrough */ | ||
203 | case 0: | ||
204 | if (offset < 0 || offset > MAX_NON_LFS) | ||
205 | break; | ||
206 | file->f_pos = retval = offset; | ||
207 | } | ||
208 | return retval; | ||
209 | } | ||
210 | |||
211 | static const struct file_operations proc_file_operations = { | ||
212 | .llseek = proc_file_lseek, | ||
213 | .read = proc_file_read, | ||
214 | }; | ||
215 | |||
216 | static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) | 174 | static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) |
217 | { | 175 | { |
218 | struct inode *inode = dentry->d_inode; | 176 | struct inode *inode = dentry->d_inode; |
@@ -722,41 +680,6 @@ void pde_put(struct proc_dir_entry *pde) | |||
722 | free_proc_entry(pde); | 680 | free_proc_entry(pde); |
723 | } | 681 | } |
724 | 682 | ||
725 | static void entry_rundown(struct proc_dir_entry *de) | ||
726 | { | ||
727 | spin_lock(&de->pde_unload_lock); | ||
728 | /* | ||
729 | * Stop accepting new callers into module. If you're | ||
730 | * dynamically allocating ->proc_fops, save a pointer somewhere. | ||
731 | */ | ||
732 | de->proc_fops = NULL; | ||
733 | /* Wait until all existing callers into module are done. */ | ||
734 | if (de->pde_users > 0) { | ||
735 | DECLARE_COMPLETION_ONSTACK(c); | ||
736 | |||
737 | if (!de->pde_unload_completion) | ||
738 | de->pde_unload_completion = &c; | ||
739 | |||
740 | spin_unlock(&de->pde_unload_lock); | ||
741 | |||
742 | wait_for_completion(de->pde_unload_completion); | ||
743 | |||
744 | spin_lock(&de->pde_unload_lock); | ||
745 | } | ||
746 | |||
747 | while (!list_empty(&de->pde_openers)) { | ||
748 | struct pde_opener *pdeo; | ||
749 | |||
750 | pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh); | ||
751 | list_del(&pdeo->lh); | ||
752 | spin_unlock(&de->pde_unload_lock); | ||
753 | pdeo->release(pdeo->inode, pdeo->file); | ||
754 | kfree(pdeo); | ||
755 | spin_lock(&de->pde_unload_lock); | ||
756 | } | ||
757 | spin_unlock(&de->pde_unload_lock); | ||
758 | } | ||
759 | |||
760 | /* | 683 | /* |
761 | * Remove a /proc entry and free it if it's not currently in use. | 684 | * Remove a /proc entry and free it if it's not currently in use. |
762 | */ | 685 | */ |
@@ -788,7 +711,7 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | |||
788 | return; | 711 | return; |
789 | } | 712 | } |
790 | 713 | ||
791 | entry_rundown(de); | 714 | proc_entry_rundown(de); |
792 | 715 | ||
793 | if (S_ISDIR(de->mode)) | 716 | if (S_ISDIR(de->mode)) |
794 | parent->nlink--; | 717 | parent->nlink--; |
@@ -837,7 +760,7 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) | |||
837 | } | 760 | } |
838 | spin_unlock(&proc_subdir_lock); | 761 | spin_unlock(&proc_subdir_lock); |
839 | 762 | ||
840 | entry_rundown(de); | 763 | proc_entry_rundown(de); |
841 | next = de->parent; | 764 | next = de->parent; |
842 | if (S_ISDIR(de->mode)) | 765 | if (S_ISDIR(de->mode)) |
843 | next->nlink--; | 766 | next->nlink--; |