Whamcloud - gitweb
LU-15880 quota: fix issues in reserving quota
[fs/lustre-release.git] / lustre / osd-zfs / osd_handler.c
index 30ec13e..7d1b579 100644 (file)
@@ -27,7 +27,6 @@
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
  *
  * lustre/osd-zfs/osd_handler.c
  * Top-level entry points into osd module
@@ -644,7 +643,7 @@ static void osd_conf_get(const struct lu_env *env,
                param->ddp_brw_size = ONE_MB_BRW_SIZE;
 
 #ifdef HAVE_DMU_OFFSET_NEXT
-       param->ddp_has_lseek_data_hole = true;
+       param->ddp_has_lseek_data_hole = osd->od_sync_on_lseek;
 #else
        param->ddp_has_lseek_data_hole = false;
 #endif
@@ -699,17 +698,38 @@ static int osd_ro(const struct lu_env *env, struct dt_device *d)
        RETURN(0);
 }
 
+/* reserve or free quota for some operation */
+static int osd_reserve_or_free_quota(const struct lu_env *env,
+                                    struct dt_device *dev,
+                                    struct lquota_id_info *qi)
+{
+       struct osd_device       *osd = osd_dt_dev(dev);
+       struct qsd_instance     *qsd = NULL;
+       int rc;
+
+       ENTRY;
+
+       if (qi->lqi_is_blk)
+               qsd = osd->od_quota_slave_dt;
+       else
+               qsd = osd->od_quota_slave_md;
+
+       rc = qsd_reserve_or_free_quota(env, qsd, qi);
+       RETURN(rc);
+}
+
 static const struct dt_device_operations osd_dt_ops = {
-       .dt_root_get            = osd_root_get,
-       .dt_statfs              = osd_statfs,
-       .dt_trans_create        = osd_trans_create,
-       .dt_trans_start         = osd_trans_start,
-       .dt_trans_stop          = osd_trans_stop,
-       .dt_trans_cb_add        = osd_trans_cb_add,
-       .dt_conf_get            = osd_conf_get,
-       .dt_sync                = osd_sync,
-       .dt_commit_async        = osd_commit_async,
-       .dt_ro                  = osd_ro,
+       .dt_root_get              = osd_root_get,
+       .dt_statfs                = osd_statfs,
+       .dt_trans_create          = osd_trans_create,
+       .dt_trans_start           = osd_trans_start,
+       .dt_trans_stop            = osd_trans_stop,
+       .dt_trans_cb_add          = osd_trans_cb_add,
+       .dt_conf_get              = osd_conf_get,
+       .dt_sync                  = osd_sync,
+       .dt_commit_async          = osd_commit_async,
+       .dt_ro                    = osd_ro,
+       .dt_reserve_or_free_quota = osd_reserve_or_free_quota,
 };
 
 /*
@@ -1070,12 +1090,15 @@ osd_unlinked_drain(const struct lu_env *env, struct osd_device *osd)
 static int osd_mount(const struct lu_env *env,
                     struct osd_device *o, struct lustre_cfg *cfg)
 {
-       char                    *mntdev = lustre_cfg_string(cfg, 1);
-       char                    *str    = lustre_cfg_string(cfg, 2);
-       char                    *svname = lustre_cfg_string(cfg, 4);
+       char *mntdev = lustre_cfg_string(cfg, 1);
+       char *str = lustre_cfg_string(cfg, 2);
+       char *svname = lustre_cfg_string(cfg, 4);
+       time64_t interval = AS_DEFAULT;
        dnode_t *rootdn;
-       const char              *opts;
-       int                      rc;
+       const char *opts;
+       bool resetoi = false;
+       int rc;
+
        ENTRY;
 
        if (o->od_os != NULL)
@@ -1092,6 +1115,8 @@ static int osd_mount(const struct lu_env *env,
        if (rc >= sizeof(o->od_svname))
                RETURN(-E2BIG);
 
+       opts = lustre_cfg_string(cfg, 3);
+
        o->od_index_backup_stop = 0;
        o->od_index = -1; /* -1 means index is invalid */
        rc = server_name2index(o->od_svname, &o->od_index, NULL);
@@ -1110,7 +1135,7 @@ static int osd_mount(const struct lu_env *env,
                }
 
                if (flags & LMD_FLG_NOSCRUB)
-                       o->od_auto_scrub_interval = AS_NEVER;
+                       interval = AS_NEVER;
        }
 
        if (server_name_is_ost(o->od_svname))
@@ -1162,8 +1187,15 @@ static int osd_mount(const struct lu_env *env,
        if (rc)
                GOTO(err, rc);
 
+       if (opts && strstr(opts, "resetoi"))
+               resetoi = true;
+
+       rc = lprocfs_init_brw_stats(&o->od_brw_stats);
+       if (rc)
+               GOTO(err, rc);
+
        o->od_in_init = 1;
-       rc = osd_scrub_setup(env, o);
+       rc = osd_scrub_setup(env, o, interval, resetoi);
        o->od_in_init = 0;
        if (rc)
                GOTO(err, rc);
@@ -1175,8 +1207,8 @@ static int osd_mount(const struct lu_env *env,
        /* currently it's no need to prepare qsd_instance_md for OST */
        if (!o->od_is_ost) {
                o->od_quota_slave_md = qsd_init(env, o->od_svname,
-                                               &o->od_dt_dev,
-                                               o->od_proc_entry, true);
+                                               &o->od_dt_dev, o->od_proc_entry,
+                                               true, false);
                if (IS_ERR(o->od_quota_slave_md)) {
                        rc = PTR_ERR(o->od_quota_slave_md);
                        o->od_quota_slave_md = NULL;
@@ -1185,7 +1217,7 @@ static int osd_mount(const struct lu_env *env,
        }
 
        o->od_quota_slave_dt = qsd_init(env, o->od_svname, &o->od_dt_dev,
-                                    o->od_proc_entry, false);
+                                       o->od_proc_entry, false, false);
 
        if (IS_ERR(o->od_quota_slave_dt)) {
                if (o->od_quota_slave_md != NULL) {
@@ -1206,17 +1238,14 @@ static int osd_mount(const struct lu_env *env,
 #endif
 
        /* parse mount option "noacl", and enable ACL by default */
-       opts = lustre_cfg_string(cfg, 3);
        if (opts == NULL || strstr(opts, "noacl") == NULL)
                o->od_posix_acl = 1;
 
        osd_unlinked_drain(env, o);
-err:
-       if (rc && o->od_os) {
-               osd_dmu_objset_disown(o->od_os, B_TRUE, o);
-               o->od_os = NULL;
-       }
 
+       RETURN(0);
+
+err:
        RETURN(rc);
 }
 
@@ -1283,7 +1312,7 @@ static int osd_device_init0(const struct lu_env *env,
        o->od_dt_dev.dd_ops = &osd_dt_ops;
        sema_init(&o->od_otable_sem, 1);
        INIT_LIST_HEAD(&o->od_ios_list);
-       o->od_auto_scrub_interval = AS_DEFAULT;
+       o->od_sync_on_lseek = B_TRUE;
 
        /* ZFS does not support reporting nonrotional status yet, so this flag
         * is only set if explicitly set by the user.
@@ -1295,7 +1324,59 @@ out:
 }
 
 static struct lu_device *osd_device_fini(const struct lu_env *env,
-                                        struct lu_device *dev);
+                                        struct lu_device *d)
+{
+       struct osd_device *o = osd_dev(d);
+       int                rc;
+
+       ENTRY;
+       osd_index_backup(env, o, false);
+       if (o->od_os) {
+               osd_objset_unregister_callbacks(o);
+               if (!o->od_dt_dev.dd_rdonly) {
+                       osd_sync(env, lu2dt_dev(d));
+                       txg_wait_callbacks(
+                                       spa_get_dsl(dmu_objset_spa(o->od_os)));
+               }
+       }
+
+       /* now with all the callbacks completed we can cleanup the remainings */
+       osd_shutdown(env, o);
+       osd_scrub_cleanup(env, o);
+
+       rc = osd_procfs_fini(o);
+       if (rc) {
+               CERROR("proc fini error %d\n", rc);
+               RETURN(ERR_PTR(rc));
+       }
+
+       if (o->od_os)
+               osd_umount(env, o);
+
+       RETURN(NULL);
+}
+
+
+static struct lu_device *osd_device_free(const struct lu_env *env,
+                                        struct lu_device *d)
+{
+       struct osd_device *o = osd_dev(d);
+
+       ENTRY;
+       /* XXX: make osd top device in order to release reference */
+       if (d->ld_site) {
+               d->ld_site->ls_top_dev = d;
+               lu_site_purge(env, d->ld_site, -1);
+               lu_site_print(env, d->ld_site, &d->ld_site->ls_obj_hash.nelems,
+                             D_ERROR, lu_cdebug_printer);
+       }
+       if (o->od_site.ls_bottom_dev)
+               lu_site_fini(&o->od_site);
+       dt_device_fini(&o->od_dt_dev);
+       OBD_FREE_PTR(o);
+
+       RETURN(NULL);
+}
 
 static struct lu_device *osd_device_alloc(const struct lu_env *env,
                                          struct lu_device_type *type,
@@ -1323,70 +1404,22 @@ static struct lu_device *osd_device_alloc(const struct lu_env *env,
                rc = osd_device_init0(env, dev, cfg);
                if (rc == 0) {
                        rc = osd_mount(env, dev, cfg);
-                       if (rc)
+                       if (rc) {
                                osd_device_fini(env, osd2lu_dev(dev));
-               }
-               if (rc)
+                               osd_device_free(env, osd2lu_dev(dev));
+                               dev = NULL;
+                       }
+               } else {
                        dt_device_fini(&dev->od_dt_dev);
+               }
        }
 
-       if (unlikely(rc != 0))
+       if (unlikely(rc != 0) && dev)
                OBD_FREE_PTR(dev);
 
        return rc == 0 ? osd2lu_dev(dev) : ERR_PTR(rc);
 }
 
-static struct lu_device *osd_device_free(const struct lu_env *env,
-                                        struct lu_device *d)
-{
-       struct osd_device *o = osd_dev(d);
-       ENTRY;
-
-       /* XXX: make osd top device in order to release reference */
-       d->ld_site->ls_top_dev = d;
-       lu_site_purge(env, d->ld_site, -1);
-       lu_site_print(env, d->ld_site, &d->ld_site->ls_obj_hash.nelems,
-                     D_ERROR, lu_cdebug_printer);
-       lu_site_fini(&o->od_site);
-       dt_device_fini(&o->od_dt_dev);
-       OBD_FREE_PTR(o);
-
-       RETURN (NULL);
-}
-
-static struct lu_device *osd_device_fini(const struct lu_env *env,
-                                        struct lu_device *d)
-{
-       struct osd_device *o = osd_dev(d);
-       int                rc;
-       ENTRY;
-
-       osd_index_backup(env, o, false);
-       if (o->od_os) {
-               osd_objset_unregister_callbacks(o);
-               if (!o->od_dt_dev.dd_rdonly) {
-                       osd_sync(env, lu2dt_dev(d));
-                       txg_wait_callbacks(
-                                       spa_get_dsl(dmu_objset_spa(o->od_os)));
-               }
-       }
-
-       /* now with all the callbacks completed we can cleanup the remainings */
-       osd_shutdown(env, o);
-       osd_scrub_cleanup(env, o);
-
-       rc = osd_procfs_fini(o);
-       if (rc) {
-               CERROR("proc fini error %d\n", rc);
-               RETURN(ERR_PTR(rc));
-       }
-
-       if (o->od_os)
-               osd_umount(env, o);
-
-       RETURN(NULL);
-}
-
 static int osd_device_init(const struct lu_env *env, struct lu_device *d,
                            const char *name, struct lu_device *next)
 {