aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2009-12-24 01:26:48 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2010-03-05 09:01:11 -0500
commit648fa8611de3d4d43bbd64af3226679d2d0eb609 (patch)
tree96d134de1d935d6d54daac678dc07346bbbda940 /fs
parent64ba9926759792cf7b95f823402e2781edd1b5d4 (diff)
beginning to untangle do_filp_open()
That's going to be a long and painful series. The first step: take the stuff reachable from 'ok' label in do_filp_open() into a new helper (finish_open()). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/namei.c106
1 files changed, 56 insertions, 50 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 0741c69b3319..60b74b3946a1 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1590,6 +1590,61 @@ static int open_will_truncate(int flag, struct inode *inode)
1590 return (flag & O_TRUNC); 1590 return (flag & O_TRUNC);
1591} 1591}
1592 1592
1593static struct file *finish_open(struct nameidata *nd,
1594 int open_flag, int flag, int acc_mode)
1595{
1596 struct file *filp;
1597 int will_truncate;
1598 int error;
1599
1600 will_truncate = open_will_truncate(flag, nd->path.dentry->d_inode);
1601 if (will_truncate) {
1602 error = mnt_want_write(nd->path.mnt);
1603 if (error)
1604 goto exit;
1605 }
1606 error = may_open(&nd->path, acc_mode, open_flag);
1607 if (error) {
1608 if (will_truncate)
1609 mnt_drop_write(nd->path.mnt);
1610 goto exit;
1611 }
1612 filp = nameidata_to_filp(nd);
1613 if (!IS_ERR(filp)) {
1614 error = ima_file_check(filp, acc_mode);
1615 if (error) {
1616 fput(filp);
1617 filp = ERR_PTR(error);
1618 }
1619 }
1620 if (!IS_ERR(filp)) {
1621 if (acc_mode & MAY_WRITE)
1622 vfs_dq_init(nd->path.dentry->d_inode);
1623
1624 if (will_truncate) {
1625 error = handle_truncate(&nd->path);
1626 if (error) {
1627 fput(filp);
1628 filp = ERR_PTR(error);
1629 }
1630 }
1631 }
1632 /*
1633 * It is now safe to drop the mnt write
1634 * because the filp has had a write taken
1635 * on its behalf.
1636 */
1637 if (will_truncate)
1638 mnt_drop_write(nd->path.mnt);
1639 return filp;
1640
1641exit:
1642 if (!IS_ERR(nd->intent.open.file))
1643 release_open_intent(nd);
1644 path_put(&nd->path);
1645 return ERR_PTR(error);
1646}
1647
1593/* 1648/*
1594 * Note that the low bits of the passed in "open_flag" 1649 * Note that the low bits of the passed in "open_flag"
1595 * are not the same as in the local variable "flag". See 1650 * are not the same as in the local variable "flag". See
@@ -1604,7 +1659,6 @@ struct file *do_filp_open(int dfd, const char *pathname,
1604 struct path path; 1659 struct path path;
1605 struct dentry *dir; 1660 struct dentry *dir;
1606 int count = 0; 1661 int count = 0;
1607 int will_truncate;
1608 int flag = open_to_namei_flags(open_flag); 1662 int flag = open_to_namei_flags(open_flag);
1609 int force_reval = 0; 1663 int force_reval = 0;
1610 1664
@@ -1769,55 +1823,7 @@ do_last:
1769 if (S_ISDIR(path.dentry->d_inode->i_mode)) 1823 if (S_ISDIR(path.dentry->d_inode->i_mode))
1770 goto exit; 1824 goto exit;
1771ok: 1825ok:
1772 /* 1826 filp = finish_open(&nd, open_flag, flag, acc_mode);
1773 * Consider:
1774 * 1. may_open() truncates a file
1775 * 2. a rw->ro mount transition occurs
1776 * 3. nameidata_to_filp() fails due to
1777 * the ro mount.
1778 * That would be inconsistent, and should
1779 * be avoided. Taking this mnt write here
1780 * ensures that (2) can not occur.
1781 */
1782 will_truncate = open_will_truncate(flag, nd.path.dentry->d_inode);
1783 if (will_truncate) {
1784 error = mnt_want_write(nd.path.mnt);
1785 if (error)
1786 goto exit;
1787 }
1788 error = may_open(&nd.path, acc_mode, open_flag);
1789 if (error) {
1790 if (will_truncate)
1791 mnt_drop_write(nd.path.mnt);
1792 goto exit;
1793 }
1794 filp = nameidata_to_filp(&nd);
1795 if (!IS_ERR(filp)) {
1796 error = ima_file_check(filp, acc_mode);
1797 if (error) {
1798 fput(filp);
1799 filp = ERR_PTR(error);
1800 }
1801 }
1802 if (!IS_ERR(filp)) {
1803 if (acc_mode & MAY_WRITE)
1804 vfs_dq_init(nd.path.dentry->d_inode);
1805
1806 if (will_truncate) {
1807 error = handle_truncate(&nd.path);
1808 if (error) {
1809 fput(filp);
1810 filp = ERR_PTR(error);
1811 }
1812 }
1813 }
1814 /*
1815 * It is now safe to drop the mnt write
1816 * because the filp has had a write taken
1817 * on its behalf.
1818 */
1819 if (will_truncate)
1820 mnt_drop_write(nd.path.mnt);
1821 if (nd.root.mnt) 1827 if (nd.root.mnt)
1822 path_put(&nd.root); 1828 path_put(&nd.root);
1823 return filp; 1829 return filp;