diff options
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 32e6c53520e2..f23f455be42b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -281,7 +281,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des | |||
281 | 281 | ||
282 | for (i = 0; i < array->size; i++) { | 282 | for (i = 0; i < array->size; i++) { |
283 | if (array->array[i].cookie == *desc->dir_cookie) { | 283 | if (array->array[i].cookie == *desc->dir_cookie) { |
284 | struct nfs_inode *nfsi = NFS_I(desc->file->f_path.dentry->d_inode); | 284 | struct nfs_inode *nfsi = NFS_I(file_inode(desc->file)); |
285 | struct nfs_open_dir_context *ctx = desc->file->private_data; | 285 | struct nfs_open_dir_context *ctx = desc->file->private_data; |
286 | 286 | ||
287 | new_pos = desc->current_index + i; | 287 | new_pos = desc->current_index + i; |
@@ -629,7 +629,7 @@ out: | |||
629 | static | 629 | static |
630 | int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page) | 630 | int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page) |
631 | { | 631 | { |
632 | struct inode *inode = desc->file->f_path.dentry->d_inode; | 632 | struct inode *inode = file_inode(desc->file); |
633 | int ret; | 633 | int ret; |
634 | 634 | ||
635 | ret = nfs_readdir_xdr_to_array(desc, page, inode); | 635 | ret = nfs_readdir_xdr_to_array(desc, page, inode); |
@@ -660,7 +660,7 @@ void cache_page_release(nfs_readdir_descriptor_t *desc) | |||
660 | static | 660 | static |
661 | struct page *get_cache_page(nfs_readdir_descriptor_t *desc) | 661 | struct page *get_cache_page(nfs_readdir_descriptor_t *desc) |
662 | { | 662 | { |
663 | return read_cache_page(desc->file->f_path.dentry->d_inode->i_mapping, | 663 | return read_cache_page(file_inode(desc->file)->i_mapping, |
664 | desc->page_index, (filler_t *)nfs_readdir_filler, desc); | 664 | desc->page_index, (filler_t *)nfs_readdir_filler, desc); |
665 | } | 665 | } |
666 | 666 | ||
@@ -764,7 +764,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
764 | { | 764 | { |
765 | struct page *page = NULL; | 765 | struct page *page = NULL; |
766 | int status; | 766 | int status; |
767 | struct inode *inode = desc->file->f_path.dentry->d_inode; | 767 | struct inode *inode = file_inode(desc->file); |
768 | struct nfs_open_dir_context *ctx = desc->file->private_data; | 768 | struct nfs_open_dir_context *ctx = desc->file->private_data; |
769 | 769 | ||
770 | dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n", | 770 | dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n", |
@@ -1136,6 +1136,45 @@ out_error: | |||
1136 | } | 1136 | } |
1137 | 1137 | ||
1138 | /* | 1138 | /* |
1139 | * A weaker form of d_revalidate for revalidating just the dentry->d_inode | ||
1140 | * when we don't really care about the dentry name. This is called when a | ||
1141 | * pathwalk ends on a dentry that was not found via a normal lookup in the | ||
1142 | * parent dir (e.g.: ".", "..", procfs symlinks or mountpoint traversals). | ||
1143 | * | ||
1144 | * In this situation, we just want to verify that the inode itself is OK | ||
1145 | * since the dentry might have changed on the server. | ||
1146 | */ | ||
1147 | static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags) | ||
1148 | { | ||
1149 | int error; | ||
1150 | struct inode *inode = dentry->d_inode; | ||
1151 | |||
1152 | /* | ||
1153 | * I believe we can only get a negative dentry here in the case of a | ||
1154 | * procfs-style symlink. Just assume it's correct for now, but we may | ||
1155 | * eventually need to do something more here. | ||
1156 | */ | ||
1157 | if (!inode) { | ||
1158 | dfprintk(LOOKUPCACHE, "%s: %s/%s has negative inode\n", | ||
1159 | __func__, dentry->d_parent->d_name.name, | ||
1160 | dentry->d_name.name); | ||
1161 | return 1; | ||
1162 | } | ||
1163 | |||
1164 | if (is_bad_inode(inode)) { | ||
1165 | dfprintk(LOOKUPCACHE, "%s: %s/%s has dud inode\n", | ||
1166 | __func__, dentry->d_parent->d_name.name, | ||
1167 | dentry->d_name.name); | ||
1168 | return 0; | ||
1169 | } | ||
1170 | |||
1171 | error = nfs_revalidate_inode(NFS_SERVER(inode), inode); | ||
1172 | dfprintk(LOOKUPCACHE, "NFS: %s: inode %lu is %s\n", | ||
1173 | __func__, inode->i_ino, error ? "invalid" : "valid"); | ||
1174 | return !error; | ||
1175 | } | ||
1176 | |||
1177 | /* | ||
1139 | * This is called from dput() when d_count is going to 0. | 1178 | * This is called from dput() when d_count is going to 0. |
1140 | */ | 1179 | */ |
1141 | static int nfs_dentry_delete(const struct dentry *dentry) | 1180 | static int nfs_dentry_delete(const struct dentry *dentry) |
@@ -1202,6 +1241,7 @@ static void nfs_d_release(struct dentry *dentry) | |||
1202 | 1241 | ||
1203 | const struct dentry_operations nfs_dentry_operations = { | 1242 | const struct dentry_operations nfs_dentry_operations = { |
1204 | .d_revalidate = nfs_lookup_revalidate, | 1243 | .d_revalidate = nfs_lookup_revalidate, |
1244 | .d_weak_revalidate = nfs_weak_revalidate, | ||
1205 | .d_delete = nfs_dentry_delete, | 1245 | .d_delete = nfs_dentry_delete, |
1206 | .d_iput = nfs_dentry_iput, | 1246 | .d_iput = nfs_dentry_iput, |
1207 | .d_automount = nfs_d_automount, | 1247 | .d_automount = nfs_d_automount, |
@@ -2153,12 +2193,16 @@ static int nfs_open_permission_mask(int openflags) | |||
2153 | { | 2193 | { |
2154 | int mask = 0; | 2194 | int mask = 0; |
2155 | 2195 | ||
2156 | if ((openflags & O_ACCMODE) != O_WRONLY) | 2196 | if (openflags & __FMODE_EXEC) { |
2157 | mask |= MAY_READ; | 2197 | /* ONLY check exec rights */ |
2158 | if ((openflags & O_ACCMODE) != O_RDONLY) | 2198 | mask = MAY_EXEC; |
2159 | mask |= MAY_WRITE; | 2199 | } else { |
2160 | if (openflags & __FMODE_EXEC) | 2200 | if ((openflags & O_ACCMODE) != O_WRONLY) |
2161 | mask |= MAY_EXEC; | 2201 | mask |= MAY_READ; |
2202 | if ((openflags & O_ACCMODE) != O_RDONLY) | ||
2203 | mask |= MAY_WRITE; | ||
2204 | } | ||
2205 | |||
2162 | return mask; | 2206 | return mask; |
2163 | } | 2207 | } |
2164 | 2208 | ||