Whamcloud - gitweb
LU-6152 osd-zfs: ZFS large block compat 44/13544/3
authorBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 27 Jan 2015 23:20:56 +0000 (15:20 -0800)
committerOleg Drokin <oleg.drokin@intel.com>
Sat, 9 May 2015 02:48:45 +0000 (02:48 +0000)
This patch adds the required compatibility code to leverage the
new ZFS large block feature.  This includes supporting older versions
of ZFS which not contain large block support (ZFS v0.6.3 and earlier).

At the heart of this change is the SPA_MAXBLOCKSIZE macro which has
been increased from 128K to 16M.  This macro has always defined the
maximum possible blocksize support by ZFS.  However, just because
the ZFS code may now support this new large block it doesn't mean
that the feature is enabled on the pool.  Therefore, all consumers
of SPA_MAXBLOCKSIZE have been changed to use spa_maxblocksize() which
consults the pools feature flags to determine the supported maximum.

In addition, the ZFS OSD has been updated to to properly integrate
with a datasets recordsize property.  This allows the maximum block
size of a dataset to be changed with the 'zfs set' command.  This
has no effect on existing objects but new objects will be written
using the larger block size.  For example:

  zfs set recordsize=1M <dataset>

Finally, all references to SPA_MAXBLOCKSIZE and SPA_MAXBLOCKSHIFT
were removed and replaced with portable equivilants.  Going forward
the OSD layer needs to take case to no longer make any assumtions
about the maximum block size.

Test-Parameters: mdtfilesystemtype=zfs ostfilesystemtype=zfs mdsfilesystemtype=zfs
Change-Id: Iae782ff80ff185ca8c0f38e1002ff90e457c3ca1
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-on: http://review.whamcloud.com/13544
Reviewed-by: Nathaniel Clark <nathaniel.l.clark@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
config/lustre-build-zfs.m4
lustre/osd-zfs/osd_handler.c
lustre/osd-zfs/osd_internal.h
lustre/osd-zfs/osd_io.c
lustre/osd-zfs/osd_object.c
lustre/osd-zfs/osd_quota.c

index 455977d..dd14cc6 100644 (file)
@@ -414,6 +414,18 @@ your distribution.
                        AC_DEFINE(HAVE_SA_SPILL_ALLOC, 1,
                                [Have sa_spill_alloc in ZFS])
                ])
                        AC_DEFINE(HAVE_SA_SPILL_ALLOC, 1,
                                [Have sa_spill_alloc in ZFS])
                ])
+               LB_CHECK_COMPILE([if zfs defines spa_maxblocksize],
+               spa_maxblocksize, [
+                       #include <sys/spa.h>
+               ],[
+                       spa_t *spa = NULL;
+                       int size;
+
+                       size = spa_maxblocksize(spa);
+               ],[
+                       AC_DEFINE(HAVE_SPA_MAXBLOCKSIZE, 1,
+                               [Have spa_maxblocksize in ZFS])
+               ])
        ])
 
        AM_CONDITIONAL(ZFS_ENABLED, [test "x$enable_zfs" = xyes])
        ])
 
        AM_CONDITIONAL(ZFS_ENABLED, [test "x$enable_zfs" = xyes])
index e03668a..e13909c 100644 (file)
@@ -313,7 +313,7 @@ static struct thandle *osd_trans_create(const struct lu_env *env,
 
 /* Estimate the number of objects from a number of blocks */
 uint64_t osd_objs_count_estimate(uint64_t refdbytes, uint64_t usedobjs,
 
 /* Estimate the number of objects from a number of blocks */
 uint64_t osd_objs_count_estimate(uint64_t refdbytes, uint64_t usedobjs,
-                                uint64_t nrblocks)
+                                uint64_t nrblocks, uint64_t est_maxblockshift)
 {
        uint64_t est_objs, est_refdblocks, est_usedobjs;
 
 {
        uint64_t est_objs, est_refdblocks, est_usedobjs;
 
@@ -332,7 +332,7 @@ uint64_t osd_objs_count_estimate(uint64_t refdbytes, uint64_t usedobjs,
        CLASSERT(OSD_DNODE_MIN_BLKSHIFT > 0);
        CLASSERT(OSD_DNODE_EST_BLKSHIFT > 0);
 
        CLASSERT(OSD_DNODE_MIN_BLKSHIFT > 0);
        CLASSERT(OSD_DNODE_EST_BLKSHIFT > 0);
 
-       est_refdblocks = (refdbytes >> SPA_MAXBLOCKSHIFT) +
+       est_refdblocks = (refdbytes >> est_maxblockshift) +
                         (OSD_DNODE_EST_COUNT >> OSD_DNODE_EST_BLKSHIFT);
        est_usedobjs   = usedobjs + OSD_DNODE_EST_COUNT;
 
                         (OSD_DNODE_EST_COUNT >> OSD_DNODE_EST_BLKSHIFT);
        est_usedobjs   = usedobjs + OSD_DNODE_EST_COUNT;
 
@@ -377,14 +377,15 @@ uint64_t osd_objs_count_estimate(uint64_t refdbytes, uint64_t usedobjs,
        return est_objs;
 }
 
        return est_objs;
 }
 
-static int osd_objset_statfs(struct objset *os, struct obd_statfs *osfs)
+static int osd_objset_statfs(struct osd_device *osd, struct obd_statfs *osfs)
 {
 {
+       struct objset *os = osd->od_os;
        uint64_t refdbytes, availbytes, usedobjs, availobjs;
        uint64_t est_availobjs;
        uint64_t reserved;
        uint64_t refdbytes, availbytes, usedobjs, availobjs;
        uint64_t est_availobjs;
        uint64_t reserved;
+       uint64_t bshift;
 
 
-       dmu_objset_space(os, &refdbytes, &availbytes, &usedobjs,
-                        &availobjs);
+       dmu_objset_space(os, &refdbytes, &availbytes, &usedobjs, &availobjs);
 
        /*
         * ZFS allows multiple block sizes.  For statfs, Linux makes no
 
        /*
         * ZFS allows multiple block sizes.  For statfs, Linux makes no
@@ -394,10 +395,11 @@ static int osd_objset_statfs(struct objset *os, struct obd_statfs *osfs)
         * largest possible block size as IO size for the optimum performance
         * and scale the free and used blocks count appropriately.
         */
         * largest possible block size as IO size for the optimum performance
         * and scale the free and used blocks count appropriately.
         */
-       osfs->os_bsize = 1ULL << SPA_MAXBLOCKSHIFT;
+       osfs->os_bsize = osd->od_max_blksz;
+       bshift = fls64(osfs->os_bsize) - 1;
 
 
-       osfs->os_blocks = (refdbytes + availbytes) >> SPA_MAXBLOCKSHIFT;
-       osfs->os_bfree = availbytes >> SPA_MAXBLOCKSHIFT;
+       osfs->os_blocks = (refdbytes + availbytes) >> bshift;
+       osfs->os_bfree = availbytes >> bshift;
        osfs->os_bavail = osfs->os_bfree; /* no extra root reservation */
 
        /* Take replication (i.e. number of copies) into account */
        osfs->os_bavail = osfs->os_bfree; /* no extra root reservation */
 
        /* Take replication (i.e. number of copies) into account */
@@ -412,12 +414,11 @@ static int osd_objset_statfs(struct objset *os, struct obd_statfs *osfs)
         * Reserve 0.78% of total space, at least 4MB for small filesystems,
         * for internal files to be created/unlinked when space is tight.
         */
         * Reserve 0.78% of total space, at least 4MB for small filesystems,
         * for internal files to be created/unlinked when space is tight.
         */
-       CLASSERT(OSD_STATFS_RESERVED_BLKS > 0);
-       if (likely(osfs->os_blocks >=
-                       OSD_STATFS_RESERVED_BLKS << OSD_STATFS_RESERVED_SHIFT))
+       CLASSERT(OSD_STATFS_RESERVED_SIZE > 0);
+       if (likely(osfs->os_blocks >= OSD_STATFS_RESERVED_SIZE))
                reserved = osfs->os_blocks >> OSD_STATFS_RESERVED_SHIFT;
        else
                reserved = osfs->os_blocks >> OSD_STATFS_RESERVED_SHIFT;
        else
-               reserved = OSD_STATFS_RESERVED_BLKS;
+               reserved = OSD_STATFS_RESERVED_SIZE >> bshift;
 
        osfs->os_blocks -= reserved;
        osfs->os_bfree  -= MIN(reserved, osfs->os_bfree);
 
        osfs->os_blocks -= reserved;
        osfs->os_bfree  -= MIN(reserved, osfs->os_bfree);
@@ -431,7 +432,7 @@ static int osd_objset_statfs(struct objset *os, struct obd_statfs *osfs)
         * Compute a better estimate in udmu_objs_count_estimate().
         */
        est_availobjs = osd_objs_count_estimate(refdbytes, usedobjs,
         * Compute a better estimate in udmu_objs_count_estimate().
         */
        est_availobjs = osd_objs_count_estimate(refdbytes, usedobjs,
-                                               osfs->os_bfree);
+                                               osfs->os_bfree, bshift);
 
        osfs->os_ffree = min(availobjs, est_availobjs);
        osfs->os_files = osfs->os_ffree + usedobjs;
 
        osfs->os_ffree = min(availobjs, est_availobjs);
        osfs->os_files = osfs->os_ffree + usedobjs;
@@ -460,11 +461,10 @@ static int osd_objset_statfs(struct objset *os, struct obd_statfs *osfs)
 int osd_statfs(const struct lu_env *env, struct dt_device *d,
               struct obd_statfs *osfs)
 {
 int osd_statfs(const struct lu_env *env, struct dt_device *d,
               struct obd_statfs *osfs)
 {
-       struct osd_device *osd = osd_dt_dev(d);
        int                rc;
        ENTRY;
 
        int                rc;
        ENTRY;
 
-       rc = osd_objset_statfs(osd->od_os, osfs);
+       rc = osd_objset_statfs(osd_dt_dev(d), osfs);
        if (unlikely(rc != 0))
                RETURN(rc);
 
        if (unlikely(rc != 0))
                RETURN(rc);
 
@@ -474,13 +474,14 @@ int osd_statfs(const struct lu_env *env, struct dt_device *d,
        RETURN(0);
 }
 
        RETURN(0);
 }
 
-static int osd_blk_insert_cost(void)
+static int osd_blk_insert_cost(struct osd_device *osd)
 {
 {
-       int max_blockshift, nr_blkptrshift;
+       int max_blockshift, nr_blkptrshift, bshift;
 
        /* max_blockshift is the log2 of the number of blocks needed to reach
         * the maximum filesize (that's to say 2^64) */
 
        /* max_blockshift is the log2 of the number of blocks needed to reach
         * the maximum filesize (that's to say 2^64) */
-       max_blockshift = DN_MAX_OFFSET_SHIFT - SPA_MAXBLOCKSHIFT;
+       bshift = osd_spa_maxblockshift(dmu_objset_spa(osd->od_os));
+       max_blockshift = DN_MAX_OFFSET_SHIFT - bshift;
 
        /* nr_blkptrshift is the log2 of the number of block pointers that can
         * be stored in an indirect block */
 
        /* nr_blkptrshift is the log2 of the number of block pointers that can
         * be stored in an indirect block */
@@ -532,7 +533,7 @@ static void osd_conf_get(const struct lu_env *env,
         * estimate the real size consumed by an object */
        param->ddp_inodespace = OSD_DNODE_EST_COUNT;
        /* per-fragment overhead to be used by the client code */
         * estimate the real size consumed by an object */
        param->ddp_inodespace = OSD_DNODE_EST_COUNT;
        /* per-fragment overhead to be used by the client code */
-       param->ddp_grant_frag = osd_blk_insert_cost();
+       param->ddp_grant_frag = osd_blk_insert_cost(osd);
 }
 
 /*
 }
 
 /*
@@ -675,6 +676,70 @@ static void osd_xattr_changed_cb(void *arg, uint64_t newval)
        osd->od_xattr_in_sa = (newval == ZFS_XATTR_SA);
 }
 
        osd->od_xattr_in_sa = (newval == ZFS_XATTR_SA);
 }
 
+static void osd_recordsize_changed_cb(void *arg, uint64_t newval)
+{
+       struct osd_device *osd = arg;
+
+       LASSERT(newval <= osd_spa_maxblocksize(dmu_objset_spa(osd->od_os)));
+       LASSERT(newval >= SPA_MINBLOCKSIZE);
+       LASSERT(ISP2(newval));
+
+       osd->od_max_blksz = newval;
+}
+
+/*
+ * This function unregisters all registered callbacks.  It's harmless to
+ * unregister callbacks that were never registered so it is used to safely
+ * unwind a partially completed call to osd_objset_register_callbacks().
+ */
+static void osd_objset_unregister_callbacks(struct osd_device *o)
+{
+       struct dsl_dataset      *ds = dmu_objset_ds(o->od_os);
+
+       (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_XATTR),
+                                  osd_xattr_changed_cb, o);
+       (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_RECORDSIZE),
+                                  osd_recordsize_changed_cb, o);
+
+       if (o->arc_prune_cb != NULL) {
+               arc_remove_prune_callback(o->arc_prune_cb);
+               o->arc_prune_cb = NULL;
+       }
+}
+
+/*
+ * Register the required callbacks to be notified when zfs properties
+ * are modified using the 'zfs(8)' command line utility.
+ */
+static int osd_objset_register_callbacks(struct osd_device *o)
+{
+       struct dsl_dataset      *ds = dmu_objset_ds(o->od_os);
+       dsl_pool_t              *dp = dmu_objset_pool(o->od_os);
+       int                     rc;
+
+       LASSERT(ds);
+       LASSERT(dp);
+
+       dsl_pool_config_enter(dp, FTAG);
+       rc = -dsl_prop_register(ds, zfs_prop_to_name(ZFS_PROP_XATTR),
+                               osd_xattr_changed_cb, o);
+       if (rc)
+               GOTO(err, rc);
+
+       rc = -dsl_prop_register(ds, zfs_prop_to_name(ZFS_PROP_RECORDSIZE),
+                               osd_recordsize_changed_cb, o);
+       if (rc)
+               GOTO(err, rc);
+
+       o->arc_prune_cb = arc_add_prune_callback(arc_prune_func, o);
+err:
+       dsl_pool_config_exit(dp, FTAG);
+       if (rc)
+               osd_objset_unregister_callbacks(o);
+
+       RETURN(rc);
+}
+
 static int osd_objset_open(struct osd_device *o)
 {
        uint64_t        version = ZPL_VERSION;
 static int osd_objset_open(struct osd_device *o)
 {
        uint64_t        version = ZPL_VERSION;
@@ -737,11 +802,9 @@ out:
 static int osd_mount(const struct lu_env *env,
                     struct osd_device *o, struct lustre_cfg *cfg)
 {
 static int osd_mount(const struct lu_env *env,
                     struct osd_device *o, struct lustre_cfg *cfg)
 {
-       struct dsl_dataset      *ds;
        char                    *mntdev = lustre_cfg_string(cfg, 1);
        char                    *svname = lustre_cfg_string(cfg, 4);
        dmu_buf_t               *rootdb;
        char                    *mntdev = lustre_cfg_string(cfg, 1);
        char                    *svname = lustre_cfg_string(cfg, 4);
        dmu_buf_t               *rootdb;
-       dsl_pool_t              *dp;
        const char              *opts;
        int                      rc;
        ENTRY;
        const char              *opts;
        int                      rc;
        ENTRY;
@@ -764,30 +827,19 @@ static int osd_mount(const struct lu_env *env,
                o->od_is_ost = 1;
 
        rc = osd_objset_open(o);
                o->od_is_ost = 1;
 
        rc = osd_objset_open(o);
-       if (rc) {
-               CERROR("%s: can't open objset %s: rc = %d\n", o->od_svname,
-                       o->od_mntdev, rc);
-               RETURN(rc);
-       }
+       if (rc)
+               GOTO(err, rc);
 
 
-       ds = dmu_objset_ds(o->od_os);
-       dp = dmu_objset_pool(o->od_os);
-       LASSERT(ds);
-       LASSERT(dp);
-       dsl_pool_config_enter(dp, FTAG);
-       rc = dsl_prop_register(ds, "xattr", osd_xattr_changed_cb, o);
-       dsl_pool_config_exit(dp, FTAG);
+       o->od_xattr_in_sa = B_TRUE;
+       o->od_max_blksz = SPA_OLD_MAXBLOCKSIZE;
+
+       rc = osd_objset_register_callbacks(o);
        if (rc)
        if (rc)
-               CWARN("%s: can't register xattr callback, ignore: rc=%d\n",
-                     o->od_svname, rc);
+               GOTO(err, rc);
 
        rc = __osd_obj2dbuf(env, o->od_os, o->od_rootid, &rootdb);
 
        rc = __osd_obj2dbuf(env, o->od_os, o->od_rootid, &rootdb);
-       if (rc) {
-               CERROR("%s: obj2dbuf() failed: rc = %d\n", o->od_svname, rc);
-               dmu_objset_disown(o->od_os, o);
-               o->od_os = NULL;
-               RETURN(rc);
-       }
+       if (rc)
+               GOTO(err, rc);
 
        o->od_root = rootdb->db_object;
        sa_buf_rele(rootdb, osd_obj_tag);
 
        o->od_root = rootdb->db_object;
        sa_buf_rele(rootdb, osd_obj_tag);
@@ -818,8 +870,6 @@ static int osd_mount(const struct lu_env *env,
        if (rc)
                GOTO(err, rc);
 
        if (rc)
                GOTO(err, rc);
 
-       o->arc_prune_cb = arc_add_prune_callback(arc_prune_func, o);
-
        /* initialize quota slave instance */
        o->od_quota_slave = qsd_init(env, o->od_svname, &o->od_dt_dev,
                                     o->od_proc_entry);
        /* initialize quota slave instance */
        o->od_quota_slave = qsd_init(env, o->od_svname, &o->od_dt_dev,
                                     o->od_proc_entry);
@@ -835,6 +885,11 @@ static int osd_mount(const struct lu_env *env,
                o->od_posix_acl = 1;
 
 err:
                o->od_posix_acl = 1;
 
 err:
+       if (rc) {
+               dmu_objset_disown(o->od_os, o);
+               o->od_os = NULL;
+       }
+
        RETURN(rc);
 }
 
        RETURN(rc);
 }
 
@@ -940,7 +995,6 @@ static struct lu_device *osd_device_fini(const struct lu_env *env,
                                         struct lu_device *d)
 {
        struct osd_device *o = osd_dev(d);
                                         struct lu_device *d)
 {
        struct osd_device *o = osd_dev(d);
-       struct dsl_dataset *ds;
        int                rc;
        ENTRY;
 
        int                rc;
        ENTRY;
 
@@ -949,15 +1003,7 @@ static struct lu_device *osd_device_fini(const struct lu_env *env,
        osd_oi_fini(env, o);
 
        if (o->od_os) {
        osd_oi_fini(env, o);
 
        if (o->od_os) {
-               ds = dmu_objset_ds(o->od_os);
-               rc = dsl_prop_unregister(ds, "xattr", osd_xattr_changed_cb, o);
-               if (rc)
-                       CERROR("%s: dsl_prop_unregister xattr error %d\n",
-                               o->od_svname, rc);
-               if (o->arc_prune_cb != NULL) {
-                       arc_remove_prune_callback(o->arc_prune_cb);
-                       o->arc_prune_cb = NULL;
-               }
+               osd_objset_unregister_callbacks(o);
                osd_sync(env, lu2dt_dev(d));
                txg_wait_callbacks(spa_get_dsl(dmu_objset_spa(o->od_os)));
        }
                osd_sync(env, lu2dt_dev(d));
                txg_wait_callbacks(spa_get_dsl(dmu_objset_spa(o->od_os)));
        }
index d746578..c698db1 100644 (file)
 #define OSD_GFP_IO             (GFP_NOFS | __GFP_HIGHMEM)
 
 /* Statfs space reservation for grant, fragmentation, and unlink space. */
 #define OSD_GFP_IO             (GFP_NOFS | __GFP_HIGHMEM)
 
 /* Statfs space reservation for grant, fragmentation, and unlink space. */
-#define OSD_STATFS_RESERVED_BLKS  (1ULL << (22 - SPA_MAXBLOCKSHIFT)) /* 4MB */
-#define OSD_STATFS_RESERVED_SHIFT (7)         /* reserve 0.78% of all space */
+#define OSD_STATFS_RESERVED_SIZE       (16ULL << 20) /* reserve 16MB minimum */
+#define OSD_STATFS_RESERVED_SHIFT      (7)     /* reserve 0.78% of all space */
 
 /* Statfs {minimum, safe estimate, and maximum} dnodes per block */
 
 /* Statfs {minimum, safe estimate, and maximum} dnodes per block */
-#define OSD_DNODE_MIN_BLKSHIFT (SPA_MAXBLOCKSHIFT - DNODE_SHIFT) /* 17-9 =8 */
-#define OSD_DNODE_EST_BLKSHIFT (SPA_MAXBLOCKSHIFT - 12)          /* 17-12=5 */
-#define OSD_DNODE_EST_COUNT    1024
+#define OSD_DNODE_MIN_BLKSHIFT (DNODES_PER_BLOCK_SHIFT)
+#define OSD_DNODE_EST_BLKSHIFT (DNODES_PER_BLOCK_SHIFT >> 1)
+#define OSD_DNODE_EST_COUNT    1024
 
 #define OSD_GRANT_FOR_LOCAL_OIDS (2ULL << 20) /* 2MB for last_rcvd, ... */
 
 
 #define OSD_GRANT_FOR_LOCAL_OIDS (2ULL << 20) /* 2MB for last_rcvd, ... */
 
@@ -252,6 +252,7 @@ struct osd_device {
        struct proc_dir_entry   *od_proc_entry;
        struct lprocfs_stats    *od_stats;
 
        struct proc_dir_entry   *od_proc_entry;
        struct lprocfs_stats    *od_stats;
 
+       uint64_t                 od_max_blksz;
        uint64_t                 od_root;
        uint64_t                 od_O_id;
        struct osd_oi           **od_oi_table;
        uint64_t                 od_root;
        uint64_t                 od_O_id;
        struct osd_oi           **od_oi_table;
@@ -334,7 +335,7 @@ int osd_declare_quota(const struct lu_env *env, struct osd_device *osd,
                      struct osd_thandle *oh, bool is_blk, int *flags,
                      bool force);
 uint64_t osd_objs_count_estimate(uint64_t refdbytes, uint64_t usedobjs,
                      struct osd_thandle *oh, bool is_blk, int *flags,
                      bool force);
 uint64_t osd_objs_count_estimate(uint64_t refdbytes, uint64_t usedobjs,
-                                uint64_t nrblocks);
+                                uint64_t nrblocks, uint64_t est_maxblockshift);
 
 /*
  * Helpers.
 
 /*
  * Helpers.
@@ -535,7 +536,15 @@ static inline void dsl_pool_config_enter(dsl_pool_t *dp, char *name)
 static inline void dsl_pool_config_exit(dsl_pool_t *dp, char *name)
 {
 }
 static inline void dsl_pool_config_exit(dsl_pool_t *dp, char *name)
 {
 }
+#endif
 
 
+#ifdef HAVE_SPA_MAXBLOCKSIZE
+#define        osd_spa_maxblocksize(spa)       spa_maxblocksize(spa)
+#define        osd_spa_maxblockshift(spa)      fls64(spa_maxblocksize(spa) - 1)
+#else
+#define        osd_spa_maxblocksize(spa)       SPA_MAXBLOCKSIZE
+#define        osd_spa_maxblockshift(spa)      SPA_MAXBLOCKSHIFT
+#define        SPA_OLD_MAXBLOCKSIZE            SPA_MAXBLOCKSIZE
 #endif
 
 #ifdef HAVE_SA_SPILL_ALLOC
 #endif
 
 #ifdef HAVE_SA_SPILL_ALLOC
index d85c25b..49c69c1 100644 (file)
@@ -559,7 +559,8 @@ static int osd_count_not_mapped(struct osd_object *obj, uint64_t start,
                if (start < dn->dn_datablksz)
                        start = dn->dn_datablksz;
                /* assume largest block size */
                if (start < dn->dn_datablksz)
                        start = dn->dn_datablksz;
                /* assume largest block size */
-               blkshift = SPA_MAXBLOCKSHIFT;
+               blkshift = osd_spa_maxblockshift(
+                       dmu_objset_spa(osd_obj2dev(obj)->od_os));
        } else {
                /* blocksize can't change */
                blkshift = dn->dn_datablkshift;
        } else {
                /* blocksize can't change */
                blkshift = dn->dn_datablkshift;
index ad6752f..ab0a288 100644 (file)
@@ -758,7 +758,8 @@ static int osd_attr_get(const struct lu_env *env,
                attr->la_size = 512 * blocks;
        /* Block size may be not set; suggest maximal I/O transfers. */
        if (blksize == 0)
                attr->la_size = 512 * blocks;
        /* Block size may be not set; suggest maximal I/O transfers. */
        if (blksize == 0)
-               blksize = 1ULL << SPA_MAXBLOCKSHIFT;
+               blksize = osd_spa_maxblocksize(
+                       dmu_objset_spa(osd_obj2dev(obj)->od_os));
 
        attr->la_blksize = blksize;
        attr->la_blocks = blocks;
 
        attr->la_blksize = blksize;
        attr->la_blocks = blocks;
@@ -1329,13 +1330,15 @@ static dmu_buf_t *osd_mkreg(const struct lu_env *env, struct osd_object *obj,
                return ERR_PTR(rc);
 
        /*
                return ERR_PTR(rc);
 
        /*
-        * XXX: a hack, OST to use bigger blocksize. we need
-        * a method in OSD API to control this from OFD/MDD
+        * XXX: This heuristic is non-optimal.  It would be better to
+        * increase the blocksize up to osd->od_max_blksz during the write.
+        * This is exactly how the ZPL behaves and it ensures that the right
+        * blocksize is selected based on the file size rather than the
+        * making broad assumptions based on the osd type.
         */
        if (!lu_device_is_md(osd2lu_dev(osd))) {
         */
        if (!lu_device_is_md(osd2lu_dev(osd))) {
-               rc = -dmu_object_set_blocksize(osd->od_os,
-                                              db->db_object,
-                               128 << 10, 0, oh->ot_tx);
+               rc = -dmu_object_set_blocksize(osd->od_os, db->db_object,
+                                              osd->od_max_blksz, 0, oh->ot_tx);
                if (unlikely(rc)) {
                        CERROR("%s: can't change blocksize: %d\n",
                               osd->od_svname, rc);
                if (unlikely(rc)) {
                        CERROR("%s: can't change blocksize: %d\n",
                               osd->od_svname, rc);
index abffb58..a5a2e8e 100644 (file)
@@ -49,15 +49,16 @@ uint64_t osd_quota_fid2dmu(const struct lu_fid *fid)
 static uint64_t osd_objset_user_iused(struct osd_device *osd, uint64_t uidbytes)
 {
        uint64_t refdbytes, availbytes, usedobjs, availobjs;
 static uint64_t osd_objset_user_iused(struct osd_device *osd, uint64_t uidbytes)
 {
        uint64_t refdbytes, availbytes, usedobjs, availobjs;
-       uint64_t uidobjs;
+       uint64_t uidobjs, bshift;
 
        /* get fresh statfs info */
        dmu_objset_space(osd->od_os, &refdbytes, &availbytes,
                         &usedobjs, &availobjs);
 
        /* estimate the number of objects based on the disk usage */
 
        /* get fresh statfs info */
        dmu_objset_space(osd->od_os, &refdbytes, &availbytes,
                         &usedobjs, &availobjs);
 
        /* estimate the number of objects based on the disk usage */
+       bshift = fls64(osd->od_max_blksz) - 1;
        uidobjs = osd_objs_count_estimate(refdbytes, usedobjs,
        uidobjs = osd_objs_count_estimate(refdbytes, usedobjs,
-                                         uidbytes >> SPA_MAXBLOCKSHIFT);
+                                         uidbytes >> bshift, bshift);
        if (uidbytes > 0)
                /* if we have at least 1 byte, we have at least one dnode ... */
                uidobjs = max_t(uint64_t, uidobjs, 1);
        if (uidbytes > 0)
                /* if we have at least 1 byte, we have at least one dnode ... */
                uidobjs = max_t(uint64_t, uidobjs, 1);