@@ -1072,6 +1072,100 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
1072
1072
return !nfs_check_verifier (dir , dentry , flags & LOOKUP_RCU );
1073
1073
}
1074
1074
1075
+ static int
1076
+ nfs_lookup_revalidate_done (struct inode * dir , struct dentry * dentry ,
1077
+ struct inode * inode , int error )
1078
+ {
1079
+ switch (error ) {
1080
+ case 1 :
1081
+ dfprintk (LOOKUPCACHE , "NFS: %s(%pd2) is valid\n" ,
1082
+ __func__ , dentry );
1083
+ return 1 ;
1084
+ case 0 :
1085
+ nfs_mark_for_revalidate (dir );
1086
+ if (inode && S_ISDIR (inode -> i_mode )) {
1087
+ /* Purge readdir caches. */
1088
+ nfs_zap_caches (inode );
1089
+ /*
1090
+ * We can't d_drop the root of a disconnected tree:
1091
+ * its d_hash is on the s_anon list and d_drop() would hide
1092
+ * it from shrink_dcache_for_unmount(), leading to busy
1093
+ * inodes on unmount and further oopses.
1094
+ */
1095
+ if (IS_ROOT (dentry ))
1096
+ return 1 ;
1097
+ }
1098
+ dfprintk (LOOKUPCACHE , "NFS: %s(%pd2) is invalid\n" ,
1099
+ __func__ , dentry );
1100
+ return 0 ;
1101
+ }
1102
+ dfprintk (LOOKUPCACHE , "NFS: %s(%pd2) lookup returned error %d\n" ,
1103
+ __func__ , dentry , error );
1104
+ return error ;
1105
+ }
1106
+
1107
+ static int
1108
+ nfs_lookup_revalidate_negative (struct inode * dir , struct dentry * dentry ,
1109
+ unsigned int flags )
1110
+ {
1111
+ int ret = 1 ;
1112
+ if (nfs_neg_need_reval (dir , dentry , flags )) {
1113
+ if (flags & LOOKUP_RCU )
1114
+ return - ECHILD ;
1115
+ ret = 0 ;
1116
+ }
1117
+ return nfs_lookup_revalidate_done (dir , dentry , NULL , ret );
1118
+ }
1119
+
1120
+ static int
1121
+ nfs_lookup_revalidate_delegated (struct inode * dir , struct dentry * dentry ,
1122
+ struct inode * inode )
1123
+ {
1124
+ nfs_set_verifier (dentry , nfs_save_change_attribute (dir ));
1125
+ return nfs_lookup_revalidate_done (dir , dentry , inode , 1 );
1126
+ }
1127
+
1128
+ static int
1129
+ nfs_lookup_revalidate_dentry (struct inode * dir , struct dentry * dentry ,
1130
+ struct inode * inode )
1131
+ {
1132
+ struct nfs_fh * fhandle ;
1133
+ struct nfs_fattr * fattr ;
1134
+ struct nfs4_label * label ;
1135
+ int ret ;
1136
+
1137
+ ret = - ENOMEM ;
1138
+ fhandle = nfs_alloc_fhandle ();
1139
+ fattr = nfs_alloc_fattr ();
1140
+ label = nfs4_label_alloc (NFS_SERVER (inode ), GFP_KERNEL );
1141
+ if (fhandle == NULL || fattr == NULL || IS_ERR (label ))
1142
+ goto out ;
1143
+
1144
+ ret = NFS_PROTO (dir )-> lookup (dir , & dentry -> d_name , fhandle , fattr , label );
1145
+ if (ret < 0 ) {
1146
+ if (ret == - ESTALE || ret == - ENOENT )
1147
+ ret = 0 ;
1148
+ goto out ;
1149
+ }
1150
+ ret = 0 ;
1151
+ if (nfs_compare_fh (NFS_FH (inode ), fhandle ))
1152
+ goto out ;
1153
+ if (nfs_refresh_inode (inode , fattr ) < 0 )
1154
+ goto out ;
1155
+
1156
+ nfs_setsecurity (inode , fattr , label );
1157
+ nfs_set_verifier (dentry , nfs_save_change_attribute (dir ));
1158
+
1159
+ /* set a readdirplus hint that we had a cache miss */
1160
+ nfs_force_use_readdirplus (dir );
1161
+ ret = 1 ;
1162
+ out :
1163
+ nfs_free_fattr (fattr );
1164
+ nfs_free_fhandle (fhandle );
1165
+ nfs4_label_free (label );
1166
+ return nfs_lookup_revalidate_done (dir , dentry , inode , ret );
1167
+ }
1168
+
1075
1169
/*
1076
1170
* This is called every time the dcache has a lookup hit,
1077
1171
* and we should check whether we can really trust that
@@ -1083,58 +1177,36 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
1083
1177
* If the parent directory is seen to have changed, we throw out the
1084
1178
* cached dentry and do a new lookup.
1085
1179
*/
1086
- static int nfs_lookup_revalidate (struct dentry * dentry , unsigned int flags )
1180
+ static int
1181
+ nfs_do_lookup_revalidate (struct inode * dir , struct dentry * dentry ,
1182
+ unsigned int flags )
1087
1183
{
1088
- struct inode * dir ;
1089
1184
struct inode * inode ;
1090
- struct dentry * parent ;
1091
- struct nfs_fh * fhandle = NULL ;
1092
- struct nfs_fattr * fattr = NULL ;
1093
- struct nfs4_label * label = NULL ;
1094
1185
int error ;
1095
1186
1096
- if (flags & LOOKUP_RCU ) {
1097
- parent = READ_ONCE (dentry -> d_parent );
1098
- dir = d_inode_rcu (parent );
1099
- if (!dir )
1100
- return - ECHILD ;
1101
- } else {
1102
- parent = dget_parent (dentry );
1103
- dir = d_inode (parent );
1104
- }
1105
1187
nfs_inc_stats (dir , NFSIOS_DENTRYREVALIDATE );
1106
1188
inode = d_inode (dentry );
1107
1189
1108
- if (!inode ) {
1109
- if (nfs_neg_need_reval (dir , dentry , flags )) {
1110
- if (flags & LOOKUP_RCU )
1111
- return - ECHILD ;
1112
- goto out_bad ;
1113
- }
1114
- goto out_valid ;
1115
- }
1190
+ if (!inode )
1191
+ return nfs_lookup_revalidate_negative (dir , dentry , flags );
1116
1192
1117
1193
if (is_bad_inode (inode )) {
1118
- if (flags & LOOKUP_RCU )
1119
- return - ECHILD ;
1120
1194
dfprintk (LOOKUPCACHE , "%s: %pd2 has dud inode\n" ,
1121
1195
__func__ , dentry );
1122
1196
goto out_bad ;
1123
1197
}
1124
1198
1125
1199
if (NFS_PROTO (dir )-> have_delegation (inode , FMODE_READ ))
1126
- goto out_set_verifier ;
1200
+ return nfs_lookup_revalidate_delegated ( dir , dentry , inode ) ;
1127
1201
1128
1202
/* Force a full look up iff the parent directory has changed */
1129
1203
if (!(flags & (LOOKUP_EXCL | LOOKUP_REVAL )) &&
1130
1204
nfs_check_verifier (dir , dentry , flags & LOOKUP_RCU )) {
1131
1205
error = nfs_lookup_verify_inode (inode , flags );
1132
1206
if (error ) {
1133
- if (flags & LOOKUP_RCU )
1134
- return - ECHILD ;
1135
1207
if (error == - ESTALE )
1136
- goto out_zap_parent ;
1137
- goto out_error ;
1208
+ nfs_zap_caches ( dir ) ;
1209
+ goto out_bad ;
1138
1210
}
1139
1211
nfs_advise_use_readdirplus (dir );
1140
1212
goto out_valid ;
@@ -1146,81 +1218,39 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
1146
1218
if (NFS_STALE (inode ))
1147
1219
goto out_bad ;
1148
1220
1149
- error = - ENOMEM ;
1150
- fhandle = nfs_alloc_fhandle ();
1151
- fattr = nfs_alloc_fattr ();
1152
- if (fhandle == NULL || fattr == NULL )
1153
- goto out_error ;
1154
-
1155
- label = nfs4_label_alloc (NFS_SERVER (inode ), GFP_NOWAIT );
1156
- if (IS_ERR (label ))
1157
- goto out_error ;
1158
-
1159
1221
trace_nfs_lookup_revalidate_enter (dir , dentry , flags );
1160
- error = NFS_PROTO (dir ) -> lookup ( dir , & dentry -> d_name , fhandle , fattr , label );
1222
+ error = nfs_lookup_revalidate_dentry (dir , dentry , inode );
1161
1223
trace_nfs_lookup_revalidate_exit (dir , dentry , flags , error );
1162
- if (error == - ESTALE || error == - ENOENT )
1163
- goto out_bad ;
1164
- if (error )
1165
- goto out_error ;
1166
- if (nfs_compare_fh (NFS_FH (inode ), fhandle ))
1167
- goto out_bad ;
1168
- if ((error = nfs_refresh_inode (inode , fattr )) != 0 )
1169
- goto out_bad ;
1170
-
1171
- nfs_setsecurity (inode , fattr , label );
1172
-
1173
- nfs_free_fattr (fattr );
1174
- nfs_free_fhandle (fhandle );
1175
- nfs4_label_free (label );
1224
+ return error ;
1225
+ out_valid :
1226
+ return nfs_lookup_revalidate_done (dir , dentry , inode , 1 );
1227
+ out_bad :
1228
+ if (flags & LOOKUP_RCU )
1229
+ return - ECHILD ;
1230
+ return nfs_lookup_revalidate_done (dir , dentry , inode , 0 );
1231
+ }
1176
1232
1177
- /* set a readdirplus hint that we had a cache miss */
1178
- nfs_force_use_readdirplus (dir );
1233
+ static int
1234
+ nfs_lookup_revalidate (struct dentry * dentry , unsigned int flags )
1235
+ {
1236
+ struct dentry * parent ;
1237
+ struct inode * dir ;
1238
+ int ret ;
1179
1239
1180
- out_set_verifier :
1181
- nfs_set_verifier (dentry , nfs_save_change_attribute (dir ));
1182
- out_valid :
1183
1240
if (flags & LOOKUP_RCU ) {
1241
+ parent = READ_ONCE (dentry -> d_parent );
1242
+ dir = d_inode_rcu (parent );
1243
+ if (!dir )
1244
+ return - ECHILD ;
1245
+ ret = nfs_do_lookup_revalidate (dir , dentry , flags );
1184
1246
if (parent != READ_ONCE (dentry -> d_parent ))
1185
1247
return - ECHILD ;
1186
- } else
1248
+ } else {
1249
+ parent = dget_parent (dentry );
1250
+ ret = nfs_do_lookup_revalidate (d_inode (parent ), dentry , flags );
1187
1251
dput (parent );
1188
- dfprintk (LOOKUPCACHE , "NFS: %s(%pd2) is valid\n" ,
1189
- __func__ , dentry );
1190
- return 1 ;
1191
- out_zap_parent :
1192
- nfs_zap_caches (dir );
1193
- out_bad :
1194
- WARN_ON (flags & LOOKUP_RCU );
1195
- nfs_free_fattr (fattr );
1196
- nfs_free_fhandle (fhandle );
1197
- nfs4_label_free (label );
1198
- nfs_mark_for_revalidate (dir );
1199
- if (inode && S_ISDIR (inode -> i_mode )) {
1200
- /* Purge readdir caches. */
1201
- nfs_zap_caches (inode );
1202
- /*
1203
- * We can't d_drop the root of a disconnected tree:
1204
- * its d_hash is on the s_anon list and d_drop() would hide
1205
- * it from shrink_dcache_for_unmount(), leading to busy
1206
- * inodes on unmount and further oopses.
1207
- */
1208
- if (IS_ROOT (dentry ))
1209
- goto out_valid ;
1210
1252
}
1211
- dput (parent );
1212
- dfprintk (LOOKUPCACHE , "NFS: %s(%pd2) is invalid\n" ,
1213
- __func__ , dentry );
1214
- return 0 ;
1215
- out_error :
1216
- WARN_ON (flags & LOOKUP_RCU );
1217
- nfs_free_fattr (fattr );
1218
- nfs_free_fhandle (fhandle );
1219
- nfs4_label_free (label );
1220
- dput (parent );
1221
- dfprintk (LOOKUPCACHE , "NFS: %s(%pd2) lookup returned error %d\n" ,
1222
- __func__ , dentry , error );
1223
- return error ;
1253
+ return ret ;
1224
1254
}
1225
1255
1226
1256
/*
0 commit comments