Merge branch 'drm-tda9950-fixes' of git://git.armlinux.org.uk/~rmk/linux-arm into...
[linux-2.6-microblaze.git] / fs / file_table.c
index d6eccd0..e49af4c 100644 (file)
@@ -52,7 +52,8 @@ static void file_free_rcu(struct rcu_head *head)
 static inline void file_free(struct file *f)
 {
        security_file_free(f);
-       percpu_counter_dec(&nr_files);
+       if (!(f->f_mode & FMODE_NOACCOUNT))
+               percpu_counter_dec(&nr_files);
        call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
 }
 
@@ -91,6 +92,34 @@ int proc_nr_files(struct ctl_table *table, int write,
 }
 #endif
 
+static struct file *__alloc_file(int flags, const struct cred *cred)
+{
+       struct file *f;
+       int error;
+
+       f = kmem_cache_zalloc(filp_cachep, GFP_KERNEL);
+       if (unlikely(!f))
+               return ERR_PTR(-ENOMEM);
+
+       f->f_cred = get_cred(cred);
+       error = security_file_alloc(f);
+       if (unlikely(error)) {
+               file_free_rcu(&f->f_u.fu_rcuhead);
+               return ERR_PTR(error);
+       }
+
+       atomic_long_set(&f->f_count, 1);
+       rwlock_init(&f->f_owner.lock);
+       spin_lock_init(&f->f_lock);
+       mutex_init(&f->f_pos_lock);
+       eventpoll_init_file(f);
+       f->f_flags = flags;
+       f->f_mode = OPEN_FMODE(flags);
+       /* f->f_version: 0 */
+
+       return f;
+}
+
 /* Find an unused file structure and return a pointer to it.
  * Returns an error pointer if some error happend e.g. we over file
  * structures limit, run out of memory or operation is not permitted.
@@ -105,7 +134,6 @@ struct file *alloc_empty_file(int flags, const struct cred *cred)
 {
        static long old_max;
        struct file *f;
-       int error;
 
        /*
         * Privileged users can go above max_files
@@ -119,26 +147,10 @@ struct file *alloc_empty_file(int flags, const struct cred *cred)
                        goto over;
        }
 
-       f = kmem_cache_zalloc(filp_cachep, GFP_KERNEL);
-       if (unlikely(!f))
-               return ERR_PTR(-ENOMEM);
-
-       f->f_cred = get_cred(cred);
-       error = security_file_alloc(f);
-       if (unlikely(error)) {
-               file_free_rcu(&f->f_u.fu_rcuhead);
-               return ERR_PTR(error);
-       }
+       f = __alloc_file(flags, cred);
+       if (!IS_ERR(f))
+               percpu_counter_inc(&nr_files);
 
-       atomic_long_set(&f->f_count, 1);
-       rwlock_init(&f->f_owner.lock);
-       spin_lock_init(&f->f_lock);
-       mutex_init(&f->f_pos_lock);
-       eventpoll_init_file(f);
-       f->f_flags = flags;
-       f->f_mode = OPEN_FMODE(flags);
-       /* f->f_version: 0 */
-       percpu_counter_inc(&nr_files);
        return f;
 
 over:
@@ -150,6 +162,21 @@ over:
        return ERR_PTR(-ENFILE);
 }
 
+/*
+ * Variant of alloc_empty_file() that doesn't check and modify nr_files.
+ *
+ * Should not be used unless there's a very good reason to do so.
+ */
+struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred)
+{
+       struct file *f = __alloc_file(flags, cred);
+
+       if (!IS_ERR(f))
+               f->f_mode |= FMODE_NOACCOUNT;
+
+       return f;
+}
+
 /**
  * alloc_file - allocate and initialize a 'struct file'
  *