Whamcloud - gitweb
LU-3233 mdt: validate open handle cookies 38/6938/3
authorJohn L. Hammond <john.hammond@intel.com>
Wed, 10 Jul 2013 20:45:18 +0000 (15:45 -0500)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 19 Jul 2013 04:35:26 +0000 (04:35 +0000)
Add a const void *h_owner member to struct portals_handle. Add a const
void *owner parameter to class_handle2object() which must be matched
by the h_owner member of the handle in addition to the cookie.  Adjust
the callers of class_handle2object() accordingly, using NULL as the
argument to the owner parameter, except in the case of
mdt_handle2mfd() where we add an explicit mdt_export_data parameter
which we use as the owner when searching for a MFD. When allocating a
new MFD, pass a pointer to the mdt_export_data into mdt_mfd_new() and
store it in h_owner. This allows the MDT to validate that the client
has not sent the wrong open handle cookie, or sent the right cookie to
the wrong MDT.

Signed-off-by: John L. Hammond <john.hammond@intel.com>
Change-Id: I4c26504d808db0c27cfc2f8ebcf7e1fa19719170
Reviewed-on: http://review.whamcloud.com/6938
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Fan Yong <fan.yong@intel.com>
Reviewed-by: Mike Pershin <mike.pershin@intel.com>
lustre/include/lustre_handles.h
lustre/ldlm/ldlm_lock.c
lustre/lov/lov_internal.h
lustre/mdt/mdt_internal.h
lustre/mdt/mdt_open.c
lustre/mdt/mdt_reint.c
lustre/obdclass/genops.c
lustre/obdclass/lustre_handles.c

index 035ae06..496887e 100644 (file)
@@ -79,7 +79,8 @@ struct portals_handle_ops {
 struct portals_handle {
        cfs_list_t                      h_link;
        __u64                           h_cookie;
-       struct portals_handle_ops       *h_ops;
+       const void                     *h_owner;
+       struct portals_handle_ops      *h_ops;
 
        /* newly added fields to handle the RCU issue. -jxiong */
        cfs_rcu_head_t                  h_rcu;
@@ -96,7 +97,7 @@ void class_handle_hash(struct portals_handle *,
                       struct portals_handle_ops *ops);
 void class_handle_unhash(struct portals_handle *);
 void class_handle_hash_back(struct portals_handle *);
-void *class_handle2object(__u64 cookie);
+void *class_handle2object(__u64 cookie, const void *owner);
 void class_handle_free_cb(cfs_rcu_head_t *);
 int class_handle_init(void);
 void class_handle_cleanup(void);
index 1e17527..334de9c 100644 (file)
@@ -610,7 +610,7 @@ struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *handle,
 
         LASSERT(handle);
 
-        lock = class_handle2object(handle->cookie);
+       lock = class_handle2object(handle->cookie, NULL);
         if (lock == NULL)
                 RETURN(NULL);
 
index 767ca73..2c7f854 100644 (file)
@@ -105,10 +105,10 @@ static inline void lov_put_reqset(struct lov_request_set *set)
 }
 
 static inline struct lov_lock_handles *
-lov_handle2llh(struct lustre_handle *handle)
+lov_handle2llh(const struct lustre_handle *handle)
 {
-        LASSERT(handle != NULL);
-        return(class_handle2object(handle->cookie));
+       LASSERT(handle != NULL);
+       return class_handle2object(handle->cookie, NULL);
 }
 
 static inline void lov_llh_put(struct lov_lock_handles *llh)
index 8b204de..8f813d8 100644 (file)
@@ -760,8 +760,9 @@ void mdt_mfd_set_mode(struct mdt_file_data *mfd,
 int mdt_reint_open(struct mdt_thread_info *info,
                    struct mdt_lock_handle *lhc);
 
-struct mdt_file_data *mdt_handle2mfd(struct mdt_thread_info *,
-                                     const struct lustre_handle *);
+struct mdt_file_data *mdt_handle2mfd(struct mdt_export_data *med,
+                                    const struct lustre_handle *handle,
+                                    bool is_replay);
 
 enum {
         MDT_IOEPOCH_CLOSED  = 0,
@@ -782,7 +783,7 @@ int mdt_object_is_som_enabled(struct mdt_object *mo);
 int mdt_write_get(struct mdt_object *o);
 void mdt_write_put(struct mdt_object *o);
 int mdt_write_read(struct mdt_object *o);
-struct mdt_file_data *mdt_mfd_new(void);
+struct mdt_file_data *mdt_mfd_new(const struct mdt_export_data *med);
 int mdt_mfd_close(struct mdt_thread_info *info, struct mdt_file_data *mfd);
 void mdt_mfd_free(struct mdt_file_data *mfd);
 int mdt_close(struct mdt_thread_info *info);
index 6ac5eee..f408eba 100644 (file)
@@ -58,18 +58,20 @@ static struct portals_handle_ops mfd_handle_ops = {
 
 /* Create a new mdt_file_data struct, initialize it,
  * and insert it to global hash table */
-struct mdt_file_data *mdt_mfd_new(void)
+struct mdt_file_data *mdt_mfd_new(const struct mdt_export_data *med)
 {
-        struct mdt_file_data *mfd;
-        ENTRY;
+       struct mdt_file_data *mfd;
+       ENTRY;
 
-        OBD_ALLOC_PTR(mfd);
-        if (mfd != NULL) {
-                CFS_INIT_LIST_HEAD(&mfd->mfd_handle.h_link);
-                CFS_INIT_LIST_HEAD(&mfd->mfd_list);
+       OBD_ALLOC_PTR(mfd);
+       if (mfd != NULL) {
+               CFS_INIT_LIST_HEAD(&mfd->mfd_handle.h_link);
+               mfd->mfd_handle.h_owner = med;
+               CFS_INIT_LIST_HEAD(&mfd->mfd_list);
                class_handle_hash(&mfd->mfd_handle, &mfd_handle_ops);
-        }
-        RETURN(mfd);
+       }
+
+       RETURN(mfd);
 }
 
 /*
@@ -77,25 +79,25 @@ struct mdt_file_data *mdt_mfd_new(void)
  * In case of replay the handle is obsoleted
  * but mfd can be found in mfd list by that handle
  */
-struct mdt_file_data *mdt_handle2mfd(struct mdt_thread_info *info,
-                                     const struct lustre_handle *handle)
+struct mdt_file_data *mdt_handle2mfd(struct mdt_export_data *med,
+                                    const struct lustre_handle *handle,
+                                    bool is_replay)
 {
-        struct ptlrpc_request *req = mdt_info_req(info);
-        struct mdt_file_data  *mfd;
-        ENTRY;
+       struct mdt_file_data   *mfd;
+       ENTRY;
 
-        LASSERT(handle != NULL);
-        mfd = class_handle2object(handle->cookie);
-        /* during dw/setattr replay the mfd can be found by old handle */
-        if (mfd == NULL && req_is_replay(req)) {
-                struct mdt_export_data *med = &req->rq_export->exp_mdt_data;
-                cfs_list_for_each_entry(mfd, &med->med_open_head, mfd_list) {
-                        if (mfd->mfd_old_handle.cookie == handle->cookie)
-                                RETURN (mfd);
-                }
-                mfd = NULL;
-        }
-        RETURN (mfd);
+       LASSERT(handle != NULL);
+       mfd = class_handle2object(handle->cookie, med);
+       /* during dw/setattr replay the mfd can be found by old handle */
+       if (mfd == NULL && is_replay) {
+               cfs_list_for_each_entry(mfd, &med->med_open_head, mfd_list) {
+                       if (mfd->mfd_old_handle.cookie == handle->cookie)
+                               RETURN(mfd);
+               }
+               mfd = NULL;
+       }
+
+       RETURN(mfd);
 }
 
 /* free mfd */
@@ -725,76 +727,77 @@ static int mdt_mfd_open(struct mdt_thread_info *info, struct mdt_object *p,
         if (rc)
                 GOTO(err_out, rc);
 
-        mfd = mdt_mfd_new();
-        if (mfd != NULL) {
-                /*
-                 * Keep a reference on this object for this open, and is
-                 * released by mdt_mfd_close().
-                 */
-                mdt_object_get(info->mti_env, o);
+       mfd = mdt_mfd_new(med);
+       if (mfd == NULL)
+               GOTO(err_out, rc = -ENOMEM);
 
-                /*
-                 * @flags is always not zero. At least it should be FMODE_READ,
-                 * FMODE_WRITE or MDS_FMODE_EXEC.
-                 */
-                LASSERT(flags != 0);
-
-                /* Open handling. */
-                mdt_mfd_set_mode(mfd, flags);
-
-                mfd->mfd_object = o;
-                mfd->mfd_xid = req->rq_xid;
-
-                /* replay handle */
-                if (req_is_replay(req)) {
-                        struct mdt_file_data *old_mfd;
-                        /* Check wheather old cookie already exist in
-                         * the list, becasue when do recovery, client
-                         * might be disconnected from server, and
-                         * restart replay, so there maybe some orphan
-                         * mfd here, we should remove them */
-                        LASSERT(info->mti_rr.rr_handle != NULL);
-                        old_mfd = mdt_handle2mfd(info, info->mti_rr.rr_handle);
-                        if (old_mfd) {
-                                CDEBUG(D_HA, "del orph mfd %p fid=("DFID") "
-                                       "cookie=" LPX64"\n", mfd,
-                                       PFID(mdt_object_fid(mfd->mfd_object)),
-                                       info->mti_rr.rr_handle->cookie);
-                               spin_lock(&med->med_open_lock);
-                               class_handle_unhash(&old_mfd->mfd_handle);
-                               cfs_list_del_init(&old_mfd->mfd_list);
-                               spin_unlock(&med->med_open_lock);
-                                /* no attr update for that close */
-                                la->la_valid = 0;
-                                ma->ma_valid |= MA_FLAGS;
-                                ma->ma_attr_flags |= MDS_RECOV_OPEN;
-                                mdt_mfd_close(info, old_mfd);
-                                ma->ma_attr_flags &= ~MDS_RECOV_OPEN;
-                                ma->ma_valid &= ~MA_FLAGS;
-                        }
-                        CDEBUG(D_HA, "Store old cookie "LPX64" in new mfd\n",
-                               info->mti_rr.rr_handle->cookie);
-                        mfd->mfd_old_handle.cookie =
-                                                info->mti_rr.rr_handle->cookie;
-                }
-                repbody->handle.cookie = mfd->mfd_handle.h_cookie;
+       /*
+        * Keep a reference on this object for this open, and is
+        * released by mdt_mfd_close().
+        */
+       mdt_object_get(info->mti_env, o);
 
-                if (req->rq_export->exp_disconnected) {
-                       spin_lock(&med->med_open_lock);
-                       class_handle_unhash(&mfd->mfd_handle);
-                       cfs_list_del_init(&mfd->mfd_list);
-                       spin_unlock(&med->med_open_lock);
-                       mdt_mfd_close(info, mfd);
-               } else {
+       /*
+        * @flags is always not zero. At least it should be FMODE_READ,
+        * FMODE_WRITE or MDS_FMODE_EXEC.
+        */
+       LASSERT(flags != 0);
+
+       /* Open handling. */
+       mdt_mfd_set_mode(mfd, flags);
+
+       mfd->mfd_object = o;
+       mfd->mfd_xid = req->rq_xid;
+
+       /* replay handle */
+       if (req_is_replay(req)) {
+               struct mdt_file_data *old_mfd;
+               /* Check wheather old cookie already exist in
+                * the list, becasue when do recovery, client
+                * might be disconnected from server, and
+                * restart replay, so there maybe some orphan
+                * mfd here, we should remove them */
+               LASSERT(info->mti_rr.rr_handle != NULL);
+               old_mfd = mdt_handle2mfd(med, info->mti_rr.rr_handle, true);
+               if (old_mfd != NULL) {
+                       CDEBUG(D_HA, "delete orphan mfd = %p, fid = "DFID", "
+                              "cookie = "LPX64"\n", mfd,
+                              PFID(mdt_object_fid(mfd->mfd_object)),
+                              info->mti_rr.rr_handle->cookie);
                        spin_lock(&med->med_open_lock);
-                       cfs_list_add(&mfd->mfd_list, &med->med_open_head);
+                       class_handle_unhash(&old_mfd->mfd_handle);
+                       cfs_list_del_init(&old_mfd->mfd_list);
                        spin_unlock(&med->med_open_lock);
-                }
+                       /* no attr update for that close */
+                       la->la_valid = 0;
+                       ma->ma_valid |= MA_FLAGS;
+                       ma->ma_attr_flags |= MDS_RECOV_OPEN;
+                       mdt_mfd_close(info, old_mfd);
+                       ma->ma_attr_flags &= ~MDS_RECOV_OPEN;
+                       ma->ma_valid &= ~MA_FLAGS;
+               }
 
-                mdt_empty_transno(info, rc);
-        } else {
-                GOTO(err_out, rc = -ENOMEM);
-        }
+               CDEBUG(D_HA, "Store old cookie "LPX64" in new mfd\n",
+                      info->mti_rr.rr_handle->cookie);
+
+               mfd->mfd_old_handle.cookie = info->mti_rr.rr_handle->cookie;
+       }
+
+       repbody->handle.cookie = mfd->mfd_handle.h_cookie;
+
+       if (req->rq_export->exp_disconnected) {
+               spin_lock(&med->med_open_lock);
+               class_handle_unhash(&mfd->mfd_handle);
+               cfs_list_del_init(&mfd->mfd_list);
+               spin_unlock(&med->med_open_lock);
+               mdt_mfd_close(info, mfd);
+       } else {
+               spin_lock(&med->med_open_lock);
+               cfs_list_add(&mfd->mfd_list, &med->med_open_head);
+               spin_unlock(&med->med_open_lock);
+       }
+
+       mdt_empty_transno(info, rc);
 
         RETURN(rc);
 
@@ -1881,7 +1884,8 @@ int mdt_close(struct mdt_thread_info *info)
 
         med = &req->rq_export->exp_mdt_data;
        spin_lock(&med->med_open_lock);
-       mfd = mdt_handle2mfd(info, &info->mti_ioepoch->handle);
+       mfd = mdt_handle2mfd(med, &info->mti_ioepoch->handle,
+                            req_is_replay(req));
        if (mdt_mfd_closed(mfd)) {
                spin_unlock(&med->med_open_lock);
                CDEBUG(D_INODE, "no handle for file close: fid = "DFID
@@ -1956,7 +1960,8 @@ int mdt_done_writing(struct mdt_thread_info *info)
 
         med = &info->mti_exp->exp_mdt_data;
        spin_lock(&med->med_open_lock);
-       mfd = mdt_handle2mfd(info, &info->mti_ioepoch->handle);
+       mfd = mdt_handle2mfd(med, &info->mti_ioepoch->handle,
+                            req_is_replay(req));
        if (mfd == NULL) {
                spin_unlock(&med->med_open_lock);
                 CDEBUG(D_INODE, "no handle for done write: fid = "DFID
index f8ab022..c861792 100644 (file)
@@ -521,7 +521,7 @@ static int mdt_reint_setattr(struct mdt_thread_info *info,
                 if (rc)
                         GOTO(out_put, rc);
 
-                mfd = mdt_mfd_new();
+               mfd = mdt_mfd_new(med);
                 if (mfd == NULL) {
                         mdt_write_put(mo);
                         GOTO(out_put, rc = -ENOMEM);
@@ -549,7 +549,8 @@ static int mdt_reint_setattr(struct mdt_thread_info *info,
                 LASSERT(info->mti_ioepoch);
 
                spin_lock(&med->med_open_lock);
-               mfd = mdt_handle2mfd(info, &info->mti_ioepoch->handle);
+               mfd = mdt_handle2mfd(med, &info->mti_ioepoch->handle,
+                                    req_is_replay(req));
                if (mfd == NULL) {
                        spin_unlock(&med->med_open_lock);
                         CDEBUG(D_INODE, "no handle for file close: "
index f8c2b93..91b6262 100644 (file)
@@ -716,8 +716,8 @@ struct obd_export *class_conn2export(struct lustre_handle *conn)
         }
 
         CDEBUG(D_INFO, "looking for export cookie "LPX64"\n", conn->cookie);
-        export = class_handle2object(conn->cookie);
-        RETURN(export);
+       export = class_handle2object(conn->cookie, NULL);
+       RETURN(export);
 }
 EXPORT_SYMBOL(class_conn2export);
 
index 268545b..e090a8a 100644 (file)
@@ -164,7 +164,7 @@ void class_handle_hash_back(struct portals_handle *h)
 }
 EXPORT_SYMBOL(class_handle_hash_back);
 
-void *class_handle2object(__u64 cookie)
+void *class_handle2object(__u64 cookie, const void *owner)
 {
         struct handle_bucket *bucket;
         struct portals_handle *h;
@@ -179,7 +179,7 @@ void *class_handle2object(__u64 cookie)
 
         rcu_read_lock();
         list_for_each_entry_rcu(h, &bucket->head, h_link) {
-                if (h->h_cookie != cookie)
+               if (h->h_cookie != cookie || h->h_owner != owner)
                         continue;
 
                spin_lock(&h->h_lock);