aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r--fs/nfs/dir.c64
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:
629static 629static
630int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page) 630int 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)
660static 660static
661struct page *get_cache_page(nfs_readdir_descriptor_t *desc) 661struct 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 */
1147static 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 */
1141static int nfs_dentry_delete(const struct dentry *dentry) 1180static int nfs_dentry_delete(const struct dentry *dentry)
@@ -1202,6 +1241,7 @@ static void nfs_d_release(struct dentry *dentry)
1202 1241
1203const struct dentry_operations nfs_dentry_operations = { 1242const 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