+
+ ll_frob_intent(&it, &lookup_it);
+ LASSERT(it);
+
+ ll_i2uctxt(&ctxt, de->d_parent->d_inode, de->d_inode);
+
+ rc = mdc_intent_lock(exp, &ctxt, &pfid, de->d_name.name, de->d_name.len,
+ NULL, 0,
+ &cfid, it, flags, &req, ll_mdc_blocking_ast);
+ /* If req is NULL, then mdc_intent_lock only tried to do a lock match;
+ * if all was well, it will return 1 if it found locks, 0 otherwise. */
+ if (req == NULL && rc >= 0)
+ GOTO(out, rc);
+
+ if (rc < 0) {
+ if (rc != -ESTALE) {
+ CDEBUG(D_INFO, "ll_intent_lock: rc %d : it->it_status "
+ "%d\n", rc, it->d.lustre.it_status);
+ }
+ GOTO(out, rc = 0);
+ }
+
+ rc = revalidate_it_finish(req, 1, it, de);
+ if (rc != 0) {
+ ll_intent_release(it);
+ GOTO(out, rc = 0);
+ }
+ rc = 1;
+
+ /* unfortunately ll_intent_lock may cause a callback and revoke our
+ dentry */
+ spin_lock(&dcache_lock);
+ hlist_del_init(&de->d_hash);
+ __d_rehash(de, 0);
+ spin_unlock(&dcache_lock);
+
+ out:
+ if (req != NULL && rc == 1)
+ ptlrpc_req_finished(req);
+ if (rc == 0) {
+ ll_unhash_aliases(de->d_inode);
+ de->d_flags |= DCACHE_LUSTRE_INVALID;
+ } else {
+ ll_lookup_finish_locks(it, de);
+ de->d_flags &= ~DCACHE_LUSTRE_INVALID;
+ }
+ RETURN(rc);
+}
+
+/*static*/ void ll_pin(struct dentry *de, struct vfsmount *mnt, int flag)
+{
+ struct inode *inode= de->d_inode;
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
+ struct ll_dentry_data *ldd = ll_d2d(de);
+ struct obd_client_handle *handle;
+ int rc = 0;
+ ENTRY;
+ LASSERT(ldd);
+
+ lock_kernel();
+ /* Strictly speaking this introduces an additional race: the
+ * increments should wait until the rpc has returned.
+ * However, given that at present the function is void, this
+ * issue is moot. */
+ if (flag == 1 && (++ldd->lld_mnt_count) > 1) {
+ unlock_kernel();
+ EXIT;
+ return;