Whamcloud - gitweb
LU-354 test: Change dev_set_rdonly() check to warning
[fs/lustre-release.git] / lustre / mdt / mdt_handler.c
index 021b681..55ab803 100644 (file)
@@ -28,9 +28,8 @@
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
- */
-/*
- * Copyright (c) 2011 Whamcloud, Inc.
+ *
+ * Copyright (c) 2011, 2012, Whamcloud, Inc.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -213,7 +212,7 @@ void mdt_lock_pdo_init(struct mdt_lock_handle *lh, ldlm_mode_t lm,
         lh->mlh_reg_mode = lm;
         lh->mlh_type = MDT_PDO_LOCK;
 
-        if (name != NULL) {
+        if (name != NULL && (name[0] != '\0')) {
                 LASSERT(namelen > 0);
                 lh->mlh_pdo_hash = full_name_hash(name, namelen);
         } else {
@@ -325,8 +324,7 @@ static int mdt_getstatus(struct mdt_thread_info *info)
                 struct mdt_object  *root;
                 struct lustre_capa *capa;
 
-                root = mdt_object_find(info->mti_env, mdt, &repbody->fid1,
-                                       MDT_OBJ_MUST_EXIST);
+                root = mdt_object_find(info->mti_env, mdt, &repbody->fid1);
                 if (IS_ERR(root))
                         RETURN(PTR_ERR(root));
 
@@ -817,6 +815,7 @@ static int mdt_raw_lookup(struct mdt_thread_info *info,
         LASSERT(!info->mti_cross_ref);
 
         /* Only got the fid of this obj by name */
+        fid_zero(child_fid);
         rc = mdo_lookup(info->mti_env, next, lname, child_fid,
                         &info->mti_spec);
 #if 0
@@ -897,8 +896,8 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info,
                         name = NULL;
                         CDEBUG(D_INODE, "getattr with lock for "DFID"/"DFID", "
                                "ldlm_rep = %p\n",
-                               PFID(mdt_object_fid(parent)), PFID(&reqbody->fid2),
-                               ldlm_rep);
+                               PFID(mdt_object_fid(parent)),
+                               PFID(&reqbody->fid2), ldlm_rep);
                 } else {
                         lname = mdt_name(info->mti_env, (char *)name, namelen);
                         CDEBUG(D_INODE, "getattr with lock for "DFID"/%s, "
@@ -969,21 +968,26 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info,
         }
 
         if (lname) {
-                /* step 1: lock parent */
-                lhp = &info->mti_lh[MDT_LH_PARENT];
-                mdt_lock_pdo_init(lhp, LCK_PR, name, namelen);
-                rc = mdt_object_lock(info, parent, lhp, MDS_INODELOCK_UPDATE,
-                                     MDT_LOCAL_LOCK);
-                if (unlikely(rc != 0))
-                        RETURN(rc);
+                /* step 1: lock parent only if parent is a directory */
+                if (S_ISDIR(lu_object_attr(&parent->mot_obj.mo_lu))) {
+                        lhp = &info->mti_lh[MDT_LH_PARENT];
+                        mdt_lock_pdo_init(lhp, LCK_PR, name, namelen);
+                        rc = mdt_object_lock(info, parent, lhp,
+                                             MDS_INODELOCK_UPDATE,
+                                             MDT_LOCAL_LOCK);
+                        if (unlikely(rc != 0))
+                                RETURN(rc);
+                }
 
                 /* step 2: lookup child's fid by name */
+                fid_zero(child_fid);
                 rc = mdo_lookup(info->mti_env, next, lname, child_fid,
                                 &info->mti_spec);
 
                 if (rc != 0) {
                         if (rc == -ENOENT)
-                                mdt_set_disposition(info, ldlm_rep, DISP_LOOKUP_NEG);
+                                mdt_set_disposition(info, ldlm_rep,
+                                                    DISP_LOOKUP_NEG);
                         GOTO(out_parent, rc);
                 } else
                         mdt_set_disposition(info, ldlm_rep, DISP_LOOKUP_POS);
@@ -996,8 +1000,7 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info,
          *step 3: find the child object by fid & lock it.
          *        regardless if it is local or remote.
          */
-        child = mdt_object_find(info->mti_env, info->mti_mdt, child_fid,
-                                MDT_OBJ_MUST_EXIST);
+        child = mdt_object_find(info->mti_env, info->mti_mdt, child_fid);
 
         if (unlikely(IS_ERR(child)))
                 GOTO(out_parent, rc = PTR_ERR(child));
@@ -1031,7 +1034,17 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info,
 relock:
                 OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_RESEND, obd_timeout*2);
                 mdt_lock_handle_init(lhc);
-                mdt_lock_reg_init(lhc, LCK_PR);
+                if (child_bits == MDS_INODELOCK_LAYOUT)
+                        mdt_lock_reg_init(lhc, LCK_CR);
+                else
+                        mdt_lock_reg_init(lhc, LCK_PR);
+
+                if (mdt_object_exists(child) == 0) {
+                        LU_OBJECT_DEBUG(D_INODE, info->mti_env,
+                                        &child->mot_obj.mo_lu,
+                                        "Object doesn't exist!\n");
+                        GOTO(out_child, rc = -ENOENT);
+                }
 
                 if (!(child_bits & MDS_INODELOCK_UPDATE)) {
                         struct md_attr *ma = &info->mti_attr;
@@ -1043,6 +1056,12 @@ relock:
                         if (unlikely(rc != 0))
                                 GOTO(out_child, rc);
 
+                        /* layout lock is used only on regular files */
+                        if ((ma->ma_valid & MA_INODE) &&
+                            (ma->ma_attr.la_valid & LA_MODE) &&
+                            !S_ISREG(ma->ma_attr.la_mode))
+                                child_bits &= ~MDS_INODELOCK_LAYOUT;
+
                         /* If the file has not been changed for some time, we
                          * return not only a LOOKUP lock, but also an UPDATE
                          * lock and this might save us RPC on later STAT. For
@@ -2061,8 +2080,7 @@ static struct mdt_object *mdt_obj(struct lu_object *o)
 
 struct mdt_object *mdt_object_find(const struct lu_env *env,
                                    struct mdt_device *d,
-                                   const struct lu_fid *f,
-                                   enum mdt_obj_exist check_exist)
+                                   const struct lu_fid *f)
 {
         struct lu_object *o;
         struct mdt_object *m;
@@ -2071,16 +2089,9 @@ struct mdt_object *mdt_object_find(const struct lu_env *env,
         CDEBUG(D_INFO, "Find object for "DFID"\n", PFID(f));
         o = lu_object_find(env, &d->mdt_md_dev.md_lu_dev, f, NULL);
         if (unlikely(IS_ERR(o)))
-                RETURN((struct mdt_object *)o);
+                m = (struct mdt_object *)o;
         else
                 m = mdt_obj(o);
-
-        if (check_exist == MDT_OBJ_MUST_EXIST && mdt_object_exists(m) == 0) {
-                mdt_object_put(env, m);
-                CERROR("%s: object "DFID" not found: rc = -2\n",
-                       mdt_obj_dev_name(m), PFID(f));
-                RETURN(ERR_PTR(-ENOENT));
-        }
         RETURN(m);
 }
 
@@ -2357,12 +2368,11 @@ void mdt_object_unlock(struct mdt_thread_info *info, struct mdt_object *o,
 struct mdt_object *mdt_object_find_lock(struct mdt_thread_info *info,
                                         const struct lu_fid *f,
                                         struct mdt_lock_handle *lh,
-                                        __u64 ibits,
-                                        enum mdt_obj_exist check_exist)
+                                        __u64 ibits)
 {
         struct mdt_object *o;
 
-        o = mdt_object_find(info->mti_env, info->mti_mdt, f, check_exist);
+        o = mdt_object_find(info->mti_env, info->mti_mdt, f);
         if (!IS_ERR(o)) {
                 int rc;
 
@@ -2466,11 +2476,10 @@ static int mdt_body_unpack(struct mdt_thread_info *info, __u32 flags)
                 mdt_set_capainfo(info, 0, &body->fid1,
                                  req_capsule_client_get(pill, &RMF_CAPA1));
 
-        obj = mdt_object_find(env, info->mti_mdt, &body->fid1,
-                              MDT_OBJ_MAY_NOT_EXIST);
+        obj = mdt_object_find(env, info->mti_mdt, &body->fid1);
         if (!IS_ERR(obj)) {
                 if ((flags & HABEO_CORPUS) &&
-                    mdt_object_exists(obj) == 0) {
+                    !mdt_object_exists(obj)) {
                         mdt_object_put(env, obj);
                         /* for capability renew ENOENT will be handled in
                          * mdt_renew_capa */
@@ -3082,6 +3091,7 @@ enum mdt_it_code {
         MDT_IT_UNLINK,
         MDT_IT_TRUNC,
         MDT_IT_GETXATTR,
+        MDT_IT_LAYOUT,
         MDT_IT_NR
 };
 
@@ -3152,6 +3162,11 @@ static struct mdt_it_flavor {
                 .it_fmt   = NULL,
                 .it_flags = 0,
                 .it_act   = NULL
+        },
+        [MDT_IT_LAYOUT] = {
+                .it_fmt   = &RQF_LDLM_INTENT_GETATTR,
+                .it_flags = HABEO_REFERO,
+                .it_act   = mdt_intent_getattr
         }
 };
 
@@ -3327,8 +3342,18 @@ static int mdt_intent_getattr(enum mdt_it_code opcode,
         case MDT_IT_GETATTR:
                 child_bits = MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE;
                 break;
+        case MDT_IT_LAYOUT: {
+                static int printed = 0;
+
+                if (!printed) {
+                        CERROR("layout lock not supported by this version\n");
+                        printed = 1;
+                }
+                GOTO(out_shrink, rc = -EINVAL);
+                break;
+        }
         default:
-                CERROR("Unhandled till now");
+                CERROR("Unsupported intent (%d)\n", opcode);
                 GOTO(out_shrink, rc = -EINVAL);
         }
 
@@ -3483,6 +3508,9 @@ static int mdt_intent_code(long itcode)
         case IT_GETXATTR:
                 rc = MDT_IT_GETXATTR;
                 break;
+        case IT_LAYOUT:
+                rc = MDT_IT_LAYOUT;
+                break;
         default:
                 CERROR("Unknown intent opcode: %ld\n", itcode);
                 rc = -EINVAL;
@@ -4795,8 +4823,8 @@ static struct lu_object *mdt_object_alloc(const struct lu_env *env,
                 lu_object_init(o, h, d);
                 lu_object_add_top(h, o);
                 o->lo_ops = &mdt_obj_ops;
-                cfs_sema_init(&mo->mot_ioepoch_sem, 1);
-                cfs_sema_init(&mo->mot_lov_sem, 1);
+                cfs_mutex_init(&mo->mot_ioepoch_mutex);
+                cfs_mutex_init(&mo->mot_lov_mutex);
                 RETURN(o);
         } else
                 RETURN(NULL);
@@ -5201,7 +5229,7 @@ static int mdt_init_export(struct obd_export *exp)
 
         CFS_INIT_LIST_HEAD(&med->med_open_head);
         cfs_spin_lock_init(&med->med_open_lock);
-        cfs_sema_init(&med->med_idmap_sem, 1);
+        cfs_mutex_init(&med->med_idmap_mutex);
         med->med_idmap = NULL;
         cfs_spin_lock(&exp->exp_lock);
         exp->exp_connecting = 1;
@@ -5371,16 +5399,19 @@ static int mdt_fid2path(const struct lu_env *env, struct mdt_device *mdt,
         if (!fid_is_sane(&fp->gf_fid))
                 RETURN(-EINVAL);
 
-        obj = mdt_object_find(env, mdt, &fp->gf_fid, MDT_OBJ_MUST_EXIST);
+        obj = mdt_object_find(env, mdt, &fp->gf_fid);
         if (obj == NULL || IS_ERR(obj)) {
-                CDEBUG(D_IOCTL, "%s: no object "DFID": %ld\n",
-                       mdt2obd_dev(mdt)->obd_name, PFID(&fp->gf_fid),
+                CDEBUG(D_IOCTL, "no object "DFID": %ld\n", PFID(&fp->gf_fid),
                        PTR_ERR(obj));
-                RETURN(obj == NULL ? -EINVAL : PTR_ERR(obj));
+                RETURN(-EINVAL);
         }
 
-        if (lu_object_exists(&obj->mot_obj.mo_lu) < 0) {
-                rc = -EREMOTE;
+        rc = lu_object_exists(&obj->mot_obj.mo_lu);
+        if (rc <= 0) {
+                if (rc == -1)
+                        rc = -EREMOTE;
+                else
+                        rc = -ENOENT;
                 mdt_object_put(env, obj);
                 CDEBUG(D_IOCTL, "nonlocal object "DFID": %d\n",
                        PFID(&fp->gf_fid), rc);
@@ -5478,13 +5509,9 @@ static int mdt_ioc_version_get(struct mdt_thread_info *mti, void *karg)
         lh = &mti->mti_lh[MDT_LH_PARENT];
         mdt_lock_reg_init(lh, LCK_CR);
 
-        obj = mdt_object_find_lock(mti, fid, lh, MDS_INODELOCK_UPDATE,
-                                   MDT_OBJ_MUST_EXIST);
-        if (IS_ERR(obj)) {
-                if (PTR_ERR(obj) == -ENOENT)
-                        *(__u64 *)data->ioc_inlbuf2 = ENOENT_VERSION;
+        obj = mdt_object_find_lock(mti, fid, lh, MDS_INODELOCK_UPDATE);
+        if (IS_ERR(obj))
                 RETURN(PTR_ERR(obj));
-        }
 
         rc = mdt_object_exists(obj);
         if (rc < 0) {
@@ -5494,13 +5521,15 @@ static int mdt_ioc_version_get(struct mdt_thread_info *mti, void *karg)
                  * fid, this is error to find remote object here
                  */
                 CERROR("nonlocal object "DFID"\n", PFID(fid));
-        } else if (rc > 0) {
+        } else if (rc == 0) {
+                *(__u64 *)data->ioc_inlbuf2 = ENOENT_VERSION;
+                rc = -ENOENT;
+        } else {
                 version = dt_version_get(mti->mti_env, mdt_obj2dt(obj));
                *(__u64 *)data->ioc_inlbuf2 = version;
                 rc = 0;
         }
         mdt_object_unlock_put(mti, obj, lh, 1);
-
         RETURN(rc);
 }
 
@@ -5525,7 +5554,7 @@ static int mdt_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                 rc = mdt_device_sync(&env, mdt);
                 break;
         case OBD_IOC_SET_READONLY:
-                dt->dd_ops->dt_ro(&env, dt);
+                rc = dt->dd_ops->dt_ro(&env, dt);
                 break;
         case OBD_IOC_ABORT_RECOVERY:
                 CERROR("Aborting recovery for device %s\n", obd->obd_name);