diff options
Diffstat (limited to 'fs/nfs')
| -rw-r--r-- | fs/nfs/dir.c | 32 | ||||
| -rw-r--r-- | fs/nfs/getroot.c | 10 | ||||
| -rw-r--r-- | fs/nfs/inode.c | 9 | ||||
| -rw-r--r-- | fs/nfs/namespace.c | 17 | ||||
| -rw-r--r-- | fs/nfs/unlink.c | 2 |
5 files changed, 46 insertions, 24 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 996dd8989a91..d33da530097a 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -438,7 +438,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
| 438 | if (dentry == NULL) | 438 | if (dentry == NULL) |
| 439 | return; | 439 | return; |
| 440 | 440 | ||
| 441 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | 441 | d_set_d_op(dentry, NFS_PROTO(dir)->dentry_ops); |
| 442 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); | 442 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); |
| 443 | if (IS_ERR(inode)) | 443 | if (IS_ERR(inode)) |
| 444 | goto out; | 444 | goto out; |
| @@ -938,7 +938,8 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry) | |||
| 938 | * component of the path. | 938 | * component of the path. |
| 939 | * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT. | 939 | * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT. |
| 940 | */ | 940 | */ |
| 941 | static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask) | 941 | static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, |
| 942 | unsigned int mask) | ||
| 942 | { | 943 | { |
| 943 | if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT)) | 944 | if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT)) |
| 944 | return 0; | 945 | return 0; |
| @@ -1018,7 +1019,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, | |||
| 1018 | * If the parent directory is seen to have changed, we throw out the | 1019 | * If the parent directory is seen to have changed, we throw out the |
| 1019 | * cached dentry and do a new lookup. | 1020 | * cached dentry and do a new lookup. |
| 1020 | */ | 1021 | */ |
| 1021 | static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | 1022 | static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) |
| 1022 | { | 1023 | { |
| 1023 | struct inode *dir; | 1024 | struct inode *dir; |
| 1024 | struct inode *inode; | 1025 | struct inode *inode; |
| @@ -1027,6 +1028,9 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
| 1027 | struct nfs_fattr *fattr = NULL; | 1028 | struct nfs_fattr *fattr = NULL; |
| 1028 | int error; | 1029 | int error; |
| 1029 | 1030 | ||
| 1031 | if (nd->flags & LOOKUP_RCU) | ||
| 1032 | return -ECHILD; | ||
| 1033 | |||
| 1030 | parent = dget_parent(dentry); | 1034 | parent = dget_parent(dentry); |
| 1031 | dir = parent->d_inode; | 1035 | dir = parent->d_inode; |
| 1032 | nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE); | 1036 | nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE); |
| @@ -1117,7 +1121,7 @@ out_error: | |||
| 1117 | /* | 1121 | /* |
| 1118 | * This is called from dput() when d_count is going to 0. | 1122 | * This is called from dput() when d_count is going to 0. |
| 1119 | */ | 1123 | */ |
| 1120 | static int nfs_dentry_delete(struct dentry *dentry) | 1124 | static int nfs_dentry_delete(const struct dentry *dentry) |
| 1121 | { | 1125 | { |
| 1122 | dfprintk(VFS, "NFS: dentry_delete(%s/%s, %x)\n", | 1126 | dfprintk(VFS, "NFS: dentry_delete(%s/%s, %x)\n", |
| 1123 | dentry->d_parent->d_name.name, dentry->d_name.name, | 1127 | dentry->d_parent->d_name.name, dentry->d_name.name, |
| @@ -1188,7 +1192,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
| 1188 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) | 1192 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) |
| 1189 | goto out; | 1193 | goto out; |
| 1190 | 1194 | ||
| 1191 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | 1195 | d_set_d_op(dentry, NFS_PROTO(dir)->dentry_ops); |
| 1192 | 1196 | ||
| 1193 | /* | 1197 | /* |
| 1194 | * If we're doing an exclusive create, optimize away the lookup | 1198 | * If we're doing an exclusive create, optimize away the lookup |
| @@ -1333,7 +1337,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
| 1333 | res = ERR_PTR(-ENAMETOOLONG); | 1337 | res = ERR_PTR(-ENAMETOOLONG); |
| 1334 | goto out; | 1338 | goto out; |
| 1335 | } | 1339 | } |
| 1336 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | 1340 | d_set_d_op(dentry, NFS_PROTO(dir)->dentry_ops); |
| 1337 | 1341 | ||
| 1338 | /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash | 1342 | /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash |
| 1339 | * the dentry. */ | 1343 | * the dentry. */ |
| @@ -1718,11 +1722,9 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 1718 | dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, | 1722 | dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, |
| 1719 | dir->i_ino, dentry->d_name.name); | 1723 | dir->i_ino, dentry->d_name.name); |
| 1720 | 1724 | ||
| 1721 | spin_lock(&dcache_lock); | ||
| 1722 | spin_lock(&dentry->d_lock); | 1725 | spin_lock(&dentry->d_lock); |
| 1723 | if (atomic_read(&dentry->d_count) > 1) { | 1726 | if (dentry->d_count > 1) { |
| 1724 | spin_unlock(&dentry->d_lock); | 1727 | spin_unlock(&dentry->d_lock); |
| 1725 | spin_unlock(&dcache_lock); | ||
| 1726 | /* Start asynchronous writeout of the inode */ | 1728 | /* Start asynchronous writeout of the inode */ |
| 1727 | write_inode_now(dentry->d_inode, 0); | 1729 | write_inode_now(dentry->d_inode, 0); |
| 1728 | error = nfs_sillyrename(dir, dentry); | 1730 | error = nfs_sillyrename(dir, dentry); |
| @@ -1733,7 +1735,6 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 1733 | need_rehash = 1; | 1735 | need_rehash = 1; |
| 1734 | } | 1736 | } |
| 1735 | spin_unlock(&dentry->d_lock); | 1737 | spin_unlock(&dentry->d_lock); |
| 1736 | spin_unlock(&dcache_lock); | ||
| 1737 | error = nfs_safe_remove(dentry); | 1738 | error = nfs_safe_remove(dentry); |
| 1738 | if (!error || error == -ENOENT) { | 1739 | if (!error || error == -ENOENT) { |
| 1739 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1740 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
| @@ -1868,7 +1869,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 1868 | dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", | 1869 | dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", |
| 1869 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1870 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
| 1870 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, | 1871 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, |
| 1871 | atomic_read(&new_dentry->d_count)); | 1872 | new_dentry->d_count); |
| 1872 | 1873 | ||
| 1873 | /* | 1874 | /* |
| 1874 | * For non-directories, check whether the target is busy and if so, | 1875 | * For non-directories, check whether the target is busy and if so, |
| @@ -1886,7 +1887,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 1886 | rehash = new_dentry; | 1887 | rehash = new_dentry; |
| 1887 | } | 1888 | } |
| 1888 | 1889 | ||
| 1889 | if (atomic_read(&new_dentry->d_count) > 2) { | 1890 | if (new_dentry->d_count > 2) { |
| 1890 | int err; | 1891 | int err; |
| 1891 | 1892 | ||
| 1892 | /* copy the target dentry's name */ | 1893 | /* copy the target dentry's name */ |
| @@ -2188,11 +2189,14 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags) | |||
| 2188 | return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags)); | 2189 | return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags)); |
| 2189 | } | 2190 | } |
| 2190 | 2191 | ||
| 2191 | int nfs_permission(struct inode *inode, int mask) | 2192 | int nfs_permission(struct inode *inode, int mask, unsigned int flags) |
| 2192 | { | 2193 | { |
| 2193 | struct rpc_cred *cred; | 2194 | struct rpc_cred *cred; |
| 2194 | int res = 0; | 2195 | int res = 0; |
| 2195 | 2196 | ||
| 2197 | if (flags & IPERM_FLAG_RCU) | ||
| 2198 | return -ECHILD; | ||
| 2199 | |||
| 2196 | nfs_inc_stats(inode, NFSIOS_VFSACCESS); | 2200 | nfs_inc_stats(inode, NFSIOS_VFSACCESS); |
| 2197 | 2201 | ||
| 2198 | if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) | 2202 | if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) |
| @@ -2240,7 +2244,7 @@ out: | |||
| 2240 | out_notsup: | 2244 | out_notsup: |
| 2241 | res = nfs_revalidate_inode(NFS_SERVER(inode), inode); | 2245 | res = nfs_revalidate_inode(NFS_SERVER(inode), inode); |
| 2242 | if (res == 0) | 2246 | if (res == 0) |
| 2243 | res = generic_permission(inode, mask, NULL); | 2247 | res = generic_permission(inode, mask, flags, NULL); |
| 2244 | goto out; | 2248 | goto out; |
| 2245 | } | 2249 | } |
| 2246 | 2250 | ||
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index ac7b814ce162..5596c6a2881e 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
| @@ -63,9 +63,11 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i | |||
| 63 | * This again causes shrink_dcache_for_umount_subtree() to | 63 | * This again causes shrink_dcache_for_umount_subtree() to |
| 64 | * Oops, since the test for IS_ROOT() will fail. | 64 | * Oops, since the test for IS_ROOT() will fail. |
| 65 | */ | 65 | */ |
| 66 | spin_lock(&dcache_lock); | 66 | spin_lock(&sb->s_root->d_inode->i_lock); |
| 67 | spin_lock(&sb->s_root->d_lock); | ||
| 67 | list_del_init(&sb->s_root->d_alias); | 68 | list_del_init(&sb->s_root->d_alias); |
| 68 | spin_unlock(&dcache_lock); | 69 | spin_unlock(&sb->s_root->d_lock); |
| 70 | spin_unlock(&sb->s_root->d_inode->i_lock); | ||
| 69 | } | 71 | } |
| 70 | return 0; | 72 | return 0; |
| 71 | } | 73 | } |
| @@ -119,7 +121,7 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
| 119 | security_d_instantiate(ret, inode); | 121 | security_d_instantiate(ret, inode); |
| 120 | 122 | ||
| 121 | if (ret->d_op == NULL) | 123 | if (ret->d_op == NULL) |
| 122 | ret->d_op = server->nfs_client->rpc_ops->dentry_ops; | 124 | d_set_d_op(ret, server->nfs_client->rpc_ops->dentry_ops); |
| 123 | out: | 125 | out: |
| 124 | nfs_free_fattr(fsinfo.fattr); | 126 | nfs_free_fattr(fsinfo.fattr); |
| 125 | return ret; | 127 | return ret; |
| @@ -226,7 +228,7 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
| 226 | security_d_instantiate(ret, inode); | 228 | security_d_instantiate(ret, inode); |
| 227 | 229 | ||
| 228 | if (ret->d_op == NULL) | 230 | if (ret->d_op == NULL) |
| 229 | ret->d_op = server->nfs_client->rpc_ops->dentry_ops; | 231 | d_set_d_op(ret, server->nfs_client->rpc_ops->dentry_ops); |
| 230 | 232 | ||
| 231 | out: | 233 | out: |
| 232 | nfs_free_fattr(fattr); | 234 | nfs_free_fattr(fattr); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e67e31c73416..017daa3bed38 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -1438,11 +1438,18 @@ struct inode *nfs_alloc_inode(struct super_block *sb) | |||
| 1438 | return &nfsi->vfs_inode; | 1438 | return &nfsi->vfs_inode; |
| 1439 | } | 1439 | } |
| 1440 | 1440 | ||
| 1441 | void nfs_destroy_inode(struct inode *inode) | 1441 | static void nfs_i_callback(struct rcu_head *head) |
| 1442 | { | 1442 | { |
| 1443 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 1444 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 1443 | kmem_cache_free(nfs_inode_cachep, NFS_I(inode)); | 1445 | kmem_cache_free(nfs_inode_cachep, NFS_I(inode)); |
| 1444 | } | 1446 | } |
| 1445 | 1447 | ||
| 1448 | void nfs_destroy_inode(struct inode *inode) | ||
| 1449 | { | ||
| 1450 | call_rcu(&inode->i_rcu, nfs_i_callback); | ||
| 1451 | } | ||
| 1452 | |||
| 1446 | static inline void nfs4_init_once(struct nfs_inode *nfsi) | 1453 | static inline void nfs4_init_once(struct nfs_inode *nfsi) |
| 1447 | { | 1454 | { |
| 1448 | #ifdef CONFIG_NFS_V4 | 1455 | #ifdef CONFIG_NFS_V4 |
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index db6aa3673cf3..74aaf3963c10 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
| @@ -49,12 +49,17 @@ char *nfs_path(const char *base, | |||
| 49 | const struct dentry *dentry, | 49 | const struct dentry *dentry, |
| 50 | char *buffer, ssize_t buflen) | 50 | char *buffer, ssize_t buflen) |
| 51 | { | 51 | { |
| 52 | char *end = buffer+buflen; | 52 | char *end; |
| 53 | int namelen; | 53 | int namelen; |
| 54 | unsigned seq; | ||
| 54 | 55 | ||
| 56 | rename_retry: | ||
| 57 | end = buffer+buflen; | ||
| 55 | *--end = '\0'; | 58 | *--end = '\0'; |
| 56 | buflen--; | 59 | buflen--; |
| 57 | spin_lock(&dcache_lock); | 60 | |
| 61 | seq = read_seqbegin(&rename_lock); | ||
| 62 | rcu_read_lock(); | ||
| 58 | while (!IS_ROOT(dentry) && dentry != droot) { | 63 | while (!IS_ROOT(dentry) && dentry != droot) { |
| 59 | namelen = dentry->d_name.len; | 64 | namelen = dentry->d_name.len; |
| 60 | buflen -= namelen + 1; | 65 | buflen -= namelen + 1; |
| @@ -65,7 +70,9 @@ char *nfs_path(const char *base, | |||
| 65 | *--end = '/'; | 70 | *--end = '/'; |
| 66 | dentry = dentry->d_parent; | 71 | dentry = dentry->d_parent; |
| 67 | } | 72 | } |
| 68 | spin_unlock(&dcache_lock); | 73 | rcu_read_unlock(); |
| 74 | if (read_seqretry(&rename_lock, seq)) | ||
| 75 | goto rename_retry; | ||
| 69 | if (*end != '/') { | 76 | if (*end != '/') { |
| 70 | if (--buflen < 0) | 77 | if (--buflen < 0) |
| 71 | goto Elong; | 78 | goto Elong; |
| @@ -82,7 +89,9 @@ char *nfs_path(const char *base, | |||
| 82 | memcpy(end, base, namelen); | 89 | memcpy(end, base, namelen); |
| 83 | return end; | 90 | return end; |
| 84 | Elong_unlock: | 91 | Elong_unlock: |
| 85 | spin_unlock(&dcache_lock); | 92 | rcu_read_unlock(); |
| 93 | if (read_seqretry(&rename_lock, seq)) | ||
| 94 | goto rename_retry; | ||
| 86 | Elong: | 95 | Elong: |
| 87 | return ERR_PTR(-ENAMETOOLONG); | 96 | return ERR_PTR(-ENAMETOOLONG); |
| 88 | } | 97 | } |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 7bdec8531400..8fe9eb47a97f 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
| @@ -496,7 +496,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry) | |||
| 496 | 496 | ||
| 497 | dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n", | 497 | dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n", |
| 498 | dentry->d_parent->d_name.name, dentry->d_name.name, | 498 | dentry->d_parent->d_name.name, dentry->d_name.name, |
| 499 | atomic_read(&dentry->d_count)); | 499 | dentry->d_count); |
| 500 | nfs_inc_stats(dir, NFSIOS_SILLYRENAME); | 500 | nfs_inc_stats(dir, NFSIOS_SILLYRENAME); |
| 501 | 501 | ||
| 502 | /* | 502 | /* |
