aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/generic.c')
-rw-r--r--fs/proc/generic.c48
1 files changed, 21 insertions, 27 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 0d80cef4cfb9..76ddae83daa5 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -261,16 +261,9 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
261 if (error) 261 if (error)
262 return error; 262 return error;
263 263
264 if ((iattr->ia_valid & ATTR_SIZE) &&
265 iattr->ia_size != i_size_read(inode)) {
266 error = vmtruncate(inode, iattr->ia_size);
267 if (error)
268 return error;
269 }
270
271 setattr_copy(inode, iattr); 264 setattr_copy(inode, iattr);
272 mark_inode_dirty(inode); 265 mark_inode_dirty(inode);
273 266
274 de->uid = inode->i_uid; 267 de->uid = inode->i_uid;
275 de->gid = inode->i_gid; 268 de->gid = inode->i_gid;
276 de->mode = inode->i_mode; 269 de->mode = inode->i_mode;
@@ -350,37 +343,39 @@ static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
350 * Return an inode number between PROC_DYNAMIC_FIRST and 343 * Return an inode number between PROC_DYNAMIC_FIRST and
351 * 0xffffffff, or zero on failure. 344 * 0xffffffff, or zero on failure.
352 */ 345 */
353static unsigned int get_inode_number(void) 346int proc_alloc_inum(unsigned int *inum)
354{ 347{
355 unsigned int i; 348 unsigned int i;
356 int error; 349 int error;
357 350
358retry: 351retry:
359 if (ida_pre_get(&proc_inum_ida, GFP_KERNEL) == 0) 352 if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
360 return 0; 353 return -ENOMEM;
361 354
362 spin_lock(&proc_inum_lock); 355 spin_lock_irq(&proc_inum_lock);
363 error = ida_get_new(&proc_inum_ida, &i); 356 error = ida_get_new(&proc_inum_ida, &i);
364 spin_unlock(&proc_inum_lock); 357 spin_unlock_irq(&proc_inum_lock);
365 if (error == -EAGAIN) 358 if (error == -EAGAIN)
366 goto retry; 359 goto retry;
367 else if (error) 360 else if (error)
368 return 0; 361 return error;
369 362
370 if (i > UINT_MAX - PROC_DYNAMIC_FIRST) { 363 if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
371 spin_lock(&proc_inum_lock); 364 spin_lock_irq(&proc_inum_lock);
372 ida_remove(&proc_inum_ida, i); 365 ida_remove(&proc_inum_ida, i);
373 spin_unlock(&proc_inum_lock); 366 spin_unlock_irq(&proc_inum_lock);
374 return 0; 367 return -ENOSPC;
375 } 368 }
376 return PROC_DYNAMIC_FIRST + i; 369 *inum = PROC_DYNAMIC_FIRST + i;
370 return 0;
377} 371}
378 372
379static void release_inode_number(unsigned int inum) 373void proc_free_inum(unsigned int inum)
380{ 374{
381 spin_lock(&proc_inum_lock); 375 unsigned long flags;
376 spin_lock_irqsave(&proc_inum_lock, flags);
382 ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST); 377 ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
383 spin_unlock(&proc_inum_lock); 378 spin_unlock_irqrestore(&proc_inum_lock, flags);
384} 379}
385 380
386static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) 381static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
@@ -554,13 +549,12 @@ static const struct inode_operations proc_dir_inode_operations = {
554 549
555static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp) 550static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
556{ 551{
557 unsigned int i;
558 struct proc_dir_entry *tmp; 552 struct proc_dir_entry *tmp;
553 int ret;
559 554
560 i = get_inode_number(); 555 ret = proc_alloc_inum(&dp->low_ino);
561 if (i == 0) 556 if (ret)
562 return -EAGAIN; 557 return ret;
563 dp->low_ino = i;
564 558
565 if (S_ISDIR(dp->mode)) { 559 if (S_ISDIR(dp->mode)) {
566 if (dp->proc_iops == NULL) { 560 if (dp->proc_iops == NULL) {
@@ -764,7 +758,7 @@ EXPORT_SYMBOL(proc_create_data);
764 758
765static void free_proc_entry(struct proc_dir_entry *de) 759static void free_proc_entry(struct proc_dir_entry *de)
766{ 760{
767 release_inode_number(de->low_ino); 761 proc_free_inum(de->low_ino);
768 762
769 if (S_ISLNK(de->mode)) 763 if (S_ISLNK(de->mode))
770 kfree(de->data); 764 kfree(de->data);