diff options
Diffstat (limited to 'net/sunrpc/rpc_pipe.c')
| -rw-r--r-- | net/sunrpc/rpc_pipe.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 49278f830367..8c8eef2b8f26 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
| 28 | #include <linux/sunrpc/rpc_pipe_fs.h> | 28 | #include <linux/sunrpc/rpc_pipe_fs.h> |
| 29 | #include <linux/sunrpc/cache.h> | 29 | #include <linux/sunrpc/cache.h> |
| 30 | #include <linux/smp_lock.h> | ||
| 30 | 31 | ||
| 31 | static struct vfsmount *rpc_mount __read_mostly; | 32 | static struct vfsmount *rpc_mount __read_mostly; |
| 32 | static int rpc_mount_count; | 33 | static int rpc_mount_count; |
| @@ -47,7 +48,7 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, | |||
| 47 | return; | 48 | return; |
| 48 | do { | 49 | do { |
| 49 | msg = list_entry(head->next, struct rpc_pipe_msg, list); | 50 | msg = list_entry(head->next, struct rpc_pipe_msg, list); |
| 50 | list_del(&msg->list); | 51 | list_del_init(&msg->list); |
| 51 | msg->errno = err; | 52 | msg->errno = err; |
| 52 | destroy_msg(msg); | 53 | destroy_msg(msg); |
| 53 | } while (!list_empty(head)); | 54 | } while (!list_empty(head)); |
| @@ -78,7 +79,7 @@ rpc_timeout_upcall_queue(struct work_struct *work) | |||
| 78 | } | 79 | } |
| 79 | 80 | ||
| 80 | /** | 81 | /** |
| 81 | * rpc_queue_upcall | 82 | * rpc_queue_upcall - queue an upcall message to userspace |
| 82 | * @inode: inode of upcall pipe on which to queue given message | 83 | * @inode: inode of upcall pipe on which to queue given message |
| 83 | * @msg: message to queue | 84 | * @msg: message to queue |
| 84 | * | 85 | * |
| @@ -207,7 +208,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) | |||
| 207 | if (msg != NULL) { | 208 | if (msg != NULL) { |
| 208 | spin_lock(&inode->i_lock); | 209 | spin_lock(&inode->i_lock); |
| 209 | msg->errno = -EAGAIN; | 210 | msg->errno = -EAGAIN; |
| 210 | list_del(&msg->list); | 211 | list_del_init(&msg->list); |
| 211 | spin_unlock(&inode->i_lock); | 212 | spin_unlock(&inode->i_lock); |
| 212 | rpci->ops->destroy_msg(msg); | 213 | rpci->ops->destroy_msg(msg); |
| 213 | } | 214 | } |
| @@ -267,7 +268,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | |||
| 267 | if (res < 0 || msg->len == msg->copied) { | 268 | if (res < 0 || msg->len == msg->copied) { |
| 268 | filp->private_data = NULL; | 269 | filp->private_data = NULL; |
| 269 | spin_lock(&inode->i_lock); | 270 | spin_lock(&inode->i_lock); |
| 270 | list_del(&msg->list); | 271 | list_del_init(&msg->list); |
| 271 | spin_unlock(&inode->i_lock); | 272 | spin_unlock(&inode->i_lock); |
| 272 | rpci->ops->destroy_msg(msg); | 273 | rpci->ops->destroy_msg(msg); |
| 273 | } | 274 | } |
| @@ -309,8 +310,7 @@ rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) | |||
| 309 | } | 310 | } |
| 310 | 311 | ||
| 311 | static int | 312 | static int |
| 312 | rpc_pipe_ioctl(struct inode *ino, struct file *filp, | 313 | rpc_pipe_ioctl_unlocked(struct file *filp, unsigned int cmd, unsigned long arg) |
| 313 | unsigned int cmd, unsigned long arg) | ||
| 314 | { | 314 | { |
| 315 | struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode); | 315 | struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode); |
| 316 | int len; | 316 | int len; |
| @@ -331,13 +331,25 @@ rpc_pipe_ioctl(struct inode *ino, struct file *filp, | |||
| 331 | } | 331 | } |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | static long | ||
| 335 | rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | ||
| 336 | { | ||
| 337 | long ret; | ||
| 338 | |||
| 339 | lock_kernel(); | ||
| 340 | ret = rpc_pipe_ioctl_unlocked(filp, cmd, arg); | ||
| 341 | unlock_kernel(); | ||
| 342 | |||
| 343 | return ret; | ||
| 344 | } | ||
| 345 | |||
| 334 | static const struct file_operations rpc_pipe_fops = { | 346 | static const struct file_operations rpc_pipe_fops = { |
| 335 | .owner = THIS_MODULE, | 347 | .owner = THIS_MODULE, |
| 336 | .llseek = no_llseek, | 348 | .llseek = no_llseek, |
| 337 | .read = rpc_pipe_read, | 349 | .read = rpc_pipe_read, |
| 338 | .write = rpc_pipe_write, | 350 | .write = rpc_pipe_write, |
| 339 | .poll = rpc_pipe_poll, | 351 | .poll = rpc_pipe_poll, |
| 340 | .ioctl = rpc_pipe_ioctl, | 352 | .unlocked_ioctl = rpc_pipe_ioctl, |
| 341 | .open = rpc_pipe_open, | 353 | .open = rpc_pipe_open, |
| 342 | .release = rpc_pipe_release, | 354 | .release = rpc_pipe_release, |
| 343 | }; | 355 | }; |
| @@ -359,21 +371,23 @@ rpc_show_info(struct seq_file *m, void *v) | |||
| 359 | static int | 371 | static int |
| 360 | rpc_info_open(struct inode *inode, struct file *file) | 372 | rpc_info_open(struct inode *inode, struct file *file) |
| 361 | { | 373 | { |
| 362 | struct rpc_clnt *clnt; | 374 | struct rpc_clnt *clnt = NULL; |
| 363 | int ret = single_open(file, rpc_show_info, NULL); | 375 | int ret = single_open(file, rpc_show_info, NULL); |
| 364 | 376 | ||
| 365 | if (!ret) { | 377 | if (!ret) { |
| 366 | struct seq_file *m = file->private_data; | 378 | struct seq_file *m = file->private_data; |
| 367 | mutex_lock(&inode->i_mutex); | 379 | |
| 368 | clnt = RPC_I(inode)->private; | 380 | spin_lock(&file->f_path.dentry->d_lock); |
| 369 | if (clnt) { | 381 | if (!d_unhashed(file->f_path.dentry)) |
| 370 | kref_get(&clnt->cl_kref); | 382 | clnt = RPC_I(inode)->private; |
| 383 | if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) { | ||
| 384 | spin_unlock(&file->f_path.dentry->d_lock); | ||
| 371 | m->private = clnt; | 385 | m->private = clnt; |
| 372 | } else { | 386 | } else { |
| 387 | spin_unlock(&file->f_path.dentry->d_lock); | ||
| 373 | single_release(inode, file); | 388 | single_release(inode, file); |
| 374 | ret = -EINVAL; | 389 | ret = -EINVAL; |
| 375 | } | 390 | } |
| 376 | mutex_unlock(&inode->i_mutex); | ||
| 377 | } | 391 | } |
| 378 | return ret; | 392 | return ret; |
| 379 | } | 393 | } |
| @@ -587,6 +601,8 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, | |||
| 587 | struct dentry *dentry; | 601 | struct dentry *dentry; |
| 588 | 602 | ||
| 589 | dentry = __rpc_lookup_create(parent, name); | 603 | dentry = __rpc_lookup_create(parent, name); |
| 604 | if (IS_ERR(dentry)) | ||
| 605 | return dentry; | ||
| 590 | if (dentry->d_inode == NULL) | 606 | if (dentry->d_inode == NULL) |
| 591 | return dentry; | 607 | return dentry; |
| 592 | dput(dentry); | 608 | dput(dentry); |
| @@ -999,19 +1015,14 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) | |||
| 999 | inode = rpc_get_inode(sb, S_IFDIR | 0755); | 1015 | inode = rpc_get_inode(sb, S_IFDIR | 0755); |
| 1000 | if (!inode) | 1016 | if (!inode) |
| 1001 | return -ENOMEM; | 1017 | return -ENOMEM; |
| 1002 | root = d_alloc_root(inode); | 1018 | sb->s_root = root = d_alloc_root(inode); |
| 1003 | if (!root) { | 1019 | if (!root) { |
| 1004 | iput(inode); | 1020 | iput(inode); |
| 1005 | return -ENOMEM; | 1021 | return -ENOMEM; |
| 1006 | } | 1022 | } |
| 1007 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) | 1023 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) |
| 1008 | goto out; | 1024 | return -ENOMEM; |
| 1009 | sb->s_root = root; | ||
| 1010 | return 0; | 1025 | return 0; |
| 1011 | out: | ||
| 1012 | d_genocide(root); | ||
| 1013 | dput(root); | ||
| 1014 | return -ENOMEM; | ||
| 1015 | } | 1026 | } |
| 1016 | 1027 | ||
| 1017 | static int | 1028 | static int |
