Whamcloud - gitweb
LU-13508 mdc: chlg device could be used after free
[fs/lustre-release.git] / lustre / mdc / mdc_request.c
index 93b2e63..82d1b5e 100644 (file)
@@ -39,9 +39,9 @@
 #include <linux/user_namespace.h>
 #include <linux/utsname.h>
 #include <linux/delay.h>
-#ifdef HAVE_UIDGID_HEADER
-# include <linux/uidgid.h>
-#endif
+#include <linux/uidgid.h>
+#include <linux/device.h>
+#include <linux/xarray.h>
 
 #include <lustre_errno.h>
 
@@ -49,6 +49,7 @@
 #include <llog_swab.h>
 #include <lprocfs_status.h>
 #include <lustre_acl.h>
+#include <lustre_compat.h>
 #include <lustre_fid.h>
 #include <uapi/linux/lustre/lustre_ioctl.h>
 #include <lustre_kernelcomm.h>
@@ -240,8 +241,9 @@ again:
        rc = mdc_getattr_common(exp, req);
        if (rc) {
                if (rc == -ERANGE) {
-                       acl_bufsize = MIN(imp->imp_connect_data.ocd_max_easize,
-                                         XATTR_SIZE_MAX);
+                       acl_bufsize = min_t(__u32,
+                                           imp->imp_connect_data.ocd_max_easize,
+                                           XATTR_SIZE_MAX);
                        mdc_reset_acl_req(req);
                        goto again;
                }
@@ -295,8 +297,9 @@ again:
        rc = mdc_getattr_common(exp, req);
        if (rc) {
                if (rc == -ERANGE) {
-                       acl_bufsize = MIN(imp->imp_connect_data.ocd_max_easize,
-                                         XATTR_SIZE_MAX);
+                       acl_bufsize = min_t(__u32,
+                                           imp->imp_connect_data.ocd_max_easize,
+                                           XATTR_SIZE_MAX);
                        mdc_reset_acl_req(req);
                        goto again;
                }
@@ -377,8 +380,8 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
        if (opcode == MDS_REINT) {
                struct mdt_rec_setxattr *rec;
 
-               CLASSERT(sizeof(struct mdt_rec_setxattr) ==
-                        sizeof(struct mdt_rec_reint));
+               BUILD_BUG_ON(sizeof(struct mdt_rec_setxattr) !=
+                            sizeof(struct mdt_rec_reint));
                rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT);
                rec->sx_opcode = REINT_SETXATTR;
                rec->sx_fsuid  = from_kuid(&init_user_ns, current_fsuid());
@@ -413,12 +416,12 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
 
         /* make rpc */
         if (opcode == MDS_REINT)
-               mdc_get_mod_rpc_slot(req, NULL);
+               ptlrpc_get_mod_rpc_slot(req);
 
         rc = ptlrpc_queue_wait(req);
 
        if (opcode == MDS_REINT)
-               mdc_put_mod_rpc_slot(req, NULL);
+               ptlrpc_put_mod_rpc_slot(req);
 
         if (rc)
                 ptlrpc_req_finished(req);
@@ -980,9 +983,9 @@ static int mdc_close(struct obd_export *exp, struct md_op_data *op_data,
 
         ptlrpc_request_set_replen(req);
 
-       mdc_get_mod_rpc_slot(req, NULL);
+       ptlrpc_get_mod_rpc_slot(req);
        rc = ptlrpc_queue_wait(req);
-       mdc_put_mod_rpc_slot(req, NULL);
+       ptlrpc_put_mod_rpc_slot(req);
 
        if (req->rq_repmsg == NULL) {
                CDEBUG(D_RPCTRACE, "request %p failed to send: rc = %d\n", req,
@@ -1057,7 +1060,7 @@ restart_bulk:
        ptlrpc_at_set_req_timeout(req);
 
        desc = ptlrpc_prep_bulk_imp(req, npages, 1,
-                                   PTLRPC_BULK_PUT_SINK | PTLRPC_BULK_BUF_KIOV,
+                                   PTLRPC_BULK_PUT_SINK,
                                    MDS_BULK_PORTAL,
                                    &ptlrpc_bulk_kiov_pin_ops);
        if (desc == NULL) {
@@ -1085,7 +1088,12 @@ restart_bulk:
                               exp->exp_obd->obd_name, -EIO);
                        RETURN(-EIO);
                }
-               ssleep(resends);
+
+               /* If a signal interrupts then the timeout returned will
+                * not be zero. In that case return -EINTR
+                */
+               if (msleep_interruptible(resends * 1000))
+                       RETURN(-EINTR);
 
                goto restart_bulk;
        }
@@ -1133,14 +1141,14 @@ static struct page *mdc_page_locate(struct address_space *mapping, __u64 *hash,
        unsigned long flags;
        int found;
 
-       xa_lock_irqsave(&mapping->i_pages, flags);
+       ll_xa_lock_irqsave(&mapping->i_pages, flags);
        found = radix_tree_gang_lookup(&mapping->page_tree,
                                       (void **)&page, offset, 1);
-       if (found > 0 && !radix_tree_exceptional_entry(page)) {
+       if (found > 0 && !ll_xa_is_value(page)) {
                struct lu_dirpage *dp;
 
                get_page(page);
-               xa_unlock_irqrestore(&mapping->i_pages, flags);
+               ll_xa_unlock_irqrestore(&mapping->i_pages, flags);
                /*
                 * In contrast to find_lock_page() we are sure that directory
                 * page cannot be truncated (while DLM lock is held) and,
@@ -1189,7 +1197,7 @@ static struct page *mdc_page_locate(struct address_space *mapping, __u64 *hash,
                        page = ERR_PTR(-EIO);
                }
        } else {
-               xa_unlock_irqrestore(&mapping->i_pages, flags);
+               ll_xa_unlock_irqrestore(&mapping->i_pages, flags);
                page = NULL;
        }
        return page;
@@ -1339,7 +1347,7 @@ static int mdc_read_page_remote(void *data, struct page *page0)
        fid = &op_data->op_fid1;
        LASSERT(inode != NULL);
 
-       OBD_ALLOC(page_pool, sizeof(page_pool[0]) * max_pages);
+       OBD_ALLOC_PTR_ARRAY(page_pool, max_pages);
        if (page_pool != NULL) {
                page_pool[0] = page0;
        } else {
@@ -1348,8 +1356,7 @@ static int mdc_read_page_remote(void *data, struct page *page0)
        }
 
        for (npages = 1; npages < max_pages; npages++) {
-               page = __page_cache_alloc(mapping_gfp_mask(inode->i_mapping)
-                                         | __GFP_COLD);
+               page = page_cache_alloc(inode->i_mapping);
                if (page == NULL)
                        break;
                page_pool[npages] = page;
@@ -1409,7 +1416,7 @@ static int mdc_read_page_remote(void *data, struct page *page0)
        }
 
        if (page_pool != &page0)
-               OBD_FREE(page_pool, sizeof(page_pool[0]) * max_pages);
+               OBD_FREE_PTR_ARRAY(page_pool, max_pages);
 
        RETURN(rc);
 }
@@ -1757,9 +1764,9 @@ static int mdc_ioc_hsm_progress(struct obd_export *exp,
 
        ptlrpc_request_set_replen(req);
 
-       mdc_get_mod_rpc_slot(req, NULL);
+       ptlrpc_get_mod_rpc_slot(req);
        rc = ptlrpc_queue_wait(req);
-       mdc_put_mod_rpc_slot(req, NULL);
+       ptlrpc_put_mod_rpc_slot(req);
 
        GOTO(out, rc);
 out:
@@ -1815,6 +1822,7 @@ static int mdc_ioc_hsm_ct_register(struct obd_import *imp, __u32 archive_count,
                *archive_array = archive_count;
 
        ptlrpc_request_set_replen(req);
+       req->rq_no_resend = 1;
 
        rc = mdc_queue_wait(req);
        GOTO(out, rc);
@@ -1960,9 +1968,9 @@ static int mdc_ioc_hsm_state_set(struct obd_export *exp,
 
        ptlrpc_request_set_replen(req);
 
-       mdc_get_mod_rpc_slot(req, NULL);
+       ptlrpc_get_mod_rpc_slot(req);
        rc = ptlrpc_queue_wait(req);
-       mdc_put_mod_rpc_slot(req, NULL);
+       ptlrpc_put_mod_rpc_slot(req);
 
        GOTO(out, rc);
 out:
@@ -2020,9 +2028,9 @@ static int mdc_ioc_hsm_request(struct obd_export *exp,
 
        ptlrpc_request_set_replen(req);
 
-       mdc_get_mod_rpc_slot(req, NULL);
+       ptlrpc_get_mod_rpc_slot(req);
        rc = ptlrpc_queue_wait(req);
-       mdc_put_mod_rpc_slot(req, NULL);
+       ptlrpc_put_mod_rpc_slot(req);
 
        GOTO(out, rc);
 
@@ -2037,34 +2045,51 @@ static int mdc_ioc_hsm_ct_start(struct obd_export *exp,
 static int mdc_quotactl(struct obd_device *unused, struct obd_export *exp,
                         struct obd_quotactl *oqctl)
 {
-       struct ptlrpc_request   *req;
-       struct obd_quotactl     *oqc;
-       int                      rc;
+       struct ptlrpc_request *req;
+       struct obd_quotactl *oqc;
+       int rc;
        ENTRY;
 
-       req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
-                                       &RQF_MDS_QUOTACTL, LUSTRE_MDS_VERSION,
-                                       MDS_QUOTACTL);
+       req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_QUOTACTL);
        if (req == NULL)
                RETURN(-ENOMEM);
 
+
+       if (LUSTRE_Q_CMD_IS_POOL(oqctl->qc_cmd))
+               req_capsule_set_size(&req->rq_pill,
+                                    &RMF_OBD_QUOTACTL,
+                                    RCL_CLIENT,
+                                    sizeof(*oqc) + LOV_MAXPOOLNAME + 1);
+
+       rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION,
+                                MDS_QUOTACTL);
+       if (rc) {
+               ptlrpc_request_free(req);
+               RETURN(rc);
+       }
+
        oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
-       *oqc = *oqctl;
+       QCTL_COPY(oqc, oqctl);
 
        ptlrpc_request_set_replen(req);
        ptlrpc_at_set_req_timeout(req);
 
        rc = ptlrpc_queue_wait(req);
-       if (rc)
-               CERROR("ptlrpc_queue_wait failed, rc: %d\n", rc);
+       if (rc) {
+               CERROR("%s: ptlrpc_queue_wait failed: rc = %d\n",
+                      exp->exp_obd->obd_name, rc);
+               GOTO(out, rc);
+       }
 
        if (req->rq_repmsg &&
            (oqc = req_capsule_server_get(&req->rq_pill, &RMF_OBD_QUOTACTL))) {
-               *oqctl = *oqc;
+               QCTL_COPY(oqctl, oqc);
        } else if (!rc) {
-               CERROR ("Can't unpack obd_quotactl\n");
                rc = -EPROTO;
+               CERROR("%s: cannot unpack obd_quotactl: rc = %d\n",
+                       exp->exp_obd->obd_name, rc);
        }
+out:
        ptlrpc_req_finished(req);
 
        RETURN(rc);
@@ -2896,7 +2921,7 @@ static int mdc_cleanup(struct obd_device *obd)
        return osc_cleanup_common(obd);
 }
 
-static struct obd_ops mdc_obd_ops = {
+static const struct obd_ops mdc_obd_ops = {
        .o_owner            = THIS_MODULE,
        .o_setup            = mdc_setup,
        .o_precleanup       = mdc_precleanup,
@@ -2919,7 +2944,7 @@ static struct obd_ops mdc_obd_ops = {
        .o_quotactl         = mdc_quotactl,
 };
 
-static struct md_ops mdc_md_ops = {
+static const struct md_ops mdc_md_ops = {
        .m_get_root         = mdc_get_root,
        .m_null_inode       = mdc_null_inode,
        .m_close            = mdc_close,
@@ -2950,15 +2975,43 @@ static struct md_ops mdc_md_ops = {
        .m_rmfid                = mdc_rmfid,
 };
 
+dev_t mdc_changelog_dev;
+struct class *mdc_changelog_class;
 static int __init mdc_init(void)
 {
-       return class_register_type(&mdc_obd_ops, &mdc_md_ops, true, NULL,
-                                  LUSTRE_MDC_NAME, &mdc_device_type);
+       int rc = 0;
+       rc = alloc_chrdev_region(&mdc_changelog_dev, 0,
+                                MDC_CHANGELOG_DEV_COUNT,
+                                MDC_CHANGELOG_DEV_NAME);
+       if (rc)
+               return rc;
+
+       mdc_changelog_class = class_create(THIS_MODULE, MDC_CHANGELOG_DEV_NAME);
+       if (IS_ERR(mdc_changelog_class)) {
+               rc = PTR_ERR(mdc_changelog_class);
+               goto out_dev;
+       }
+
+       rc = class_register_type(&mdc_obd_ops, &mdc_md_ops, true, NULL,
+                                LUSTRE_MDC_NAME, &mdc_device_type);
+       if (rc)
+               goto out_class;
+
+       return 0;
+
+out_class:
+       class_destroy(mdc_changelog_class);
+out_dev:
+       unregister_chrdev_region(mdc_changelog_dev, MDC_CHANGELOG_DEV_COUNT);
+       return rc;
 }
 
 static void __exit mdc_exit(void)
 {
-        class_unregister_type(LUSTRE_MDC_NAME);
+       class_unregister_type(LUSTRE_MDC_NAME);
+       class_destroy(mdc_changelog_class);
+       unregister_chrdev_region(mdc_changelog_dev, MDC_CHANGELOG_DEV_COUNT);
+       idr_destroy(&mdc_changelog_minor_idr);
 }
 
 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");