Whamcloud - gitweb
b=3643
[fs/lustre-release.git] / lustre / llite / namei.c
index e768933..61cf15b 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/obd_support.h>
 #include <linux/lustre_lite.h>
 #include <linux/lustre_dlm.h>
+#include <linux/lustre_version.h>
 #include "llite_internal.h"
 
 /* methods */
@@ -70,16 +71,25 @@ static int ll_test_inode(struct inode *inode, void *opaque)
                 last_ino = md->body->ino;
                 last_gen = md->body->generation;
                 CDEBUG(D_VFSTRACE,
-                       "comparing inode %p ino %lu/%u to body %u/%u\n",
+                       "comparing inode %p ino %lu/%u/%u to body %u/%u/%u\n",
                        inode, inode->i_ino, inode->i_generation,
-                       md->body->ino, md->body->generation);
+                       ll_i2info(inode)->lli_mds,
+                       md->body->ino, md->body->generation,
+                       md->body->mds);
         }
 
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+        if (inode->i_ino != md->body->ino)
+                return 0;
+#endif
         if (inode->i_generation != md->body->generation)
                 return 0;
 
+        if (ll_i2info(inode)->lli_mds != md->body->mds)
+                return 0;
+
         /* Apply the attributes in 'opaque' to this inode */
-        ll_update_inode(inode, md->body, md->lsm);
+        ll_update_inode(inode, md);
         return 1;
 }
 
@@ -103,6 +113,7 @@ int ll_set_inode(struct inode *inode, void *opaque)
         ll_read_inode2(inode, opaque);
         return 0;
 }
+
 struct inode *ll_iget(struct super_block *sb, ino_t hash,
                       struct lustre_md *md)
 {
@@ -152,28 +163,42 @@ int ll_mdc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
                 break;
         case LDLM_CB_CANCELING: {
                 struct inode *inode = ll_inode_from_lock(lock);
+                __u64 bits = lock->l_policy_data.l_inodebits.bits;
 
-                /* Invalidate all dentries associated with this inode */
+                /* For lookup locks: Invalidate all dentries associated with
+                   this inode, for UPDATE locks - invalidate directory pages */
                 if (inode == NULL)
                         break;
 
-                clear_bit(LLI_F_HAVE_MDS_SIZE_LOCK,
-                          &(ll_i2info(inode)->lli_flags));
+                if (bits & MDS_INODELOCK_UPDATE)
+                        clear_bit(LLI_F_HAVE_MDS_SIZE_LOCK,
+                                  &(ll_i2info(inode)->lli_flags));
+
 
                 if (lock->l_resource->lr_name.name[0] != inode->i_ino ||
                     lock->l_resource->lr_name.name[1] != inode->i_generation) {
                         LDLM_ERROR(lock, "data mismatch with ino %lu/%u",
                                    inode->i_ino, inode->i_generation);
                 }
-                if (S_ISDIR(inode->i_mode)) {
+
+                /* If lookup lock is cancelled, we just drop the dentry and
+                   this will cause us to reget data from MDS when we'd want to
+                   access this dentry/inode again. If this is lock on
+                   other parts of inode that is cancelled, we do not need to do
+                   much (but need to discard data from readdir, if any), since
+                   abscence of lock will cause ll_revalidate_it (called from
+                   stat() and similar functions) to renew the data anyway */
+                if (S_ISDIR(inode->i_mode) &&
+                    (bits & MDS_INODELOCK_UPDATE)) {
                         CDEBUG(D_INODE, "invalidating inode %lu\n",
                                inode->i_ino);
 
-                        ll_invalidate_inode_pages(inode);
+                        truncate_inode_pages(inode->i_mapping, 0);
                 }
 
                 if (inode->i_sb->s_root &&
-                    inode != inode->i_sb->s_root->d_inode)
+                    inode != inode->i_sb->s_root->d_inode &&
+                    (bits & MDS_INODELOCK_LOOKUP))
                         ll_unhash_aliases(inode);
                 iput(inode);
                 break;
@@ -192,29 +217,11 @@ int ll_mdc_cancel_unused(struct lustre_handle *conn, struct inode *inode,
                 { .name = {inode->i_ino, inode->i_generation} };
         struct obd_device *obddev = class_conn2obd(conn);
         ENTRY;
+        
         RETURN(ldlm_cli_cancel_unused(obddev->obd_namespace, &res_id, flags,
                                       opaque));
 }
 
-
-void ll_prepare_mdc_op_data(struct mdc_op_data *data, struct inode *i1,
-                            struct inode *i2, const char *name, int namelen,
-                            int mode)
-{
-        LASSERT(i1);
-
-        ll_i2uctxt(&data->ctxt, i1, i2);
-        ll_inode2fid(&data->fid1, i1);
-
-        if (i2)
-                ll_inode2fid(&data->fid2, i2);
-
-        data->name = name;
-        data->namelen = namelen;
-        data->create_mode = mode;
-        data->mod_time = LTIME_S(CURRENT_TIME);
-}
-
 /* Search "inode"'s alias list for a dentry that has the same name and parent as
  * de.  If found, return it.  If not found, return de. */
 struct dentry *ll_find_alias(struct inode *inode, struct dentry *de)
@@ -250,6 +257,9 @@ struct dentry *ll_find_alias(struct inode *inode, struct dentry *de)
                 atomic_inc(&dentry->d_count);
                 iput(inode);
                 dentry->d_flags &= ~DCACHE_LUSTRE_INVALID;
+                CDEBUG(D_DENTRY, "alias 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));
                 return dentry;
         }
 
@@ -274,28 +284,33 @@ static int lookup_it_finish(struct ptlrpc_request *request, int offset,
         if (!it_disposition(it, DISP_LOOKUP_NEG)) {
                 ENTRY;
 
-                rc = ll_prep_inode(sbi->ll_osc_exp, &inode, request, offset,
-                                   dentry->d_sb);
+                rc = ll_prep_inode(sbi->ll_osc_exp, sbi->ll_mdc_exp,
+                                   &inode, request, offset, dentry->d_sb);
                 if (rc)
                         RETURN(rc);
 
+                CDEBUG(D_DLMTRACE, "setting l_data to inode %p (%lu/%u)\n",
+                       inode, inode->i_ino, inode->i_generation);
+                mdc_set_lock_data(NULL, &it->d.lustre.it_lock_handle, inode);
+
                 /* If this is a stat, get the authoritative file size */
                 if (it->it_op == IT_GETATTR && S_ISREG(inode->i_mode) &&
                     ll_i2info(inode)->lli_smd != NULL) {
-                        struct ldlm_extent extent = {0, OBD_OBJECT_EOF};
-                        struct lustre_handle lockh = {0};
                         struct lov_stripe_md *lsm = ll_i2info(inode)->lli_smd;
+                        struct ost_lvb lvb;
                         ldlm_error_t rc;
 
                         LASSERT(lsm->lsm_object_id != 0);
 
-                        rc = ll_extent_lock(NULL, inode, lsm, LCK_PR, &extent,
-                                            &lockh);
-                        if (rc != ELDLM_OK) {
+                        /* bug 2334: drop MDS lock before acquiring OST lock */
+                        ll_intent_drop_lock(it);
+
+                        rc = ll_glimpse_size(inode, &lvb);
+                        if (rc) {
                                 iput(inode);
-                                RETURN(-EIO);
+                                RETURN(rc);
                         }
-                        ll_extent_unlock(NULL, inode, lsm, LCK_PR, &lockh);
+                        inode->i_size = lvb.lvb_size;
                 }
 
                 dentry = *de = ll_find_alias(inode, dentry);
@@ -306,14 +321,16 @@ static int lookup_it_finish(struct ptlrpc_request *request, int offset,
         dentry->d_op = &ll_d_ops;
         ll_set_dd(dentry);
 
-        if (dentry == saved)
+        if (dentry == saved) {
                 d_add(dentry, inode);
+        }
 
         RETURN(0);
 }
 
 
 static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
+                                   struct nameidata *nd,
                                    struct lookup_intent *it, int flags)
 {
         struct dentry *save = dentry, *retval;
@@ -335,6 +352,9 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
         if (d_mountpoint(dentry))
                 CERROR("Tell Peter, lookup on mtpt, it %s\n", LL_IT2STR(it));
 
+        if (nd != NULL)
+                nd->mnt->mnt_last_used = jiffies;
+
         ll_frob_intent(&it, &lookup_it);
 
         icbd.icbd_childp = &dentry;
@@ -342,9 +362,9 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
         ll_inode2fid(&pfid, parent);
         ll_i2uctxt(&ctxt, parent, NULL);
 
-        rc = mdc_intent_lock(ll_i2mdcexp(parent), &ctxt, &pfid,
-                             dentry->d_name.name, dentry->d_name.len, NULL, 0,
-                             NULL, it, flags, &req, ll_mdc_blocking_ast);
+        rc = md_intent_lock(ll_i2mdcexp(parent), &ctxt, &pfid,
+                            dentry->d_name.name, dentry->d_name.len, NULL, 0,
+                            NULL, it, flags, &req, ll_mdc_blocking_ast);
         if (rc < 0)
                 GOTO(out, retval = ERR_PTR(rc));
 
@@ -356,6 +376,12 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
 
         ll_lookup_finish_locks(it, dentry);
 
+        if (nd &&
+            dentry->d_inode != NULL && dentry->d_inode->i_mode & S_ISUID &&
+            S_ISDIR(dentry->d_inode->i_mode) &&
+            (flags & LOOKUP_CONTINUE || (it->it_op & (IT_CHDIR | IT_OPEN))))
+                ll_dir_process_mount_object(dentry, nd->mnt);
+
         if (dentry == save)
                 GOTO(out, retval = NULL);
         else
@@ -363,6 +389,20 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
  out:
         if (req)
                 ptlrpc_req_finished(req);
+        if (dentry->d_inode)
+                CDEBUG(D_INODE, "lookup 0x%p in %lu/%lu: %*s -> %lu/%lu\n",
+                                dentry,
+                                (unsigned long) parent->i_ino,
+                                (unsigned long) parent->i_generation,
+                                dentry->d_name.len, dentry->d_name.name,
+                                (unsigned long) dentry->d_inode->i_ino,
+                                (unsigned long) dentry->d_inode->i_generation);
+        else
+                CDEBUG(D_INODE, "lookup 0x%p in %lu/%lu: %*s -> ??\n",
+                                dentry,
+                                (unsigned long) parent->i_ino,
+                                (unsigned long) parent->i_generation,
+                                dentry->d_name.len, dentry->d_name.name);
         return retval;
 }
 
@@ -373,10 +413,10 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry,
         struct dentry *de;
         ENTRY;
 
-        if (nd->flags & LOOKUP_LAST && !(nd->flags & LOOKUP_LINK_NOTLAST))
-                de = ll_lookup_it(parent, dentry, &nd->intent, nd->flags);
+        if (nd && nd->flags & LOOKUP_LAST && !(nd->flags & LOOKUP_LINK_NOTLAST))
+                de = ll_lookup_it(parent, dentry, nd, &nd->intent, nd->flags);
         else
-                de = ll_lookup_it(parent, dentry, NULL, 0);
+                de = ll_lookup_it(parent, dentry, nd, NULL, 0);
 
         RETURN(de);
 }
@@ -397,7 +437,8 @@ static struct inode *ll_create_node(struct inode *dir, const char *name,
         LASSERT(it && it->d.lustre.it_disposition);
 
         request = it->d.lustre.it_data;
-        rc = ll_prep_inode(sbi->ll_osc_exp, &inode, request, 1, dir->i_sb);
+        rc = ll_prep_inode(sbi->ll_osc_exp, sbi->ll_mdc_exp,
+                           &inode, request, 1, dir->i_sb);
         if (rc)
                 GOTO(out, inode = ERR_PTR(rc));
 
@@ -408,7 +449,7 @@ static struct inode *ll_create_node(struct inode *dir, const char *name,
          * stuff it in the lock. */
         CDEBUG(D_DLMTRACE, "setting l_ast_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);
+        mdc_set_lock_data(NULL, &it->d.lustre.it_lock_handle, inode);
         EXIT;
  out:
         ptlrpc_req_finished(request);
@@ -434,6 +475,7 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode,
 {
         struct inode *inode;
         struct ptlrpc_request *request = it->d.lustre.it_data;
+        struct obd_export *mdc_exp = ll_i2mdcexp(dir); 
         int rc = 0;
         ENTRY;
 
@@ -445,7 +487,7 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode,
         if (rc)
                 RETURN(rc);
 
-        mdc_store_inode_generation(request, 2, 1);
+        mdc_store_inode_generation(mdc_exp, request, 2, 1);
         inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
                                NULL, 0, mode, 0, it);
         if (IS_ERR(inode)) {
@@ -491,9 +533,8 @@ static int ll_mknod_raw(struct nameidata *nd, int mode, dev_t rdev)
         case S_IFIFO:
         case S_IFSOCK:
                 ll_prepare_mdc_op_data(&op_data, dir, NULL, name, len, 0);
-                err = mdc_create(sbi->ll_mdc_exp, &op_data, NULL, 0, mode,
-                                 current->fsuid, current->fsgid,
-                                 rdev, &request);
+                err = md_create(sbi->ll_mdc_exp, &op_data, NULL, 0, mode,
+                                current->fsuid, current->fsgid, rdev, &request);
                 ptlrpc_req_finished(request);
                 break;
         case S_IFDIR:
@@ -534,11 +575,10 @@ static int ll_mknod(struct inode *dir, struct dentry *child, int mode,
         case S_IFIFO:
         case S_IFSOCK:
                 ll_prepare_mdc_op_data(&op_data, dir, NULL, name, len, 0);
-                err = mdc_create(sbi->ll_mdc_exp, &op_data, NULL, 0, mode,
-                                 current->fsuid, current->fsgid,
-                                 rdev, &request);
-                err = ll_prep_inode(sbi->ll_osc_exp, &inode, request, 0,
-                                    child->d_sb);
+                err = md_create(sbi->ll_mdc_exp, &op_data, NULL, 0, mode,
+                                current->fsuid, current->fsgid, rdev, &request);
+                err = ll_prep_inode(sbi->ll_osc_exp, sbi->ll_mdc_exp,
+                                    &inode, request, 0, child->d_sb);
                 if (err)
                         GOTO(out_err, err);
                 break;
@@ -573,9 +613,9 @@ static int ll_symlink_raw(struct nameidata *nd, const char *tgt)
                 RETURN(err);
 
         ll_prepare_mdc_op_data(&op_data, dir, NULL, name, len, 0);
-        err = mdc_create(sbi->ll_mdc_exp, &op_data,
-                         tgt, strlen(tgt) + 1, S_IFLNK | S_IRWXUGO,
-                         current->fsuid, current->fsgid, 0, &request);
+        err = md_create(sbi->ll_mdc_exp, &op_data,
+                        tgt, strlen(tgt) + 1, S_IFLNK | S_IRWXUGO,
+                        current->fsuid, current->fsgid, 0, &request);
         ptlrpc_req_finished(request);
         RETURN(err);
 }
@@ -597,7 +637,7 @@ static int ll_link_raw(struct nameidata *srcnd, struct nameidata *tgtnd)
                dir->i_ino, dir->i_generation, dir, name);
 
         ll_prepare_mdc_op_data(&op_data, src, dir, name, len, 0);
-        err = mdc_link(sbi->ll_mdc_exp, &op_data, &request);
+        err = md_link(sbi->ll_mdc_exp, &op_data, &request);
         ptlrpc_req_finished(request);
 
         RETURN(err);
@@ -617,13 +657,10 @@ static int ll_mkdir_raw(struct nameidata *nd, int mode)
         CDEBUG(D_VFSTRACE, "VFS Op:name=%s,dir=%lu/%u(%p)\n",
                name, dir->i_ino, dir->i_generation, dir);
 
-        if (dir->i_nlink >= EXT3_LINK_MAX)
-                RETURN(err);
-
         mode = (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask) | S_IFDIR;
         ll_prepare_mdc_op_data(&op_data, dir, NULL, name, len, 0);
-        err = mdc_create(sbi->ll_mdc_exp, &op_data, NULL, 0, mode,
-                         current->fsuid, current->fsgid, 0, &request);
+        err = md_create(sbi->ll_mdc_exp, &op_data, NULL, 0, mode,
+                        current->fsuid, current->fsgid, 0, &request);
         ptlrpc_req_finished(request);
         RETURN(err);
 }
@@ -641,7 +678,7 @@ static int ll_rmdir_raw(struct nameidata *nd)
                name, dir->i_ino, dir->i_generation, dir);
 
         ll_prepare_mdc_op_data(&op_data, dir, NULL, name, len, S_IFDIR);
-        rc = mdc_unlink(ll_i2sbi(dir)->ll_mdc_exp, &op_data, &request);
+        rc = md_unlink(ll_i2sbi(dir)->ll_mdc_exp, &op_data, &request);
         ptlrpc_req_finished(request);
         RETURN(rc);
 }
@@ -690,8 +727,9 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
                 GOTO(out_free_memmd, rc = -ENOMEM);
 
         oa->o_id = lsm->lsm_object_id;
+        oa->o_gr = lsm->lsm_object_gr;
         oa->o_mode = body->mode & S_IFMT;
-        oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE;
+        oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLGROUP;
 
         if (body->valid & OBD_MD_FLCOOKIE) {
                 oa->o_valid |= OBD_MD_FLCOOKIE;
@@ -729,7 +767,7 @@ static int ll_unlink_raw(struct nameidata *nd)
                name, dir->i_ino, dir->i_generation, dir);
 
         ll_prepare_mdc_op_data(&op_data, dir, NULL, name, len, 0);
-        rc = mdc_unlink(ll_i2sbi(dir)->ll_mdc_exp, &op_data, &request);
+        rc = md_unlink(ll_i2sbi(dir)->ll_mdc_exp, &op_data, &request);
         if (rc)
                 GOTO(out, rc);
 
@@ -757,8 +795,8 @@ static int ll_rename_raw(struct nameidata *oldnd, struct nameidata *newnd)
                src, newname, tgt->i_ino, tgt->i_generation, tgt);
 
         ll_prepare_mdc_op_data(&op_data, src, tgt, NULL, 0, 0);
-        err = mdc_rename(sbi->ll_mdc_exp, &op_data,
-                         oldname, oldlen, newname, newlen, &request);
+        err = md_rename(sbi->ll_mdc_exp, &op_data,
+                        oldname, oldlen, newname, newlen, &request);
         if (!err) {
                 err = ll_objects_destroy(request, src);
         }
@@ -769,23 +807,23 @@ static int ll_rename_raw(struct nameidata *oldnd, struct nameidata *newnd)
 }
 
 struct inode_operations ll_dir_inode_operations = {
-        link_raw:           ll_link_raw,
-        unlink_raw:         ll_unlink_raw,
-        symlink_raw:        ll_symlink_raw,
-        mkdir_raw:          ll_mkdir_raw,
-        rmdir_raw:          ll_rmdir_raw,
-        mknod_raw:          ll_mknod_raw,
-        mknod:              ll_mknod,
-        rename_raw:         ll_rename_raw,
-        setattr:         ll_setattr,
-        setattr_raw:     ll_setattr_raw,
+        .link_raw           = ll_link_raw,
+        .unlink_raw         = ll_unlink_raw,
+        .symlink_raw        = ll_symlink_raw,
+        .mkdir_raw          = ll_mkdir_raw,
+        .rmdir_raw          = ll_rmdir_raw,
+        .mknod_raw          = ll_mknod_raw,
+        .mknod              = ll_mknod,
+        .rename_raw         = ll_rename_raw,
+        .setattr            = ll_setattr,
+        .setattr_raw        = ll_setattr_raw,
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-        create_it:          ll_create_it,
-        lookup_it:            ll_lookup_it,
-        revalidate_it:      ll_inode_revalidate_it,
+        .create_it          = ll_create_it,
+        .lookup_it          = ll_lookup_it,
+        .revalidate_it      = ll_inode_revalidate_it,
 #else
-        lookup:          ll_lookup_nd,
-        create:          ll_create_nd,
-        getattr_it:         ll_getattr,
+        .lookup             = ll_lookup_nd,
+        .create             = ll_create_nd,
+        .getattr_it         = ll_getattr,
 #endif
 };