Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
vfs: fix race in rcu lookup of pruned dentry
Fix cifs_get_root()

[ Edited the last commit to get rid of a 'unused variable "seq"'
warning due to Al editing the patch. - Linus ]

+32 -69
+26 -68
fs/cifs/cifsfs.c
··· 35 35 #include <linux/delay.h> 36 36 #include <linux/kthread.h> 37 37 #include <linux/freezer.h> 38 + #include <linux/namei.h> 38 39 #include <net/ipv6.h> 39 40 #include "cifsfs.h" 40 41 #include "cifspdu.h" ··· 543 542 static struct dentry * 544 543 cifs_get_root(struct smb_vol *vol, struct super_block *sb) 545 544 { 546 - int xid, rc; 547 - struct inode *inode; 548 - struct qstr name; 549 - struct dentry *dparent = NULL, *dchild = NULL, *alias; 545 + struct dentry *dentry; 550 546 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 551 - unsigned int i, full_len, len; 552 - char *full_path = NULL, *pstart; 547 + char *full_path = NULL; 548 + char *s, *p; 553 549 char sep; 550 + int xid; 554 551 555 552 full_path = cifs_build_path_to_root(vol, cifs_sb, 556 553 cifs_sb_master_tcon(cifs_sb)); ··· 559 560 560 561 xid = GetXid(); 561 562 sep = CIFS_DIR_SEP(cifs_sb); 562 - dparent = dget(sb->s_root); 563 - full_len = strlen(full_path); 564 - full_path[full_len] = sep; 565 - pstart = full_path + 1; 563 + dentry = dget(sb->s_root); 564 + p = s = full_path; 566 565 567 - for (i = 1, len = 0; i <= full_len; i++) { 568 - if (full_path[i] != sep || !len) { 569 - len++; 570 - continue; 571 - } 566 + do { 567 + struct inode *dir = dentry->d_inode; 568 + struct dentry *child; 572 569 573 - full_path[i] = 0; 574 - cFYI(1, "get dentry for %s", pstart); 570 + /* skip separators */ 571 + while (*s == sep) 572 + s++; 573 + if (!*s) 574 + break; 575 + p = s++; 576 + /* next separator */ 577 + while (*s && *s != sep) 578 + s++; 575 579 576 - name.name = pstart; 577 - name.len = len; 578 - name.hash = full_name_hash(pstart, len); 579 - dchild = d_lookup(dparent, &name); 580 - if (dchild == NULL) { 581 - cFYI(1, "not exists"); 582 - dchild = d_alloc(dparent, &name); 583 - if (dchild == NULL) { 584 - dput(dparent); 585 - dparent = ERR_PTR(-ENOMEM); 586 - goto out; 587 - } 588 - } 589 - 590 - cFYI(1, "get inode"); 591 - if (dchild->d_inode == NULL) { 592 - cFYI(1, "not exists"); 593 - inode = NULL; 594 - if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) 595 - rc = cifs_get_inode_info_unix(&inode, full_path, 596 - sb, xid); 597 - else 598 - rc = cifs_get_inode_info(&inode, full_path, 599 - NULL, sb, xid, NULL); 600 - if (rc) { 601 - dput(dchild); 602 - dput(dparent); 603 - dparent = ERR_PTR(rc); 604 - goto out; 605 - } 606 - alias = d_materialise_unique(dchild, inode); 607 - if (alias != NULL) { 608 - dput(dchild); 609 - if (IS_ERR(alias)) { 610 - dput(dparent); 611 - dparent = ERR_PTR(-EINVAL); /* XXX */ 612 - goto out; 613 - } 614 - dchild = alias; 615 - } 616 - } 617 - cFYI(1, "parent %p, child %p", dparent, dchild); 618 - 619 - dput(dparent); 620 - dparent = dchild; 621 - len = 0; 622 - pstart = full_path + i + 1; 623 - full_path[i] = sep; 624 - } 625 - out: 580 + mutex_lock(&dir->i_mutex); 581 + child = lookup_one_len(p, dentry, s - p); 582 + mutex_unlock(&dir->i_mutex); 583 + dput(dentry); 584 + dentry = child; 585 + } while (!IS_ERR(dentry)); 626 586 _FreeXid(xid); 627 587 kfree(full_path); 628 - return dparent; 588 + return dentry; 629 589 } 630 590 631 591 static int cifs_set_super(struct super_block *sb, void *data)
+6 -1
fs/namei.c
··· 942 942 * Don't forget we might have a non-mountpoint managed dentry 943 943 * that wants to block transit. 944 944 */ 945 - *inode = path->dentry->d_inode; 946 945 if (unlikely(managed_dentry_might_block(path->dentry))) 947 946 return false; 948 947 ··· 954 955 path->mnt = mounted; 955 956 path->dentry = mounted->mnt_root; 956 957 nd->seq = read_seqcount_begin(&path->dentry->d_seq); 958 + /* 959 + * Update the inode too. We don't need to re-check the 960 + * dentry sequence number here after this d_inode read, 961 + * because a mount-point is always pinned. 962 + */ 963 + *inode = path->dentry->d_inode; 957 964 } 958 965 return true; 959 966 }