Merge branch 'xen/xenbus' of git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen

* 'xen/xenbus' of git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen:
  xenbus: Fix memory leak on release
  xenbus: avoid zero returns from read()
  xenbus: add missing wakeup in concurrent read/write
  xenbus: allow any xenbus command over /proc/xen/xenbus
  xenfs/xenbus: report partial reads/writes correctly
This commit is contained in:
Linus Torvalds 2011-01-20 16:37:28 -08:00
commit 67290f41b2
1 changed files with 13 additions and 18 deletions

View File

@ -122,6 +122,7 @@ static ssize_t xenbus_file_read(struct file *filp,
int ret; int ret;
mutex_lock(&u->reply_mutex); mutex_lock(&u->reply_mutex);
again:
while (list_empty(&u->read_buffers)) { while (list_empty(&u->read_buffers)) {
mutex_unlock(&u->reply_mutex); mutex_unlock(&u->reply_mutex);
if (filp->f_flags & O_NONBLOCK) if (filp->f_flags & O_NONBLOCK)
@ -144,7 +145,7 @@ static ssize_t xenbus_file_read(struct file *filp,
i += sz - ret; i += sz - ret;
rb->cons += sz - ret; rb->cons += sz - ret;
if (ret != sz) { if (ret != 0) {
if (i == 0) if (i == 0)
i = -EFAULT; i = -EFAULT;
goto out; goto out;
@ -160,6 +161,8 @@ static ssize_t xenbus_file_read(struct file *filp,
struct read_buffer, list); struct read_buffer, list);
} }
} }
if (i == 0)
goto again;
out: out:
mutex_unlock(&u->reply_mutex); 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); mutex_lock(&u->reply_mutex);
rc = queue_reply(&u->read_buffers, &reply, sizeof(reply)); rc = queue_reply(&u->read_buffers, &reply, sizeof(reply));
wake_up(&u->read_waitq);
mutex_unlock(&u->reply_mutex); 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); ret = copy_from_user(u->u.buffer + u->len, ubuf, len);
if (ret == len) { if (ret != 0) {
rc = -EFAULT; rc = -EFAULT;
goto out; goto out;
} }
@ -488,21 +492,6 @@ static ssize_t xenbus_file_write(struct file *filp,
msg_type = u->u.msg.type; msg_type = u->u.msg.type;
switch (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_WATCH:
case XS_UNWATCH: case XS_UNWATCH:
/* (Un)Ask for some path to be watched for changes */ /* (Un)Ask for some path to be watched for changes */
@ -510,7 +499,8 @@ static ssize_t xenbus_file_write(struct file *filp,
break; break;
default: default:
ret = -EINVAL; /* Send out a transaction */
ret = xenbus_write_transaction(msg_type, u);
break; break;
} }
if (ret != 0) 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_file_priv *u = filp->private_data;
struct xenbus_transaction_holder *trans, *tmp; struct xenbus_transaction_holder *trans, *tmp;
struct watch_adapter *watch, *tmp_watch; struct watch_adapter *watch, *tmp_watch;
struct read_buffer *rb, *tmp_rb;
/* /*
* No need for locking here because there are no other users, * 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); free_watch_adapter(watch);
} }
list_for_each_entry_safe(rb, tmp_rb, &u->read_buffers, list) {
list_del(&rb->list);
kfree(rb);
}
kfree(u); kfree(u);
return 0; return 0;