Merge branch 'xen/xenbus' of git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen
[pandora-kernel.git] / drivers / xen / xenfs / xenbus.c
index 1c12360..bbd000f 100644 (file)
@@ -122,6 +122,7 @@ static ssize_t xenbus_file_read(struct file *filp,
        int ret;
 
        mutex_lock(&u->reply_mutex);
+again:
        while (list_empty(&u->read_buffers)) {
                mutex_unlock(&u->reply_mutex);
                if (filp->f_flags & O_NONBLOCK)
@@ -144,7 +145,7 @@ static ssize_t xenbus_file_read(struct file *filp,
                i += sz - ret;
                rb->cons += sz - ret;
 
-               if (ret != sz) {
+               if (ret != 0) {
                        if (i == 0)
                                i = -EFAULT;
                        goto out;
@@ -160,6 +161,8 @@ static ssize_t xenbus_file_read(struct file *filp,
                                        struct read_buffer, list);
                }
        }
+       if (i == 0)
+               goto again;
 
 out:
        mutex_unlock(&u->reply_mutex);
@@ -407,6 +410,7 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u)
 
                mutex_lock(&u->reply_mutex);
                rc = queue_reply(&u->read_buffers, &reply, sizeof(reply));
+               wake_up(&u->read_waitq);
                mutex_unlock(&u->reply_mutex);
        }
 
@@ -455,7 +459,7 @@ static ssize_t xenbus_file_write(struct file *filp,
 
        ret = copy_from_user(u->u.buffer + u->len, ubuf, len);
 
-       if (ret == len) {
+       if (ret != 0) {
                rc = -EFAULT;
                goto out;
        }
@@ -488,21 +492,6 @@ static ssize_t xenbus_file_write(struct file *filp,
        msg_type = u->u.msg.type;
 
        switch (msg_type) {
-       case XS_TRANSACTION_START:
-       case XS_TRANSACTION_END:
-       case XS_DIRECTORY:
-       case XS_READ:
-       case XS_GET_PERMS:
-       case XS_RELEASE:
-       case XS_GET_DOMAIN_PATH:
-       case XS_WRITE:
-       case XS_MKDIR:
-       case XS_RM:
-       case XS_SET_PERMS:
-               /* Send out a transaction */
-               ret = xenbus_write_transaction(msg_type, u);
-               break;
-
        case XS_WATCH:
        case XS_UNWATCH:
                /* (Un)Ask for some path to be watched for changes */
@@ -510,7 +499,8 @@ static ssize_t xenbus_file_write(struct file *filp,
                break;
 
        default:
-               ret = -EINVAL;
+               /* Send out a transaction */
+               ret = xenbus_write_transaction(msg_type, u);
                break;
        }
        if (ret != 0)
@@ -555,6 +545,7 @@ static int xenbus_file_release(struct inode *inode, struct file *filp)
        struct xenbus_file_priv *u = filp->private_data;
        struct xenbus_transaction_holder *trans, *tmp;
        struct watch_adapter *watch, *tmp_watch;
+       struct read_buffer *rb, *tmp_rb;
 
        /*
         * No need for locking here because there are no other users,
@@ -573,6 +564,10 @@ static int xenbus_file_release(struct inode *inode, struct file *filp)
                free_watch_adapter(watch);
        }
 
+       list_for_each_entry_safe(rb, tmp_rb, &u->read_buffers, list) {
+               list_del(&rb->list);
+               kfree(rb);
+       }
        kfree(u);
 
        return 0;