{
struct inode *dir = dentry->d_parent->d_inode;
- /*
- * if open&create is set, talk to MDS to make sure file is created if
- * necessary, because we can't do this in ->open() later since that's
- * called on an inode. return 0 here to let lookup to handle this.
- */
- if ((lookup_flags & (LOOKUP_OPEN | LOOKUP_CREATE)) ==
- (LOOKUP_OPEN | LOOKUP_CREATE))
- return 0;
+ /* If this is intermediate component path lookup and we were able to get
+ * to this dentry, then its lock has not been revoked and the
+ * path component is valid. */
+ if (lookup_flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))
+ return 1;
- if (lookup_flags & (LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE))
+ /* Symlink - always valid as long as the dentry was found */
+ if (dentry->d_inode && dentry->d_inode->i_op->follow_link)
return 1;
+ /* Last path component lookup for open or create - we always
+ * return 0 here to go through re-lookup and properly signal
+ * MDS whenever we do or do not want an open-cache to be engaged.
+ * For create we also ensure the entry is really created no matter
+ * what races might have happened.
+ * LU-4367 */
+ if (lookup_flags & (LOOKUP_OPEN | LOOKUP_CREATE))
+ return 0;
+
if (d_need_statahead(dir, dentry) <= 0)
return 1;
/*
* Normally called under two situations:
* 1. NFS export.
- * 2. revalidate with IT_OPEN (revalidate doesn't
- * execute this intent any more).
+ * 2. A race/condition on MDS resulting in no open
+ * handle to be returned from LOOKUP|OPEN request,
+ * for example if the target entry was a symlink.
*
* Always fetch MDS_OPEN_LOCK if this is not setstripe.
*