diff options
-rw-r--r-- | drivers/xen/xenfs/xenbus.c | 31 |
1 files changed, 13 insertions, 18 deletions
diff --git a/drivers/xen/xenfs/xenbus.c b/drivers/xen/xenfs/xenbus.c index 1c1236087f7..bbd000f88af 100644 --- a/drivers/xen/xenfs/xenbus.c +++ b/drivers/xen/xenfs/xenbus.c @@ -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; |