diff options
author | Len Brown <len.brown@intel.com> | 2006-01-27 17:18:29 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2006-01-27 17:18:29 -0500 |
commit | 292dd876ee765c478b27c93cc51e93a558ed58bf (patch) | |
tree | 5b740e93253295baee2a9c414a6c66d03d44a9ef /ipc/mqueue.c | |
parent | d4ec6c7cc9a15a7a529719bc3b84f46812f9842e (diff) | |
parent | 9fdb62af92c741addbea15545f214a6e89460865 (diff) |
Pull release into acpica branch
Diffstat (limited to 'ipc/mqueue.c')
-rw-r--r-- | ipc/mqueue.c | 68 |
1 files changed, 38 insertions, 30 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index c8943b53d8e6..59302fc3643b 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * This file is released under the GPL. | 11 | * This file is released under the GPL. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/capability.h> | ||
14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
15 | #include <linux/pagemap.h> | 16 | #include <linux/pagemap.h> |
16 | #include <linux/file.h> | 17 | #include <linux/file.h> |
@@ -598,15 +599,16 @@ static int mq_attr_ok(struct mq_attr *attr) | |||
598 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, | 599 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, |
599 | int oflag, mode_t mode, struct mq_attr __user *u_attr) | 600 | int oflag, mode_t mode, struct mq_attr __user *u_attr) |
600 | { | 601 | { |
601 | struct file *filp; | ||
602 | struct mq_attr attr; | 602 | struct mq_attr attr; |
603 | int ret; | 603 | int ret; |
604 | 604 | ||
605 | if (u_attr != NULL) { | 605 | if (u_attr) { |
606 | ret = -EFAULT; | ||
606 | if (copy_from_user(&attr, u_attr, sizeof(attr))) | 607 | if (copy_from_user(&attr, u_attr, sizeof(attr))) |
607 | return ERR_PTR(-EFAULT); | 608 | goto out; |
609 | ret = -EINVAL; | ||
608 | if (!mq_attr_ok(&attr)) | 610 | if (!mq_attr_ok(&attr)) |
609 | return ERR_PTR(-EINVAL); | 611 | goto out; |
610 | /* store for use during create */ | 612 | /* store for use during create */ |
611 | dentry->d_fsdata = &attr; | 613 | dentry->d_fsdata = &attr; |
612 | } | 614 | } |
@@ -615,13 +617,14 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry, | |||
615 | ret = vfs_create(dir->d_inode, dentry, mode, NULL); | 617 | ret = vfs_create(dir->d_inode, dentry, mode, NULL); |
616 | dentry->d_fsdata = NULL; | 618 | dentry->d_fsdata = NULL; |
617 | if (ret) | 619 | if (ret) |
618 | return ERR_PTR(ret); | 620 | goto out; |
619 | 621 | ||
620 | filp = dentry_open(dentry, mqueue_mnt, oflag); | 622 | return dentry_open(dentry, mqueue_mnt, oflag); |
621 | if (!IS_ERR(filp)) | ||
622 | dget(dentry); | ||
623 | 623 | ||
624 | return filp; | 624 | out: |
625 | dput(dentry); | ||
626 | mntput(mqueue_mnt); | ||
627 | return ERR_PTR(ret); | ||
625 | } | 628 | } |
626 | 629 | ||
627 | /* Opens existing queue */ | 630 | /* Opens existing queue */ |
@@ -629,20 +632,20 @@ static struct file *do_open(struct dentry *dentry, int oflag) | |||
629 | { | 632 | { |
630 | static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, | 633 | static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, |
631 | MAY_READ | MAY_WRITE }; | 634 | MAY_READ | MAY_WRITE }; |
632 | struct file *filp; | ||
633 | 635 | ||
634 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) | 636 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { |
637 | dput(dentry); | ||
638 | mntput(mqueue_mnt); | ||
635 | return ERR_PTR(-EINVAL); | 639 | return ERR_PTR(-EINVAL); |
640 | } | ||
636 | 641 | ||
637 | if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) | 642 | if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) { |
643 | dput(dentry); | ||
644 | mntput(mqueue_mnt); | ||
638 | return ERR_PTR(-EACCES); | 645 | return ERR_PTR(-EACCES); |
646 | } | ||
639 | 647 | ||
640 | filp = dentry_open(dentry, mqueue_mnt, oflag); | 648 | return dentry_open(dentry, mqueue_mnt, oflag); |
641 | |||
642 | if (!IS_ERR(filp)) | ||
643 | dget(dentry); | ||
644 | |||
645 | return filp; | ||
646 | } | 649 | } |
647 | 650 | ||
648 | asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | 651 | asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, |
@@ -660,7 +663,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | |||
660 | if (fd < 0) | 663 | if (fd < 0) |
661 | goto out_putname; | 664 | goto out_putname; |
662 | 665 | ||
663 | down(&mqueue_mnt->mnt_root->d_inode->i_sem); | 666 | mutex_lock(&mqueue_mnt->mnt_root->d_inode->i_mutex); |
664 | dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name)); | 667 | dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name)); |
665 | if (IS_ERR(dentry)) { | 668 | if (IS_ERR(dentry)) { |
666 | error = PTR_ERR(dentry); | 669 | error = PTR_ERR(dentry); |
@@ -670,17 +673,20 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | |||
670 | 673 | ||
671 | if (oflag & O_CREAT) { | 674 | if (oflag & O_CREAT) { |
672 | if (dentry->d_inode) { /* entry already exists */ | 675 | if (dentry->d_inode) { /* entry already exists */ |
673 | filp = (oflag & O_EXCL) ? ERR_PTR(-EEXIST) : | 676 | error = -EEXIST; |
674 | do_open(dentry, oflag); | 677 | if (oflag & O_EXCL) |
678 | goto out; | ||
679 | filp = do_open(dentry, oflag); | ||
675 | } else { | 680 | } else { |
676 | filp = do_create(mqueue_mnt->mnt_root, dentry, | 681 | filp = do_create(mqueue_mnt->mnt_root, dentry, |
677 | oflag, mode, u_attr); | 682 | oflag, mode, u_attr); |
678 | } | 683 | } |
679 | } else | 684 | } else { |
680 | filp = (dentry->d_inode) ? do_open(dentry, oflag) : | 685 | error = -ENOENT; |
681 | ERR_PTR(-ENOENT); | 686 | if (!dentry->d_inode) |
682 | 687 | goto out; | |
683 | dput(dentry); | 688 | filp = do_open(dentry, oflag); |
689 | } | ||
684 | 690 | ||
685 | if (IS_ERR(filp)) { | 691 | if (IS_ERR(filp)) { |
686 | error = PTR_ERR(filp); | 692 | error = PTR_ERR(filp); |
@@ -691,13 +697,15 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | |||
691 | fd_install(fd, filp); | 697 | fd_install(fd, filp); |
692 | goto out_upsem; | 698 | goto out_upsem; |
693 | 699 | ||
694 | out_putfd: | 700 | out: |
701 | dput(dentry); | ||
695 | mntput(mqueue_mnt); | 702 | mntput(mqueue_mnt); |
703 | out_putfd: | ||
696 | put_unused_fd(fd); | 704 | put_unused_fd(fd); |
697 | out_err: | 705 | out_err: |
698 | fd = error; | 706 | fd = error; |
699 | out_upsem: | 707 | out_upsem: |
700 | up(&mqueue_mnt->mnt_root->d_inode->i_sem); | 708 | mutex_unlock(&mqueue_mnt->mnt_root->d_inode->i_mutex); |
701 | out_putname: | 709 | out_putname: |
702 | putname(name); | 710 | putname(name); |
703 | return fd; | 711 | return fd; |
@@ -714,7 +722,7 @@ asmlinkage long sys_mq_unlink(const char __user *u_name) | |||
714 | if (IS_ERR(name)) | 722 | if (IS_ERR(name)) |
715 | return PTR_ERR(name); | 723 | return PTR_ERR(name); |
716 | 724 | ||
717 | down(&mqueue_mnt->mnt_root->d_inode->i_sem); | 725 | mutex_lock(&mqueue_mnt->mnt_root->d_inode->i_mutex); |
718 | dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name)); | 726 | dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name)); |
719 | if (IS_ERR(dentry)) { | 727 | if (IS_ERR(dentry)) { |
720 | err = PTR_ERR(dentry); | 728 | err = PTR_ERR(dentry); |
@@ -735,7 +743,7 @@ out_err: | |||
735 | dput(dentry); | 743 | dput(dentry); |
736 | 744 | ||
737 | out_unlock: | 745 | out_unlock: |
738 | up(&mqueue_mnt->mnt_root->d_inode->i_sem); | 746 | mutex_unlock(&mqueue_mnt->mnt_root->d_inode->i_mutex); |
739 | putname(name); | 747 | putname(name); |
740 | if (inode) | 748 | if (inode) |
741 | iput(inode); | 749 | iput(inode); |