aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-02-22 14:02:58 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-03-14 09:15:24 -0400
commite41f7d4ee5bdb00da7d327a00b0ab9c4a2e9eaa3 (patch)
treed75350ba135d66f13a59864923f9a68c51f741e7
parentee0827cd6b42b0385dc1a116cd853ac1b739f711 (diff)
merge path_init and path_init_rcu
Actual dependency on whether we want RCU or not is in 3 small areas (as it ought to be) and everything around those is the same in both versions. Since each function has only one caller and those callers are on two sides of if (flags & LOOKUP_RCU), it's easier and cleaner to merge them and pull the checks inside. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/namei.c118
1 files changed, 35 insertions, 83 deletions
diff --git a/fs/namei.c b/fs/namei.c
index f5de5bb1a61f..b9e537980ef5 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1520,45 +1520,44 @@ return_err:
1520 return err; 1520 return err;
1521} 1521}
1522 1522
1523static int path_init_rcu(int dfd, const char *name, unsigned int flags, struct nameidata *nd) 1523static int path_init(int dfd, const char *name, unsigned int flags, struct nameidata *nd)
1524{ 1524{
1525 int retval = 0; 1525 int retval = 0;
1526 int fput_needed; 1526 int fput_needed;
1527 struct file *file; 1527 struct file *file;
1528 1528
1529 nd->last_type = LAST_ROOT; /* if there are only slashes... */ 1529 nd->last_type = LAST_ROOT; /* if there are only slashes... */
1530 nd->flags = flags | LOOKUP_RCU; 1530 nd->flags = flags;
1531 nd->depth = 0; 1531 nd->depth = 0;
1532 nd->root.mnt = NULL; 1532 nd->root.mnt = NULL;
1533 nd->file = NULL; 1533 nd->file = NULL;
1534 1534
1535 if (*name=='/') { 1535 if (*name=='/') {
1536 struct fs_struct *fs = current->fs; 1536 if (flags & LOOKUP_RCU) {
1537 unsigned seq; 1537 br_read_lock(vfsmount_lock);
1538 1538 rcu_read_lock();
1539 br_read_lock(vfsmount_lock); 1539 set_root_rcu(nd);
1540 rcu_read_lock(); 1540 } else {
1541 1541 set_root(nd);
1542 do { 1542 path_get(&nd->root);
1543 seq = read_seqcount_begin(&fs->seq); 1543 }
1544 nd->root = fs->root; 1544 nd->path = nd->root;
1545 nd->path = nd->root;
1546 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
1547 } while (read_seqcount_retry(&fs->seq, seq));
1548
1549 } else if (dfd == AT_FDCWD) { 1545 } else if (dfd == AT_FDCWD) {
1550 struct fs_struct *fs = current->fs; 1546 if (flags & LOOKUP_RCU) {
1551 unsigned seq; 1547 struct fs_struct *fs = current->fs;
1552 1548 unsigned seq;
1553 br_read_lock(vfsmount_lock);
1554 rcu_read_lock();
1555 1549
1556 do { 1550 br_read_lock(vfsmount_lock);
1557 seq = read_seqcount_begin(&fs->seq); 1551 rcu_read_lock();
1558 nd->path = fs->pwd;
1559 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
1560 } while (read_seqcount_retry(&fs->seq, seq));
1561 1552
1553 do {
1554 seq = read_seqcount_begin(&fs->seq);
1555 nd->path = fs->pwd;
1556 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
1557 } while (read_seqcount_retry(&fs->seq, seq));
1558 } else {
1559 get_fs_pwd(current->fs, &nd->path);
1560 }
1562 } else { 1561 } else {
1563 struct dentry *dentry; 1562 struct dentry *dentry;
1564 1563
@@ -1578,62 +1577,18 @@ static int path_init_rcu(int dfd, const char *name, unsigned int flags, struct n
1578 goto fput_fail; 1577 goto fput_fail;
1579 1578
1580 nd->path = file->f_path; 1579 nd->path = file->f_path;
1581 if (fput_needed) 1580 if (flags & LOOKUP_RCU) {
1582 nd->file = file; 1581 if (fput_needed)
1583 1582 nd->file = file;
1584 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); 1583 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
1585 br_read_lock(vfsmount_lock); 1584 br_read_lock(vfsmount_lock);
1586 rcu_read_lock(); 1585 rcu_read_lock();
1586 } else {
1587 path_get(&file->f_path);
1588 fput_light(file, fput_needed);
1589 }
1587 } 1590 }
1588 nd->inode = nd->path.dentry->d_inode;
1589 return 0;
1590 1591
1591fput_fail:
1592 fput_light(file, fput_needed);
1593out_fail:
1594 return retval;
1595}
1596
1597static int path_init(int dfd, const char *name, unsigned int flags, struct nameidata *nd)
1598{
1599 int retval = 0;
1600 int fput_needed;
1601 struct file *file;
1602
1603 nd->last_type = LAST_ROOT; /* if there are only slashes... */
1604 nd->flags = flags;
1605 nd->depth = 0;
1606 nd->root.mnt = NULL;
1607
1608 if (*name=='/') {
1609 set_root(nd);
1610 nd->path = nd->root;
1611 path_get(&nd->root);
1612 } else if (dfd == AT_FDCWD) {
1613 get_fs_pwd(current->fs, &nd->path);
1614 } else {
1615 struct dentry *dentry;
1616
1617 file = fget_light(dfd, &fput_needed);
1618 retval = -EBADF;
1619 if (!file)
1620 goto out_fail;
1621
1622 dentry = file->f_path.dentry;
1623
1624 retval = -ENOTDIR;
1625 if (!S_ISDIR(dentry->d_inode->i_mode))
1626 goto fput_fail;
1627
1628 retval = file_permission(file, MAY_EXEC);
1629 if (retval)
1630 goto fput_fail;
1631
1632 nd->path = file->f_path;
1633 path_get(&file->f_path);
1634
1635 fput_light(file, fput_needed);
1636 }
1637 nd->inode = nd->path.dentry->d_inode; 1592 nd->inode = nd->path.dentry->d_inode;
1638 return 0; 1593 return 0;
1639 1594
@@ -1663,10 +1618,7 @@ static int path_lookupat(int dfd, const char *name,
1663 * be handled by restarting a traditional ref-walk (which will always 1618 * be handled by restarting a traditional ref-walk (which will always
1664 * be able to complete). 1619 * be able to complete).
1665 */ 1620 */
1666 if (flags & LOOKUP_RCU) 1621 retval = path_init(dfd, name, flags, nd);
1667 retval = path_init_rcu(dfd, name, flags, nd);
1668 else
1669 retval = path_init(dfd, name, flags, nd);
1670 1622
1671 if (unlikely(retval)) 1623 if (unlikely(retval))
1672 return retval; 1624 return retval;