if (!err) {
if (EX_ISSYNC(fhp->fh_export))
nfsd_sync_dir(dentry);
+@@ -1148,7 +1329,10 @@ nfsd_symlink(struct svc_rqst *rqstp, str
+ iap->ia_valid |= ATTR_CTIME;
+ iap->ia_mode = (iap->ia_mode&S_IALLUGO)
+ | S_IFLNK;
+- err = notify_change(dnew, iap);
++ if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw)
++ err = setattr_raw(dnew->d_inode, iap);
++ else
++ err = notify_change(dnew, iap);
+ if (err)
+ err = nfserrno(err);
+ else if (EX_ISSYNC(fhp->fh_export))
@@ -1211,7 +1392,10 @@
dold = tfhp->fh_dentry;
dest = dold->d_inode;
break;
}
goto return_base;
-@@ -645,6 +684,27 @@ return_reval:
+@@ -645,6 +684,34 @@ return_reval:
* Check the cached dentry for staleness.
*/
dentry = nd->dentry;
+ }
+ if (!nd->dentry->d_inode)
+ goto no_inode;
++ if (lookup_flags & LOOKUP_DIRECTORY) {
++ err = -ENOTDIR;
++ if (!nd->dentry->d_inode->i_op ||
++ (!nd->dentry->d_inode->i_op->lookup &&
++ !nd->dentry->d_inode->i_op->lookup_it))
++ break;
++ }
+ } else
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
err = -ESTALE;
break;
}
goto return_base;
-@@ -643,6 +681,25 @@
+@@ -643,6 +681,32 @@
* Check the cached dentry for staleness.
*/
dentry = nd->dentry;
+ }
+ if (!nd->dentry->d_inode)
+ goto no_inode;
++ if (lookup_flags & LOOKUP_DIRECTORY) {
++ err = -ENOTDIR;
++ if (!nd->dentry->d_inode->i_op ||
++ (!nd->dentry->d_inode->i_op->lookup &&
++ !nd->dentry->d_inode->i_op->lookup_it))
++ break;
++ }
+ } else
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
err = -ESTALE;
break;
}
goto return_base;
-@@ -633,6 +687,27 @@
+@@ -633,6 +687,34 @@
* Check the cached dentry for staleness.
*/
dentry = nd->dentry;
+ }
+ if (!nd->dentry->d_inode)
+ goto no_inode;
++ if (lookup_flags & LOOKUP_DIRECTORY) {
++ err = -ENOTDIR;
++ if (!nd->dentry->d_inode->i_op ||
++ (!nd->dentry->d_inode->i_op->lookup &&
++ !nd->dentry->d_inode->i_op->lookup_it))
++ break;
++ }
+ } else
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
err = -ESTALE;
break;
}
goto return_base;
-@@ -645,6 +698,27 @@
+@@ -645,6 +698,34 @@
* Check the cached dentry for staleness.
*/
dentry = nd->dentry;
+ }
+ if (!nd->dentry->d_inode)
+ goto no_inode;
++ if (lookup_flags & LOOKUP_DIRECTORY) {
++ err = -ENOTDIR;
++ if (!nd->dentry->d_inode->i_op ||
++ (!nd->dentry->d_inode->i_op->lookup &&
++ !nd->dentry->d_inode->i_op->lookup_it))
++ break;
++ }
+ } else
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
err = -ESTALE;
break;
}
goto return_base;
-@@ -635,6 +672,27 @@ return_reval:
+@@ -635,6 +672,34 @@ return_reval:
* Check the cached dentry for staleness.
*/
dentry = nd->dentry;
+ }
+ if (!nd->dentry->d_inode)
+ goto no_inode;
++ if (lookup_flags & LOOKUP_DIRECTORY) {
++ err = -ENOTDIR;
++ if (!nd->dentry->d_inode->i_op ||
++ (!nd->dentry->d_inode->i_op->lookup &&
++ !nd->dentry->d_inode->i_op->lookup_it))
++ break;
++ }
+ } else
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
err = -ESTALE;
+ }
+ if (!nd->dentry->d_inode)
+ goto no_inode;
++ if (lookup_flags & LOOKUP_DIRECTORY) {
++ err = -ENOTDIR;
++ if (!nd->dentry->d_inode->i_op ||
++ (!nd->dentry->d_inode->i_op->lookup &&
++ !nd->dentry->d_inode->i_op->lookup_it))
++ break;
++ }
+ } else
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
err = -ESTALE;
break;
}
goto return_base;
-@@ -643,6 +680,27 @@
+@@ -643,6 +680,34 @@
* Check the cached dentry for staleness.
*/
dentry = nd->dentry;
+ }
+ if (!nd->dentry->d_inode)
+ goto no_inode;
++ if (lookup_flags & LOOKUP_DIRECTORY) {
++ err = -ENOTDIR;
++ if (!nd->dentry->d_inode->i_op ||
++ (!nd->dentry->d_inode->i_op->lookup &&
++ !nd->dentry->d_inode->i_op->lookup_it))
++ break;
++ }
+ } else
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
err = -ESTALE;
break;
}
goto return_base;
-@@ -635,6 +672,25 @@ return_reval:
+@@ -635,6 +672,32 @@ return_reval:
* Check the cached dentry for staleness.
*/
dentry = nd->dentry;
+ dput(dentry);
+ nd->dentry = new;
+ }
++ if (lookup_flags & LOOKUP_DIRECTORY) {
++ err = -ENOTDIR;
++ if (!nd->dentry->d_inode->i_op ||
++ (!nd->dentry->d_inode->i_op->lookup &&
++ !nd->dentry->d_inode->i_op->lookup_it))
++ break;
++ }
+ } else
if (dentry && dentry->d_sb
&& (dentry->d_sb->s_type->fs_flags & FS_ALWAYS_REVAL)) {
}
run_test 48d "Access removed parent subdir (should return errors)"
+test_48e() { # bug 4134
+# check_kernel_version 36 || return 0
+ #sysctl -w portals.debug=-1
+ #set -vx
+ mkdir -p $DIR/d48e/dir
+ # On a buggy kernel addition of "; touch file" after cd .. will
+ # produce kernel oops in lookup_hash_it
+ ( cd $DIR/d48e/dir ; sleep 2 ; cd -P .. ) &
+ cdpid=$!
+ $TRACE rmdir $DIR/d48e/dir || error "remove cwd $DIR/d48e/dir failed"
+ $TRACE rmdir $DIR/d48e || error "remove parent $DIR/d48e failed"
+ $TRACE touch $DIR/d48e || error "'touch $DIR/d48e' failed"
+ $TRACE chmod +x $DIR/d48e || error "'chmod +x $DIR/d48e' failed"
+ $TRACE wait $cdpid && error "'cd ..' worked after recreate parent"
+ $TRACE rm $DIR/d48e || error "'$DIR/d48e' failed"
+}
+run_test 48e "Access to removed and recreated parent subdir (should return errors)"
+
test_50() {
# bug 1485
mkdir $DIR/d50