aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-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;