]> err.no Git - linux-2.6/blobdiff - fs/aio.c
[TCP]: fix congestion window update when using TSO deferal
[linux-2.6] / fs / aio.c
index d6b1551342b7206bff66323d60c6a8126bcaf813..20bb919eb1958e6e4dbbf96f6f04812a23983a24 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -42,8 +42,9 @@
 #endif
 
 /*------ sysctl variables----*/
-atomic_t aio_nr = ATOMIC_INIT(0);      /* current system wide number of aio requests */
-unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */
+static DEFINE_SPINLOCK(aio_nr_lock);
+unsigned long aio_nr;          /* current system wide number of aio requests */
+unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio requests */
 /*----end sysctl variables---*/
 
 static kmem_cache_t    *kiocb_cachep;
@@ -208,7 +209,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
                return ERR_PTR(-EINVAL);
        }
 
-       if (nr_events > aio_max_nr)
+       if ((unsigned long)nr_events > aio_max_nr)
                return ERR_PTR(-EAGAIN);
 
        ctx = kmem_cache_alloc(kioctx_cachep, GFP_KERNEL);
@@ -233,8 +234,14 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
                goto out_freectx;
 
        /* limit the number of system wide aios */
-       atomic_add(ctx->max_reqs, &aio_nr);     /* undone by __put_ioctx */
-       if (unlikely(atomic_read(&aio_nr) > aio_max_nr))
+       spin_lock(&aio_nr_lock);
+       if (aio_nr + ctx->max_reqs > aio_max_nr ||
+           aio_nr + ctx->max_reqs < aio_nr)
+               ctx->max_reqs = 0;
+       else
+               aio_nr += ctx->max_reqs;
+       spin_unlock(&aio_nr_lock);
+       if (ctx->max_reqs == 0)
                goto out_cleanup;
 
        /* now link into global list.  kludge.  FIXME */
@@ -248,8 +255,6 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
        return ctx;
 
 out_cleanup:
-       atomic_sub(ctx->max_reqs, &aio_nr);
-       ctx->max_reqs = 0;      /* prevent __put_ioctx from sub'ing aio_nr */
        __put_ioctx(ctx);
        return ERR_PTR(-EAGAIN);
 
@@ -374,7 +379,12 @@ void fastcall __put_ioctx(struct kioctx *ctx)
        pr_debug("__put_ioctx: freeing %p\n", ctx);
        kmem_cache_free(kioctx_cachep, ctx);
 
-       atomic_sub(nr_events, &aio_nr);
+       if (nr_events) {
+               spin_lock(&aio_nr_lock);
+               BUG_ON(aio_nr - nr_events > aio_nr);
+               aio_nr -= nr_events;
+               spin_unlock(&aio_nr_lock);
+       }
 }
 
 /* aio_get_req
@@ -398,7 +408,7 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx)
        if (unlikely(!req))
                return NULL;
 
-       req->ki_flags = 1 << KIF_LOCKED;
+       req->ki_flags = 0;
        req->ki_users = 2;
        req->ki_key = 0;
        req->ki_ctx = ctx;
@@ -547,25 +557,6 @@ struct kioctx *lookup_ioctx(unsigned long ctx_id)
        return ioctx;
 }
 
-static int lock_kiocb_action(void *param)
-{
-       schedule();
-       return 0;
-}
-
-static inline void lock_kiocb(struct kiocb *iocb)
-{
-       wait_on_bit_lock(&iocb->ki_flags, KIF_LOCKED, lock_kiocb_action,
-                        TASK_UNINTERRUPTIBLE);
-}
-
-static inline void unlock_kiocb(struct kiocb *iocb)
-{
-       kiocbClearLocked(iocb);
-       smp_mb__after_clear_bit();
-       wake_up_bit(&iocb->ki_flags, KIF_LOCKED);
-}
-
 /*
  * use_mm
  *     Makes the calling kernel thread take on the specified
@@ -796,9 +787,7 @@ static int __aio_run_iocbs(struct kioctx *ctx)
                 * Hold an extra reference while retrying i/o.
                 */
                iocb->ki_users++;       /* grab extra reference */
-               lock_kiocb(iocb);
                aio_run_iocb(iocb);
-               unlock_kiocb(iocb);
                if (__aio_put_req(ctx, iocb))  /* drop extra ref */
                        put_ioctx(ctx);
        }
@@ -1279,8 +1268,9 @@ asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp)
                goto out;
 
        ret = -EINVAL;
-       if (unlikely(ctx || (int)nr_events <= 0)) {
-               pr_debug("EINVAL: io_setup: ctx or nr_events > max\n");
+       if (unlikely(ctx || nr_events == 0)) {
+               pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
+                        ctx, nr_events);
                goto out;
        }
 
@@ -1418,6 +1408,9 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
                if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf,
                        kiocb->ki_left)))
                        break;
+               ret = security_file_permission(file, MAY_READ);
+               if (unlikely(ret))
+                       break;
                ret = -EINVAL;
                if (file->f_op->aio_read)
                        kiocb->ki_retry = aio_pread;
@@ -1430,6 +1423,9 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
                if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf,
                        kiocb->ki_left)))
                        break;
+               ret = security_file_permission(file, MAY_WRITE);
+               if (unlikely(ret))
+                       break;
                ret = -EINVAL;
                if (file->f_op->aio_write)
                        kiocb->ki_retry = aio_pwrite;
@@ -1542,7 +1538,6 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 
        spin_lock_irq(&ctx->ctx_lock);
        aio_run_iocb(req);
-       unlock_kiocb(req);
        if (!list_empty(&ctx->run_list)) {
                /* drain the run list */
                while (__aio_run_iocbs(ctx))
@@ -1674,7 +1669,6 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
        if (NULL != cancel) {
                struct io_event tmp;
                pr_debug("calling cancel\n");
-               lock_kiocb(kiocb);
                memset(&tmp, 0, sizeof(tmp));
                tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user;
                tmp.data = kiocb->ki_user_data;
@@ -1686,7 +1680,6 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
                        if (copy_to_user(result, &tmp, sizeof(tmp)))
                                ret = -EFAULT;
                }
-               unlock_kiocb(kiocb);
        } else
                ret = -EINVAL;