diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /fs/nfs/dir.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 78 |
1 files changed, 36 insertions, 42 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 7cb298525eef..a7bb5c694aa3 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -560,7 +560,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
560 | desc->entry = &my_entry; | 560 | desc->entry = &my_entry; |
561 | 561 | ||
562 | nfs_block_sillyrename(dentry); | 562 | nfs_block_sillyrename(dentry); |
563 | res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping); | 563 | res = nfs_revalidate_mapping(inode, filp->f_mapping); |
564 | if (res < 0) | 564 | if (res < 0) |
565 | goto out; | 565 | goto out; |
566 | 566 | ||
@@ -837,6 +837,8 @@ out_zap_parent: | |||
837 | /* If we have submounts, don't unhash ! */ | 837 | /* If we have submounts, don't unhash ! */ |
838 | if (have_submounts(dentry)) | 838 | if (have_submounts(dentry)) |
839 | goto out_valid; | 839 | goto out_valid; |
840 | if (dentry->d_flags & DCACHE_DISCONNECTED) | ||
841 | goto out_valid; | ||
840 | shrink_dcache_parent(dentry); | 842 | shrink_dcache_parent(dentry); |
841 | } | 843 | } |
842 | d_drop(dentry); | 844 | d_drop(dentry); |
@@ -1025,12 +1027,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
1025 | res = NULL; | 1027 | res = NULL; |
1026 | goto out; | 1028 | goto out; |
1027 | /* This turned out not to be a regular file */ | 1029 | /* This turned out not to be a regular file */ |
1030 | case -EISDIR: | ||
1028 | case -ENOTDIR: | 1031 | case -ENOTDIR: |
1029 | goto no_open; | 1032 | goto no_open; |
1030 | case -ELOOP: | 1033 | case -ELOOP: |
1031 | if (!(nd->intent.open.flags & O_NOFOLLOW)) | 1034 | if (!(nd->intent.open.flags & O_NOFOLLOW)) |
1032 | goto no_open; | 1035 | goto no_open; |
1033 | /* case -EISDIR: */ | ||
1034 | /* case -EINVAL: */ | 1036 | /* case -EINVAL: */ |
1035 | default: | 1037 | default: |
1036 | goto out; | 1038 | goto out; |
@@ -1050,7 +1052,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1050 | struct inode *dir; | 1052 | struct inode *dir; |
1051 | int openflags, ret = 0; | 1053 | int openflags, ret = 0; |
1052 | 1054 | ||
1053 | if (!is_atomic_open(nd)) | 1055 | if (!is_atomic_open(nd) || d_mountpoint(dentry)) |
1054 | goto no_open; | 1056 | goto no_open; |
1055 | parent = dget_parent(dentry); | 1057 | parent = dget_parent(dentry); |
1056 | dir = parent->d_inode; | 1058 | dir = parent->d_inode; |
@@ -1579,55 +1581,47 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1579 | struct dentry *dentry = NULL, *rehash = NULL; | 1581 | struct dentry *dentry = NULL, *rehash = NULL; |
1580 | int error = -EBUSY; | 1582 | int error = -EBUSY; |
1581 | 1583 | ||
1582 | /* | ||
1583 | * To prevent any new references to the target during the rename, | ||
1584 | * we unhash the dentry and free the inode in advance. | ||
1585 | */ | ||
1586 | if (!d_unhashed(new_dentry)) { | ||
1587 | d_drop(new_dentry); | ||
1588 | rehash = new_dentry; | ||
1589 | } | ||
1590 | |||
1591 | dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", | 1584 | dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", |
1592 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1585 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
1593 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, | 1586 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, |
1594 | atomic_read(&new_dentry->d_count)); | 1587 | atomic_read(&new_dentry->d_count)); |
1595 | 1588 | ||
1596 | /* | 1589 | /* |
1597 | * First check whether the target is busy ... we can't | 1590 | * For non-directories, check whether the target is busy and if so, |
1598 | * safely do _any_ rename if the target is in use. | 1591 | * make a copy of the dentry and then do a silly-rename. If the |
1599 | * | 1592 | * silly-rename succeeds, the copied dentry is hashed and becomes |
1600 | * For files, make a copy of the dentry and then do a | 1593 | * the new target. |
1601 | * silly-rename. If the silly-rename succeeds, the | ||
1602 | * copied dentry is hashed and becomes the new target. | ||
1603 | */ | 1594 | */ |
1604 | if (!new_inode) | 1595 | if (new_inode && !S_ISDIR(new_inode->i_mode)) { |
1605 | goto go_ahead; | 1596 | /* |
1606 | if (S_ISDIR(new_inode->i_mode)) { | 1597 | * To prevent any new references to the target during the |
1607 | error = -EISDIR; | 1598 | * rename, we unhash the dentry in advance. |
1608 | if (!S_ISDIR(old_inode->i_mode)) | 1599 | */ |
1609 | goto out; | 1600 | if (!d_unhashed(new_dentry)) { |
1610 | } else if (atomic_read(&new_dentry->d_count) > 2) { | 1601 | d_drop(new_dentry); |
1611 | int err; | 1602 | rehash = new_dentry; |
1612 | /* copy the target dentry's name */ | 1603 | } |
1613 | dentry = d_alloc(new_dentry->d_parent, | 1604 | |
1614 | &new_dentry->d_name); | 1605 | if (atomic_read(&new_dentry->d_count) > 2) { |
1615 | if (!dentry) | 1606 | int err; |
1616 | goto out; | 1607 | |
1608 | /* copy the target dentry's name */ | ||
1609 | dentry = d_alloc(new_dentry->d_parent, | ||
1610 | &new_dentry->d_name); | ||
1611 | if (!dentry) | ||
1612 | goto out; | ||
1617 | 1613 | ||
1618 | /* silly-rename the existing target ... */ | 1614 | /* silly-rename the existing target ... */ |
1619 | err = nfs_sillyrename(new_dir, new_dentry); | 1615 | err = nfs_sillyrename(new_dir, new_dentry); |
1620 | if (!err) { | 1616 | if (err) |
1621 | new_dentry = rehash = dentry; | 1617 | goto out; |
1618 | |||
1619 | new_dentry = dentry; | ||
1620 | rehash = NULL; | ||
1622 | new_inode = NULL; | 1621 | new_inode = NULL; |
1623 | /* instantiate the replacement target */ | 1622 | } |
1624 | d_instantiate(new_dentry, NULL); | ||
1625 | } else if (atomic_read(&new_dentry->d_count) > 1) | ||
1626 | /* dentry still busy? */ | ||
1627 | goto out; | ||
1628 | } | 1623 | } |
1629 | 1624 | ||
1630 | go_ahead: | ||
1631 | /* | 1625 | /* |
1632 | * ... prune child dentries and writebacks if needed. | 1626 | * ... prune child dentries and writebacks if needed. |
1633 | */ | 1627 | */ |
@@ -1797,7 +1791,7 @@ static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, str | |||
1797 | cache = nfs_access_search_rbtree(inode, cred); | 1791 | cache = nfs_access_search_rbtree(inode, cred); |
1798 | if (cache == NULL) | 1792 | if (cache == NULL) |
1799 | goto out; | 1793 | goto out; |
1800 | if (!nfs_have_delegation(inode, FMODE_READ) && | 1794 | if (!nfs_have_delegated_attributes(inode) && |
1801 | !time_in_range_open(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo)) | 1795 | !time_in_range_open(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo)) |
1802 | goto out_stale; | 1796 | goto out_stale; |
1803 | res->jiffies = cache->jiffies; | 1797 | res->jiffies = cache->jiffies; |