aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/vfs_dentry.c1
-rw-r--r--fs/9p/vfs_super.c2
-rw-r--r--fs/dcache.c3
-rw-r--r--fs/namei.c8
-rw-r--r--fs/nfs/dir.c40
-rw-r--r--fs/nfs/nfs4super.c6
-rw-r--r--fs/nfs/super.c6
7 files changed, 53 insertions, 13 deletions
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 64600b5d0522..9ad68628522c 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -137,6 +137,7 @@ out_valid:
137 137
138const struct dentry_operations v9fs_cached_dentry_operations = { 138const struct dentry_operations v9fs_cached_dentry_operations = {
139 .d_revalidate = v9fs_lookup_revalidate, 139 .d_revalidate = v9fs_lookup_revalidate,
140 .d_weak_revalidate = v9fs_lookup_revalidate,
140 .d_delete = v9fs_cached_dentry_delete, 141 .d_delete = v9fs_cached_dentry_delete,
141 .d_release = v9fs_dentry_release, 142 .d_release = v9fs_dentry_release,
142}; 143};
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 137d50396898..91dad63e5a2d 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -363,5 +363,5 @@ struct file_system_type v9fs_fs_type = {
363 .mount = v9fs_mount, 363 .mount = v9fs_mount,
364 .kill_sb = v9fs_kill_super, 364 .kill_sb = v9fs_kill_super,
365 .owner = THIS_MODULE, 365 .owner = THIS_MODULE,
366 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT, 366 .fs_flags = FS_RENAME_DOES_D_MOVE,
367}; 367};
diff --git a/fs/dcache.c b/fs/dcache.c
index ebab049826c0..68220dd0c135 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1358,6 +1358,7 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
1358 WARN_ON_ONCE(dentry->d_flags & (DCACHE_OP_HASH | 1358 WARN_ON_ONCE(dentry->d_flags & (DCACHE_OP_HASH |
1359 DCACHE_OP_COMPARE | 1359 DCACHE_OP_COMPARE |
1360 DCACHE_OP_REVALIDATE | 1360 DCACHE_OP_REVALIDATE |
1361 DCACHE_OP_WEAK_REVALIDATE |
1361 DCACHE_OP_DELETE )); 1362 DCACHE_OP_DELETE ));
1362 dentry->d_op = op; 1363 dentry->d_op = op;
1363 if (!op) 1364 if (!op)
@@ -1368,6 +1369,8 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
1368 dentry->d_flags |= DCACHE_OP_COMPARE; 1369 dentry->d_flags |= DCACHE_OP_COMPARE;
1369 if (op->d_revalidate) 1370 if (op->d_revalidate)
1370 dentry->d_flags |= DCACHE_OP_REVALIDATE; 1371 dentry->d_flags |= DCACHE_OP_REVALIDATE;
1372 if (op->d_weak_revalidate)
1373 dentry->d_flags |= DCACHE_OP_WEAK_REVALIDATE;
1371 if (op->d_delete) 1374 if (op->d_delete)
1372 dentry->d_flags |= DCACHE_OP_DELETE; 1375 dentry->d_flags |= DCACHE_OP_DELETE;
1373 if (op->d_prune) 1376 if (op->d_prune)
diff --git a/fs/namei.c b/fs/namei.c
index 052c095c2808..dc984fee5532 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -600,14 +600,10 @@ static int complete_walk(struct nameidata *nd)
600 if (likely(!(nd->flags & LOOKUP_JUMPED))) 600 if (likely(!(nd->flags & LOOKUP_JUMPED)))
601 return 0; 601 return 0;
602 602
603 if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE))) 603 if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE)))
604 return 0; 604 return 0;
605 605
606 if (likely(!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT))) 606 status = dentry->d_op->d_weak_revalidate(dentry, nd->flags);
607 return 0;
608
609 /* Note: we do not d_invalidate() */
610 status = d_revalidate(dentry, nd->flags);
611 if (status > 0) 607 if (status > 0)
612 return 0; 608 return 0;
613 609
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index a8bd28cde7e2..f23f455be42b 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -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,
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 84d2e9e2f313..569b166cc050 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -28,7 +28,7 @@ static struct file_system_type nfs4_remote_fs_type = {
28 .name = "nfs4", 28 .name = "nfs4",
29 .mount = nfs4_remote_mount, 29 .mount = nfs4_remote_mount,
30 .kill_sb = nfs_kill_super, 30 .kill_sb = nfs_kill_super,
31 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 31 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
32}; 32};
33 33
34static struct file_system_type nfs4_remote_referral_fs_type = { 34static struct file_system_type nfs4_remote_referral_fs_type = {
@@ -36,7 +36,7 @@ static struct file_system_type nfs4_remote_referral_fs_type = {
36 .name = "nfs4", 36 .name = "nfs4",
37 .mount = nfs4_remote_referral_mount, 37 .mount = nfs4_remote_referral_mount,
38 .kill_sb = nfs_kill_super, 38 .kill_sb = nfs_kill_super,
39 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 39 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
40}; 40};
41 41
42struct file_system_type nfs4_referral_fs_type = { 42struct file_system_type nfs4_referral_fs_type = {
@@ -44,7 +44,7 @@ struct file_system_type nfs4_referral_fs_type = {
44 .name = "nfs4", 44 .name = "nfs4",
45 .mount = nfs4_referral_mount, 45 .mount = nfs4_referral_mount,
46 .kill_sb = nfs_kill_super, 46 .kill_sb = nfs_kill_super,
47 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 47 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
48}; 48};
49 49
50static const struct super_operations nfs4_sops = { 50static const struct super_operations nfs4_sops = {
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 2e7e8c878e5d..92acc26f9c5f 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -292,7 +292,7 @@ struct file_system_type nfs_fs_type = {
292 .name = "nfs", 292 .name = "nfs",
293 .mount = nfs_fs_mount, 293 .mount = nfs_fs_mount,
294 .kill_sb = nfs_kill_super, 294 .kill_sb = nfs_kill_super,
295 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 295 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
296}; 296};
297EXPORT_SYMBOL_GPL(nfs_fs_type); 297EXPORT_SYMBOL_GPL(nfs_fs_type);
298 298
@@ -301,7 +301,7 @@ struct file_system_type nfs_xdev_fs_type = {
301 .name = "nfs", 301 .name = "nfs",
302 .mount = nfs_xdev_mount, 302 .mount = nfs_xdev_mount,
303 .kill_sb = nfs_kill_super, 303 .kill_sb = nfs_kill_super,
304 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 304 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
305}; 305};
306 306
307const struct super_operations nfs_sops = { 307const struct super_operations nfs_sops = {
@@ -331,7 +331,7 @@ struct file_system_type nfs4_fs_type = {
331 .name = "nfs4", 331 .name = "nfs4",
332 .mount = nfs_fs_mount, 332 .mount = nfs_fs_mount,
333 .kill_sb = nfs_kill_super, 333 .kill_sb = nfs_kill_super,
334 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 334 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
335}; 335};
336EXPORT_SYMBOL_GPL(nfs4_fs_type); 336EXPORT_SYMBOL_GPL(nfs4_fs_type);
337 337