#include <lustre_lite.h>
#include <lustre/lustre_idl.h>
#include <lustre_dlm.h>
-#include <linux/lustre_version.h>
+#include <lustre_mdc.h>
+//#include <lustre_ver.h>
+//#include <lustre_version.h>
#include "llite_internal.h"
{
ENTRY;
+ CDEBUG(D_INFO, "intent %p released\n", it);
ll_intent_drop_lock(it);
#ifdef LUSTRE_KERNEL_VERSION
it->it_magic = 0;
spin_lock(&dcache_lock);
return 1;
}
- /* disconected dentry can not be find without lookup, because we
- * not need his to unhash or mark invalid. */
- if (dentry->d_flags & DCACHE_DISCONNECTED) {
- unlock_dentry(dentry);
- RETURN (0);
- }
+ /* disconected dentry can not be find without lookup, because we
+ * not need his to unhash or mark invalid. */
+ if (dentry->d_flags & DCACHE_DISCONNECTED) {
+ unlock_dentry(dentry);
+ RETURN (0);
+ }
#ifdef LUSTRE_KERNEL_VERSION
if (!(dentry->d_flags & DCACHE_LUSTRE_INVALID)) {
* sys_getcwd() could return -ENOENT -bzzz */
#ifdef LUSTRE_KERNEL_VERSION
dentry->d_flags |= DCACHE_LUSTRE_INVALID;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- __d_drop(dentry);
- if (dentry->d_inode) {
- /* Put positive dentries to orphan list */
- list_add(&dentry->d_hash,
- &ll_i2sbi(dentry->d_inode)->ll_orphan_dentry_list);
- }
#endif
-#else
if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
__d_drop(dentry);
-#endif
}
unlock_dentry(dentry);
while ((tmp = tmp->next) != head) {
struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
+ CDEBUG(D_DENTRY, "dentry in drop %.*s (%p) parent %p "
+ "inode %p flags %d\n", dentry->d_name.len,
+ dentry->d_name.name, dentry, dentry->d_parent,
+ dentry->d_inode, dentry->d_flags);
+
if (dentry->d_name.len == 1 && dentry->d_name.name[0] == '/') {
CERROR("called on root (?) dentry=%p, inode=%p "
"ino=%lu\n", dentry, inode, inode->i_ino);
continue;
}
-
+
if (ll_drop_dentry(dentry))
goto restart;
}
EXIT;
}
-int revalidate_it_finish(struct ptlrpc_request *request, int offset,
- struct lookup_intent *it, struct dentry *de)
+int ll_revalidate_it_finish(struct ptlrpc_request *request,
+ int offset, struct lookup_intent *it,
+ struct dentry *de)
{
int rc = 0;
ENTRY;
if (!request)
RETURN(0);
- if (it_disposition(it, DISP_LOOKUP_NEG))
+ if (it_disposition(it, DISP_LOOKUP_NEG))
RETURN(-ENOENT);
- rc = ll_prep_inode(ll_i2sbi(de->d_inode)->ll_osc_exp, &de->d_inode,
+ rc = ll_prep_inode(&de->d_inode,
request, offset, NULL);
RETURN(rc);
if (it->d.lustre.it_lock_mode && dentry->d_inode != NULL) {
struct inode *inode = dentry->d_inode;
+ struct ll_sb_info *sbi = ll_i2sbi(dentry->d_inode);
+
CDEBUG(D_DLMTRACE, "setting l_data to inode %p (%lu/%u)\n",
inode, inode->i_ino, inode->i_generation);
- mdc_set_lock_data(&it->d.lustre.it_lock_handle, inode);
+ md_set_lock_data(sbi->ll_md_exp, &it->d.lustre.it_lock_handle,
+ inode);
}
/* drop lookup or getattr locks immediately */
if (it->it_op == IT_LOOKUP || it->it_op == IT_GETATTR) {
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
/* on 2.6 there are situation when several lookups and
* revalidations may be requested during single operation.
* therefore, we don't release intent here -bzzz */
ll_intent_drop_lock(it);
-#else
- ll_intent_release(it);
-#endif
}
}
void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft)
{
struct lookup_intent *it = *itp;
-#if defined(LUSTRE_KERNEL_VERSION)&&(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#if defined(LUSTRE_KERNEL_VERSION)
if (it) {
- LASSERTF(it->it_magic == INTENT_MAGIC, "bad intent magic: %x\n",
- it->it_magic);
+ LASSERTF(it->it_magic == INTENT_MAGIC,
+ "%p has bad intent magic: %x\n",
+ it, it->it_magic);
}
#endif
struct lookup_intent *it)
{
int rc;
- struct mdc_op_data op_data;
+ struct md_op_data *op_data;
struct ptlrpc_request *req = NULL;
struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
struct obd_export *exp;
+ struct inode *parent;
ENTRY;
CDEBUG(D_VFSTRACE, "VFS Op:name=%s,intent=%s\n", de->d_name.name,
RETURN(rc);
}
- exp = ll_i2mdcexp(de->d_inode);
+ exp = ll_i2mdexp(de->d_inode);
/* Never execute intents for mount points.
* Attributes will be fixed up in ll_inode_revalidate_it */
/* Root of the lustre tree. Always valid.
* Attributes will be fixed up in ll_inode_revalidate_it */
- if (de->d_name.name[0] == '/' && de->d_name.len == 1)
+ if (de == de->d_sb->s_root)
RETURN(1);
OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5);
ll_frob_intent(&it, &lookup_it);
LASSERT(it);
- ll_prepare_mdc_op_data(&op_data, de->d_parent->d_inode, de->d_inode,
- de->d_name.name, de->d_name.len, 0);
+ parent = de->d_parent->d_inode;
+
+ if (it->it_op & IT_CREAT) {
+ op_data = ll_prep_md_op_data(NULL, parent, NULL,
+ de->d_name.name, de->d_name.len,
+ 0, LUSTRE_OPC_CREATE, NULL);
+ } else {
+ op_data = ll_prep_md_op_data(NULL, parent, de->d_inode,
+ de->d_name.name, de->d_name.len,
+ 0, LUSTRE_OPC_ANY, NULL);
+ }
+ if (IS_ERR(op_data))
+ RETURN(PTR_ERR(op_data));
+
if ((it->it_op == IT_OPEN) && de->d_inode) {
struct inode *inode = de->d_inode;
struct ll_inode_info *lli = ll_i2info(inode);
struct obd_client_handle **och_p;
__u64 *och_usecount;
- /* We used to check for MDS_INODELOCK_OPEN here, but in fact
+
+ /*
+ * We used to check for MDS_INODELOCK_OPEN here, but in fact
* just having LOOKUP lock is enough to justify inode is the
* same. And if inode is the same and we have suitable
* openhandle, then there is no point in doing another OPEN RPC
- * just to throw away newly received openhandle.
- * There are no security implications too, if file owner or
- * access mode is change, LOOKUP lock is revoked */
+ * just to throw away newly received openhandle. There are no
+ * security implications too, if file owner or access mode is
+ * change, LOOKUP lock is revoked.
+ */
+
if (it->it_flags & FMODE_WRITE) {
och_p = &lli->lli_mds_write_och;
} else if (it->it_flags & FMODE_EXEC) {
och_p = &lli->lli_mds_exec_och;
och_usecount = &lli->lli_open_fd_exec_count;
- } else {
+ } else {
och_p = &lli->lli_mds_read_och;
och_usecount = &lli->lli_open_fd_read_count;
}
down(&lli->lli_och_sem);
if (*och_p) { /* Everything is open already, do nothing */
/*(*och_usecount)++; Do not let them steal our open
- handle from under us */
+ handle from under us */
/* XXX The code above was my original idea, but in case
we have the handle, but we cannot use it due to later
checks (e.g. O_CREAT|O_EXCL flags set), nobody
if it would be, we'll reopen the open request to
MDS later during file open path */
up(&lli->lli_och_sem);
+ ll_finish_md_op_data(op_data);
RETURN(1);
} else {
up(&lli->lli_och_sem);
do_lock:
it->it_create_mode &= ~current->fs->umask;
-
- rc = mdc_intent_lock(exp, &op_data, NULL, 0, it, lookup_flags,
- &req, ll_mdc_blocking_ast, 0);
- /* If req is NULL, then mdc_intent_lock only tried to do a lock match;
+ it->it_flags |= O_CHECK_STALE;
+ rc = md_intent_lock(exp, op_data, NULL, 0, it,
+ lookup_flags,
+ &req, ll_md_blocking_ast, 0);
+ it->it_flags &= ~O_CHECK_STALE;
+ ll_finish_md_op_data(op_data);
+ /* If req is NULL, then md_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) {
if (!rc)
}
revalidate_finish:
- rc = revalidate_it_finish(req, DLM_REPLY_REC_OFF, it, de);
+ rc = ll_revalidate_it_finish(req, DLM_REPLY_REC_OFF, it, de);
if (rc != 0) {
- ll_intent_release(it);
+ if (rc != -ESTALE && rc != -ENOENT)
+ ll_intent_release(it);
GOTO(out, rc = 0);
}
+
if ((it->it_op & IT_OPEN) && de->d_inode &&
!S_ISREG(de->d_inode->i_mode) &&
!S_ISDIR(de->d_inode->i_mode)) {
__d_rehash(de, 0);
spin_unlock(&dcache_lock);
- out:
+out:
/* We do not free request as it may be reused during following lookup
* (see comment in mdc/mdc_locks.c::mdc_intent_lock()), request will
* be freed in ll_lookup_it or in ll_intent_release. But if
#ifdef LUSTRE_KERNEL_VERSION
ll_unhash_aliases(de->d_inode);
/* done in ll_unhash_aliases()
- dentry->d_flags |= DCACHE_LUSTRE_INVALID; */
+ dentry->d_flags |= DCACHE_LUSTRE_INVALID; */
#else
/* We do not want d_invalidate to kill all child dentries too */
d_drop(de);
#endif
} else {
CDEBUG(D_DENTRY, "revalidated dentry %.*s (%p) parent %p "
- "inode %p refc %d\n", de->d_name.len,
- de->d_name.name, de, de->d_parent, de->d_inode,
- atomic_read(&de->d_count));
+ "inode %p refc %d\n", de->d_name.len,
+ de->d_name.name, de, de->d_parent, de->d_inode,
+ atomic_read(&de->d_count));
ll_lookup_finish_locks(it, de);
#ifdef LUSTRE_KERNEL_VERSION
lock_dentry(de);
#endif
}
RETURN(rc);
-/* This part is here to combat evil-evil race in real_lookup on 2.6 kernels.
- * The race details are: We enter do_lookup() looking for some name,
- * there is nothing in dcache for this name yet and d_lookup() returns NULL.
- * We proceed to real_lookup(), and while we do this, another process does
- * open on the same file we looking up (most simple reproducer), open succeeds
- * and the dentry is added. Now back to us. In real_lookup() we do d_lookup()
- * again and suddenly find the dentry, so we call d_revalidate on it, but there
- * is no lock, so without this code we would return 0, but unpatched
- * real_lookup just returns -ENOENT in such a case instead of retrying the
- * lookup. Once this is dealt with in real_lookup(), all of this ugly mess
- * can go and we can just check locks in ->d_revalidate without doing any
- * RPCs ever. */
+
+ /*
+ * This part is here to combat evil-evil race in real_lookup on 2.6
+ * kernels. The race details are: We enter do_lookup() looking for some
+ * name, there is nothing in dcache for this name yet and d_lookup()
+ * returns NULL. We proceed to real_lookup(), and while we do this,
+ * another process does open on the same file we looking up (most simple
+ * reproducer), open succeeds and the dentry is added. Now back to
+ * us. In real_lookup() we do d_lookup() again and suddenly find the
+ * dentry, so we call d_revalidate on it, but there is no lock, so
+ * without this code we would return 0, but unpatched real_lookup just
+ * returns -ENOENT in such a case instead of retrying the lookup. Once
+ * this is dealt with in real_lookup(), all of this ugly mess can go and
+ * we can just check locks in ->d_revalidate without doing any RPCs
+ * ever.
+ */
do_lookup:
if (it != &lookup_it) {
+ /* MDS_INODELOCK_UPDATE needed for IT_GETATTR case. */
+ if (it->it_op == IT_GETATTR)
+ lookup_it.it_op = IT_GETATTR;
ll_lookup_finish_locks(it, de);
it = &lookup_it;
}
- /*do real lookup here */
- ll_prepare_mdc_op_data(&op_data, de->d_parent->d_inode, NULL,
- de->d_name.name, de->d_name.len, 0);
- rc = mdc_intent_lock(exp, &op_data, NULL, 0, it, 0, &req,
- ll_mdc_blocking_ast, 0);
+
+ /* Do real lookup here. */
+ op_data = ll_prep_md_op_data(NULL, parent, NULL, de->d_name.name,
+ de->d_name.len, 0, (it->it_op & IT_CREAT ?
+ LUSTRE_OPC_CREATE :
+ LUSTRE_OPC_ANY), NULL);
+ if (IS_ERR(op_data))
+ RETURN(PTR_ERR(op_data));
+
+ rc = md_intent_lock(exp, op_data, NULL, 0, it, 0, &req,
+ ll_md_blocking_ast, 0);
if (rc >= 0) {
- struct mds_body *mds_body = lustre_msg_buf(req->rq_repmsg,
+ struct mdt_body *mdt_body = lustre_msg_buf(req->rq_repmsg,
DLM_REPLY_REC_OFF,
- sizeof(*mds_body));
+ sizeof(*mdt_body));
+ struct lu_fid fid = {.f_seq = 0, .f_oid = 0, .f_ver = 0};
+
+ if (de->d_inode)
+ fid = *ll_inode2fid(de->d_inode);
+
/* see if we got same inode, if not - return error */
- if(!memcmp(&op_data.fid2, &mds_body->fid1,
- sizeof(op_data.fid2)))
+ if (lu_fid_eq(&fid, &mdt_body->fid1)) {
+ ll_finish_md_op_data(op_data);
+ op_data = NULL;
goto revalidate_finish;
+ }
ll_intent_release(it);
}
+ ll_finish_md_op_data(op_data);
GOTO(out, rc = 0);
}
struct ll_sb_info *sbi = ll_i2sbi(inode);
struct ll_dentry_data *ldd = ll_d2d(de);
struct obd_client_handle *handle;
+ struct obd_capa *oc;
int rc = 0;
ENTRY;
LASSERT(ldd);
unlock_kernel();
handle = (flag) ? &ldd->lld_mnt_och : &ldd->lld_cwd_och;
- rc = obd_pin(sbi->ll_mdc_exp, inode->i_ino, inode->i_generation,
- inode->i_mode & S_IFMT, handle, flag);
-
+ oc = ll_mdscapa_get(inode);
+ rc = obd_pin(sbi->ll_md_exp, ll_inode2fid(inode), oc, handle, flag);
+ capa_put(oc);
if (rc) {
lock_kernel();
memset(handle, 0, sizeof(*handle));
return;
}
- rc = obd_unpin(sbi->ll_mdc_exp, &handle, flag);
+ rc = obd_unpin(sbi->ll_md_exp, &handle, flag);
EXIT;
return;
}
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
#ifdef LUSTRE_KERNEL_VERSION
static int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd)
{
RETURN(rc);
}
#endif
-#endif
struct dentry_operations ll_d_ops = {
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
.d_revalidate = ll_revalidate_nd,
-#else
- .d_revalidate_it = ll_revalidate_it,
-#endif
.d_release = ll_release,
.d_delete = ll_ddelete,
#ifdef LUSTRE_KERNEL_VERSION