X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=inline;f=lustre%2Fosd-zfs%2Fosd_io.c;h=dd26c0a38fbae6c7871a055c5376e5f7c3f0a8a1;hb=6c3f0cfb4a8e372e8c3ae612c6eee7b7715fbeb7;hp=f2a72b673cd385b8aaa5ca985d00b7c0b13b3fb0;hpb=83d660436a164758fd4a29c1433d11c0f4591196;p=fs%2Flustre-release.git diff --git a/lustre/osd-zfs/osd_io.c b/lustre/osd-zfs/osd_io.c index f2a72b6..dd26c0a 100644 --- a/lustre/osd-zfs/osd_io.c +++ b/lustre/osd-zfs/osd_io.c @@ -141,14 +141,14 @@ static ssize_t osd_read(const struct lu_env *env, struct dt_object *dt, { struct osd_device *osd = osd_obj2dev(osd_dt_obj(dt)); size_t size = buf->lb_len; - ktime_t start; + hrtime_t start = gethrtime(); s64 delta_ms; int rc; - start = ktime_get(); record_start_io(osd, READ, 0); rc = __osd_read(env, dt, buf, pos, &size); - delta_ms = ktime_ms_delta(ktime_get(), start); + delta_ms = gethrtime() - start; + do_div(delta_ms, NSEC_PER_MSEC); record_end_io(osd, READ, delta_ms, size, size >> PAGE_SHIFT); return rc; @@ -334,7 +334,7 @@ static int osd_bufs_get_read(const struct lu_env *env, struct osd_object *obj, { struct osd_device *osd = osd_obj2dev(obj); int rc, i, numbufs, npages = 0, drop_cache = 0; - ktime_t start = ktime_get(); + hrtime_t start = gethrtime(); dmu_buf_t **dbp; s64 delta_ms; @@ -422,7 +422,8 @@ static int osd_bufs_get_read(const struct lu_env *env, struct osd_object *obj, dmu_buf_rele_array(dbp, numbufs, osd_0copy_tag); } - delta_ms = ktime_ms_delta(ktime_get(), start); + delta_ms = gethrtime() - start; + do_div(delta_ms, NSEC_PER_MSEC); record_end_io(osd, READ, delta_ms, npages * PAGE_SIZE, npages); RETURN(npages); @@ -613,11 +614,9 @@ static inline uint64_t osd_roundup2blocksz(uint64_t size, size += offset % blksz; if (likely(is_power_of_2(blksz))) - return PO2_ROUNDUP_TYPED(size, blksz, uint64_t); - - size += blksz - 1; - do_div(size, blksz); - return size * blksz; + return round_up(size, blksz); + else + return DIV_ROUND_UP_ULL(size, blksz) * blksz; } static int osd_declare_write_commit(const struct lu_env *env, @@ -1024,9 +1023,11 @@ static int osd_read_prep(const struct lu_env *env, struct dt_object *dt, * dmu_tx_hold_sa() and if off < size, dmu_tx_hold_free() * called and then assigned to a transaction group. */ -static int __osd_object_punch(objset_t *os, dnode_t *dn, dmu_tx_t *tx, - uint64_t size, uint64_t off, uint64_t len) +static int __osd_object_punch(struct osd_object *obj, objset_t *os, + dmu_tx_t *tx, uint64_t off, uint64_t len) { + dnode_t *dn = obj->oo_dn; + uint64_t size = obj->oo_attr.la_size; int rc = 0; /* Assert that the transaction has been assigned to a @@ -1038,6 +1039,19 @@ static int __osd_object_punch(objset_t *os, dnode_t *dn, dmu_tx_t *tx, if (len == DMU_OBJECT_END && size == off) return 0; + /* if object holds encrypted content, we need to make sure we truncate + * on an encryption unit boundary, or subsequent reads will get + * corrupted content + */ + if (len != DMU_OBJECT_END) + len -= LUSTRE_ENCRYPTION_UNIT_SIZE - + (off & ~LUSTRE_ENCRYPTION_MASK); + if (obj->oo_lma_flags & LUSTRE_ENCRYPT_FL && + off & ~LUSTRE_ENCRYPTION_MASK) + off = (off & LUSTRE_ENCRYPTION_MASK) + + LUSTRE_ENCRYPTION_UNIT_SIZE; + + /* XXX: dnode_free_range() can be used to save on dnode lookup */ if (off < size) dmu_free_range(os, dn->dn_object, off, len, tx); @@ -1069,8 +1083,8 @@ static int osd_punch(const struct lu_env *env, struct dt_object *dt, len = end - start; write_unlock(&obj->oo_attr_lock); - rc = __osd_object_punch(osd->od_os, obj->oo_dn, oh->ot_tx, - obj->oo_attr.la_size, start, len); + rc = __osd_object_punch(obj, osd->od_os, oh->ot_tx, start, len); + /* set new size */ if (len == DMU_OBJECT_END) { write_lock(&obj->oo_attr_lock); @@ -1100,6 +1114,14 @@ static int osd_declare_punch(const struct lu_env *env, struct dt_object *dt, len = end - start; /* declare we'll free some blocks ... */ + /* if object holds encrypted content, we need to make sure we truncate + * on an encryption unit boundary, or subsequent reads will get + * corrupted content + */ + if (obj->oo_lma_flags & LUSTRE_ENCRYPT_FL && + start & ~LUSTRE_ENCRYPTION_MASK) + start = (start & LUSTRE_ENCRYPTION_MASK) + + LUSTRE_ENCRYPTION_UNIT_SIZE; if (start < obj->oo_attr.la_size) { read_unlock(&obj->oo_attr_lock); dmu_tx_mark_netfree(oh->ot_tx); @@ -1142,7 +1164,8 @@ static int osd_fallocate(const struct lu_env *env, struct dt_object *dt, } static int osd_declare_fallocate(const struct lu_env *env, - struct dt_object *dt, struct thandle *th) + struct dt_object *dt, __u64 start, __u64 end, + int mode, struct thandle *th) { int rc = -EOPNOTSUPP; ENTRY; @@ -1154,6 +1177,48 @@ static int osd_declare_fallocate(const struct lu_env *env, RETURN(rc); } +static loff_t osd_lseek(const struct lu_env *env, struct dt_object *dt, + loff_t offset, int whence) +{ + struct osd_object *obj = osd_dt_obj(dt); + uint64_t size = obj->oo_attr.la_size; + uint64_t result = offset; + int rc; + boolean_t hole = whence == SEEK_HOLE; + + ENTRY; + + LASSERT(dt_object_exists(dt)); + LASSERT(osd_invariant(obj)); + LASSERT(offset >= 0); + + /* for SEEK_HOLE treat 'offset' beyond the end of file as in real + * hole. LOV to decide after all if that real hole or not. + */ + if (offset >= size) + RETURN(hole ? offset : -ENXIO); + + rc = osd_dmu_offset_next(osd_obj2dev(obj)->od_os, + obj->oo_dn->dn_object, hole, &result); + if (rc == ESRCH) + RETURN(-ENXIO); + + /* file was dirty, so fall back to using generic logic: + * For HOLE return file size, for DATA the result is set + * already to the 'offset' parameter value. + */ + if (rc == EBUSY && hole) + result = size; + + /* dmu_offset_next() only works on whole blocks so may return SEEK_HOLE + * result as end of the last block instead of logical EOF which we need + */ + if (result > size) + result = size; + + RETURN(result); +} + struct dt_body_operations osd_body_ops = { .dbo_read = osd_read, .dbo_declare_write = osd_declare_write, @@ -1169,6 +1234,7 @@ struct dt_body_operations osd_body_ops = { .dbo_ladvise = osd_ladvise, .dbo_declare_fallocate = osd_declare_fallocate, .dbo_fallocate = osd_fallocate, + .dbo_lseek = osd_lseek, }; struct dt_body_operations osd_body_scrub_ops = {