+int ll_revalidate2(struct dentry *de, int flags, struct lookup_intent *it)
+{
+ int rc;
+ ENTRY;
+
+ /* We don't want to cache negative dentries, so return 0 immediately.
+ * We believe that this is safe, that negative dentries cannot be
+ * pinned by someone else */
+ if (de->d_inode == NULL) {
+ CDEBUG(D_INODE, "negative dentry: ret 0 to force lookup2\n");
+ RETURN(0);
+ }
+
+ if (it && it->it_op == IT_TRUNC)
+ it->it_op = IT_SETATTR;
+
+ if (it == NULL || it->it_op == IT_GETATTR) {
+ /* We could just return 1 immediately, but since we should only
+ * be called in revalidate2 if we already have a lock, let's
+ * verify that. */
+ struct inode *inode = de->d_inode;
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
+ struct obd_device *obddev = class_conn2obd(&sbi->ll_mdc_conn);
+ struct ldlm_res_id res_id =
+ { .name = {inode->i_ino, (__u64)inode->i_generation} };
+ struct lustre_handle lockh;
+ rc = ldlm_lock_match(obddev->obd_namespace,
+ LDLM_FL_BLOCK_GRANTED, &res_id,
+ LDLM_PLAIN, NULL, 0, LCK_PR, &lockh);
+ if (rc) {
+ de->d_flags &= ~DCACHE_LUSTRE_INVALID;
+ if (it && it->it_op == IT_GETATTR) {
+ memcpy(it->it_lock_handle, &lockh,
+ sizeof(lockh));
+ it->it_lock_mode = LCK_PR;
+ LL_SAVE_INTENT(de, it);
+ } else {
+ ldlm_lock_decref(&lockh, LCK_PR);
+ }
+ RETURN(1);
+ }
+ rc = ldlm_lock_match(obddev->obd_namespace,
+ LDLM_FL_BLOCK_GRANTED, &res_id,
+ LDLM_PLAIN, NULL, 0, LCK_PW, &lockh);
+ if (rc) {
+ de->d_flags &= ~DCACHE_LUSTRE_INVALID;
+ if (it && it->it_op == IT_GETATTR) {
+ memcpy(it->it_lock_handle, &lockh,
+ sizeof(lockh));
+ it->it_lock_mode = LCK_PW;
+ LL_SAVE_INTENT(de, it);
+ } else {
+ ldlm_lock_decref(&lockh, LCK_PW);
+ }
+ RETURN(1);
+ }
+ if (S_ISDIR(de->d_inode->i_mode))
+ ll_invalidate_inode_pages(de->d_inode);
+ d_unhash_aliases(de->d_inode);
+ RETURN(0);
+ }
+
+ rc = ll_intent_lock(de->d_parent->d_inode, &de, it, revalidate2_finish);
+ if (rc == -ESTALE)
+ RETURN(0);
+ if (rc < 0 && it->it_status) {
+ CERROR("ll_intent_lock: rc %d : it->it_status %d\n", rc,
+ it->it_status);
+ RETURN(0);
+ }
+ /* unfortunately ll_intent_lock may cause a callback and revoke our
+ dentry */
+ spin_lock(&dcache_lock);
+ list_del_init(&de->d_hash);
+ spin_unlock(&dcache_lock);
+ d_rehash(de);
+
+ RETURN(1);
+}
+