Merge tag 'pwm/for-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry...
[linux-2.6-block.git] / fs / devpts / inode.c
index e072e955ce3334e44bdc529c2650518a6ca74a6c..c53814539070d5ac5d2196e2f4b7383055e11dd1 100644 (file)
@@ -46,7 +46,7 @@ static int pty_limit = NR_UNIX98_PTY_DEFAULT;
 static int pty_reserve = NR_UNIX98_PTY_RESERVE;
 static int pty_limit_min;
 static int pty_limit_max = INT_MAX;
-static int pty_count;
+static atomic_t pty_count = ATOMIC_INIT(0);
 
 static struct ctl_table pty_table[] = {
        {
@@ -93,8 +93,6 @@ static struct ctl_table pty_root_table[] = {
        {}
 };
 
-static DEFINE_MUTEX(allocated_ptys_lock);
-
 struct pts_mount_opts {
        int setuid;
        int setgid;
@@ -533,44 +531,25 @@ static struct file_system_type devpts_fs_type = {
 
 int devpts_new_index(struct pts_fs_info *fsi)
 {
-       int index;
-       int ida_ret;
-
-retry:
-       if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL))
-               return -ENOMEM;
-
-       mutex_lock(&allocated_ptys_lock);
-       if (pty_count >= (pty_limit -
-                         (fsi->mount_opts.reserve ? 0 : pty_reserve))) {
-               mutex_unlock(&allocated_ptys_lock);
-               return -ENOSPC;
-       }
+       int index = -ENOSPC;
 
-       ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
-       if (ida_ret < 0) {
-               mutex_unlock(&allocated_ptys_lock);
-               if (ida_ret == -EAGAIN)
-                       goto retry;
-               return -EIO;
-       }
+       if (atomic_inc_return(&pty_count) >= (pty_limit -
+                         (fsi->mount_opts.reserve ? 0 : pty_reserve)))
+               goto out;
 
-       if (index >= fsi->mount_opts.max) {
-               ida_remove(&fsi->allocated_ptys, index);
-               mutex_unlock(&allocated_ptys_lock);
-               return -ENOSPC;
-       }
-       pty_count++;
-       mutex_unlock(&allocated_ptys_lock);
+       index = ida_alloc_max(&fsi->allocated_ptys, fsi->mount_opts.max - 1,
+                       GFP_KERNEL);
+
+out:
+       if (index < 0)
+               atomic_dec(&pty_count);
        return index;
 }
 
 void devpts_kill_index(struct pts_fs_info *fsi, int idx)
 {
-       mutex_lock(&allocated_ptys_lock);
-       ida_remove(&fsi->allocated_ptys, idx);
-       pty_count--;
-       mutex_unlock(&allocated_ptys_lock);
+       ida_free(&fsi->allocated_ptys, idx);
+       atomic_dec(&pty_count);
 }
 
 /**