exofs: ios: Move to a per inode components & device-table
[firefly-linux-kernel-4.4.55.git] / fs / exofs / ios.c
index f74a2ec027a643cf9685840fe4a148ab444335d1..f9d5c5a823fbdf454bef08277a837db892b3194f 100644 (file)
 #define EXOFS_DBGMSG2(M...) do {} while (0)
 /* #define EXOFS_DBGMSG2 EXOFS_DBGMSG */
 
-void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], const struct osd_obj_id *obj)
+static u8 *_ios_cred(struct exofs_io_state *ios, unsigned index)
 {
-       osd_sec_init_nosec_doall_caps(cred_a, obj, false, true);
+       return ios->comps->comps[index & ios->comps->single_comp].cred;
 }
 
-int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj,
-                   u64 offset, void *p, unsigned length)
+static struct osd_obj_id *_ios_obj(struct exofs_io_state *ios, unsigned index)
 {
-       struct osd_request *or = osd_start_request(od, GFP_KERNEL);
-/*     struct osd_sense_info osi = {.key = 0};*/
-       int ret;
-
-       if (unlikely(!or)) {
-               EXOFS_DBGMSG("%s: osd_start_request failed.\n", __func__);
-               return -ENOMEM;
-       }
-       ret = osd_req_read_kern(or, obj, offset, p, length);
-       if (unlikely(ret)) {
-               EXOFS_DBGMSG("%s: osd_req_read_kern failed.\n", __func__);
-               goto out;
-       }
-
-       ret = osd_finalize_request(or, 0, cred, NULL);
-       if (unlikely(ret)) {
-               EXOFS_DBGMSG("Failed to osd_finalize_request() => %d\n", ret);
-               goto out;
-       }
-
-       ret = osd_execute_request(or);
-       if (unlikely(ret))
-               EXOFS_DBGMSG("osd_execute_request() => %d\n", ret);
-       /* osd_req_decode_sense(or, ret); */
+       return &ios->comps->comps[index & ios->comps->single_comp].obj;
+}
 
-out:
-       osd_end_request(or);
-       return ret;
+static struct osd_dev *_ios_od(struct exofs_io_state *ios, unsigned index)
+{
+       return ios->comps->ods[index];
 }
 
-int exofs_get_io_state(struct exofs_layout *layout,
-                      struct exofs_io_state **pios)
+int exofs_get_rw_state(struct exofs_layout *layout,
+                       struct exofs_components *comps,
+                       bool is_reading, u64 offset, u64 length,
+                       struct exofs_io_state **pios)
 {
        struct exofs_io_state *ios;
 
        /*TODO: Maybe use kmem_cach per sbi of size
         * exofs_io_state_size(layout->s_numdevs)
         */
-       ios = kzalloc(exofs_io_state_size(layout->s_numdevs), GFP_KERNEL);
+       ios = kzalloc(exofs_io_state_size(comps->numdevs), GFP_KERNEL);
        if (unlikely(!ios)) {
                EXOFS_DBGMSG("Failed kzalloc bytes=%d\n",
-                            exofs_io_state_size(layout->s_numdevs));
+                            exofs_io_state_size(comps->numdevs));
                *pios = NULL;
                return -ENOMEM;
        }
 
        ios->layout = layout;
-       ios->obj.partition = layout->s_pid;
+       ios->comps = comps;
+       ios->offset = offset;
+       ios->length = length;
+       ios->reading = is_reading;
+
        *pios = ios;
        return 0;
 }
 
+int  exofs_get_io_state(struct exofs_layout *layout,
+                       struct exofs_components *comps,
+                       struct exofs_io_state **ios)
+{
+       return exofs_get_rw_state(layout, comps, true, 0, 0, ios);
+}
+
 void exofs_put_io_state(struct exofs_io_state *ios)
 {
        if (ios) {
@@ -109,29 +99,6 @@ void exofs_put_io_state(struct exofs_io_state *ios)
        }
 }
 
-unsigned exofs_layout_od_id(struct exofs_layout *layout,
-                           osd_id obj_no, unsigned layout_index)
-{
-/*     switch (layout->lay_func) {
-       case LAYOUT_MOVING_WINDOW:
-       {*/
-               unsigned dev_mod = obj_no;
-
-               return (layout_index + dev_mod * layout->mirrors_p1) %
-                                                             layout->s_numdevs;
-/*     }
-       case LAYOUT_FUNC_IMPLICT:
-               return layout->devs[layout_index];
-       }*/
-}
-
-static inline struct osd_dev *exofs_ios_od(struct exofs_io_state *ios,
-                                          unsigned layout_index)
-{
-       return ios->layout->s_ods[
-               exofs_layout_od_id(ios->layout, ios->obj.id, layout_index)];
-}
-
 static void _sync_done(struct exofs_io_state *ios, void *p)
 {
        struct completion *waiting = p;
@@ -170,7 +137,7 @@ static int exofs_io_execute(struct exofs_io_state *ios)
                if (unlikely(!or))
                        continue;
 
-               ret = osd_finalize_request(or, 0, ios->cred, NULL);
+               ret = osd_finalize_request(or, 0, _ios_cred(ios, i), NULL);
                if (unlikely(ret)) {
                        EXOFS_DBGMSG("Failed to osd_finalize_request() => %d\n",
                                     ret);
@@ -305,20 +272,21 @@ int exofs_check_io(struct exofs_io_state *ios, u64 *resid)
 struct _striping_info {
        u64 obj_offset;
        u64 group_length;
+       u64 M; /* for truncate */
        unsigned dev;
        unsigned unit_off;
 };
 
-static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset,
+static void _calc_stripe_info(struct exofs_layout *layout, u64 file_offset,
                              struct _striping_info *si)
 {
-       u32     stripe_unit = ios->layout->stripe_unit;
-       u32     group_width = ios->layout->group_width;
-       u64     group_depth = ios->layout->group_depth;
+       u32     stripe_unit = layout->stripe_unit;
+       u32     group_width = layout->group_width;
+       u64     group_depth = layout->group_depth;
 
        u32     U = stripe_unit * group_width;
        u64     T = U * group_depth;
-       u64     S = T * ios->layout->group_count;
+       u64     S = T * layout->group_count;
        u64     M = div64_u64(file_offset, S);
 
        /*
@@ -333,7 +301,7 @@ static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset,
 
        /* "H - (N * U)" is just "H % U" so it's bound to u32 */
        si->dev = (u32)(H - (N * U)) / stripe_unit + G * group_width;
-       si->dev *= ios->layout->mirrors_p1;
+       si->dev *= layout->mirrors_p1;
 
        div_u64_rem(file_offset, stripe_unit, &si->unit_off);
 
@@ -341,6 +309,7 @@ static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset,
                                  (M * group_depth * stripe_unit);
 
        si->group_length = T - H;
+       si->M = M;
 }
 
 static int _add_stripe_unit(struct exofs_io_state *ios,  unsigned *cur_pg,
@@ -349,7 +318,7 @@ static int _add_stripe_unit(struct exofs_io_state *ios,  unsigned *cur_pg,
 {
        unsigned pg = *cur_pg;
        struct request_queue *q =
-                       osd_request_queue(exofs_ios_od(ios, per_dev->dev));
+                       osd_request_queue(_ios_od(ios, per_dev->dev));
 
        per_dev->length += cur_len;
 
@@ -454,7 +423,7 @@ static int _prepare_for_striping(struct exofs_io_state *ios)
                if (ios->kern_buff) {
                        struct exofs_per_dev_state *per_dev = &ios->per_dev[0];
 
-                       _calc_stripe_info(ios, ios->offset, &si);
+                       _calc_stripe_info(ios->layout, ios->offset, &si);
                        per_dev->offset = si.obj_offset;
                        per_dev->dev = si.dev;
 
@@ -468,7 +437,7 @@ static int _prepare_for_striping(struct exofs_io_state *ios)
        }
 
        while (length) {
-               _calc_stripe_info(ios, offset, &si);
+               _calc_stripe_info(ios->layout, offset, &si);
 
                if (length < si.group_length)
                        si.group_length = length;
@@ -489,10 +458,10 @@ int exofs_sbi_create(struct exofs_io_state *ios)
 {
        int i, ret;
 
-       for (i = 0; i < ios->layout->s_numdevs; i++) {
+       for (i = 0; i < ios->comps->numdevs; i++) {
                struct osd_request *or;
 
-               or = osd_start_request(exofs_ios_od(ios, i), GFP_KERNEL);
+               or = osd_start_request(_ios_od(ios, i), GFP_KERNEL);
                if (unlikely(!or)) {
                        EXOFS_ERR("%s: osd_start_request failed\n", __func__);
                        ret = -ENOMEM;
@@ -501,7 +470,7 @@ int exofs_sbi_create(struct exofs_io_state *ios)
                ios->per_dev[i].or = or;
                ios->numdevs++;
 
-               osd_req_create_object(or, &ios->obj);
+               osd_req_create_object(or, _ios_obj(ios, i));
        }
        ret = exofs_io_execute(ios);
 
@@ -513,10 +482,10 @@ int exofs_sbi_remove(struct exofs_io_state *ios)
 {
        int i, ret;
 
-       for (i = 0; i < ios->layout->s_numdevs; i++) {
+       for (i = 0; i < ios->comps->numdevs; i++) {
                struct osd_request *or;
 
-               or = osd_start_request(exofs_ios_od(ios, i), GFP_KERNEL);
+               or = osd_start_request(_ios_od(ios, i), GFP_KERNEL);
                if (unlikely(!or)) {
                        EXOFS_ERR("%s: osd_start_request failed\n", __func__);
                        ret = -ENOMEM;
@@ -525,7 +494,7 @@ int exofs_sbi_remove(struct exofs_io_state *ios)
                ios->per_dev[i].or = or;
                ios->numdevs++;
 
-               osd_req_remove_object(or, &ios->obj);
+               osd_req_remove_object(or, _ios_obj(ios, i));
        }
        ret = exofs_io_execute(ios);
 
@@ -547,7 +516,7 @@ static int _sbi_write_mirror(struct exofs_io_state *ios, int cur_comp)
                struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
                struct osd_request *or;
 
-               or = osd_start_request(exofs_ios_od(ios, dev), GFP_KERNEL);
+               or = osd_start_request(_ios_od(ios, dev), GFP_KERNEL);
                if (unlikely(!or)) {
                        EXOFS_ERR("%s: osd_start_request failed\n", __func__);
                        ret = -ENOMEM;
@@ -582,25 +551,29 @@ static int _sbi_write_mirror(struct exofs_io_state *ios, int cur_comp)
                                bio->bi_rw |= REQ_WRITE;
                        }
 
-                       osd_req_write(or, &ios->obj, per_dev->offset, bio,
-                                     per_dev->length);
+                       osd_req_write(or, _ios_obj(ios, dev), per_dev->offset,
+                                     bio, per_dev->length);
                        EXOFS_DBGMSG("write(0x%llx) offset=0x%llx "
                                      "length=0x%llx dev=%d\n",
-                                    _LLU(ios->obj.id), _LLU(per_dev->offset),
+                                    _LLU(_ios_obj(ios, dev)->id),
+                                    _LLU(per_dev->offset),
                                     _LLU(per_dev->length), dev);
                } else if (ios->kern_buff) {
-                       ret = osd_req_write_kern(or, &ios->obj, per_dev->offset,
-                                          ios->kern_buff, ios->length);
+                       ret = osd_req_write_kern(or, _ios_obj(ios, dev),
+                                                per_dev->offset,
+                                                ios->kern_buff, ios->length);
                        if (unlikely(ret))
                                goto out;
                        EXOFS_DBGMSG2("write_kern(0x%llx) offset=0x%llx "
                                      "length=0x%llx dev=%d\n",
-                                    _LLU(ios->obj.id), _LLU(per_dev->offset),
+                                    _LLU(_ios_obj(ios, dev)->id),
+                                    _LLU(per_dev->offset),
                                     _LLU(ios->length), dev);
                } else {
-                       osd_req_set_attributes(or, &ios->obj);
+                       osd_req_set_attributes(or, _ios_obj(ios, dev));
                        EXOFS_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n",
-                                    _LLU(ios->obj.id), ios->out_attr_len, dev);
+                                    _LLU(_ios_obj(ios, dev)->id),
+                                    ios->out_attr_len, dev);
                }
 
                if (ios->out_attr)
@@ -639,13 +612,14 @@ static int _sbi_read_mirror(struct exofs_io_state *ios, unsigned cur_comp)
 {
        struct osd_request *or;
        struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
-       unsigned first_dev = (unsigned)ios->obj.id;
+       struct osd_obj_id *obj = _ios_obj(ios, cur_comp);
+       unsigned first_dev = (unsigned)obj->id;
 
        if (ios->pages && !per_dev->length)
                return 0; /* Just an empty slot */
 
        first_dev = per_dev->dev + first_dev % ios->layout->mirrors_p1;
-       or = osd_start_request(exofs_ios_od(ios, first_dev), GFP_KERNEL);
+       or = osd_start_request(_ios_od(ios, first_dev), GFP_KERNEL);
        if (unlikely(!or)) {
                EXOFS_ERR("%s: osd_start_request failed\n", __func__);
                return -ENOMEM;
@@ -653,25 +627,26 @@ static int _sbi_read_mirror(struct exofs_io_state *ios, unsigned cur_comp)
        per_dev->or = or;
 
        if (ios->pages) {
-               osd_req_read(or, &ios->obj, per_dev->offset,
+               osd_req_read(or, obj, per_dev->offset,
                                per_dev->bio, per_dev->length);
                EXOFS_DBGMSG("read(0x%llx) offset=0x%llx length=0x%llx"
-                            " dev=%d\n", _LLU(ios->obj.id),
+                            " dev=%d\n", _LLU(obj->id),
                             _LLU(per_dev->offset), _LLU(per_dev->length),
                             first_dev);
        } else if (ios->kern_buff) {
-               int ret = osd_req_read_kern(or, &ios->obj, per_dev->offset,
+               int ret = osd_req_read_kern(or, obj, per_dev->offset,
                                            ios->kern_buff, ios->length);
                EXOFS_DBGMSG2("read_kern(0x%llx) offset=0x%llx "
                              "length=0x%llx dev=%d ret=>%d\n",
-                             _LLU(ios->obj.id), _LLU(per_dev->offset),
+                             _LLU(obj->id), _LLU(per_dev->offset),
                              _LLU(ios->length), first_dev, ret);
                if (unlikely(ret))
                        return ret;
        } else {
-               osd_req_get_attributes(or, &ios->obj);
+               osd_req_get_attributes(or, obj);
                EXOFS_DBGMSG2("obj(0x%llx) get_attributes=%d dev=%d\n",
-                             _LLU(ios->obj.id), ios->in_attr_len, first_dev);
+                             _LLU(obj->id),
+                             ios->in_attr_len, first_dev);
        }
        if (ios->out_attr)
                osd_req_add_set_attr_list(or, ios->out_attr, ios->out_attr_len);
@@ -731,64 +706,93 @@ static int _truncate_mirrors(struct exofs_io_state *ios, unsigned cur_comp,
                struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
                struct osd_request *or;
 
-               or = osd_start_request(exofs_ios_od(ios, cur_comp), GFP_KERNEL);
+               or = osd_start_request(_ios_od(ios, cur_comp), GFP_KERNEL);
                if (unlikely(!or)) {
                        EXOFS_ERR("%s: osd_start_request failed\n", __func__);
                        return -ENOMEM;
                }
                per_dev->or = or;
 
-               osd_req_set_attributes(or, &ios->obj);
+               osd_req_set_attributes(or, _ios_obj(ios, cur_comp));
                osd_req_add_set_attr_list(or, attr, 1);
        }
 
        return 0;
 }
 
-int exofs_oi_truncate(struct exofs_i_info *oi, u64 size)
+struct _trunc_info {
+       struct _striping_info si;
+       u64 prev_group_obj_off;
+       u64 next_group_obj_off;
+
+       unsigned first_group_dev;
+       unsigned nex_group_dev;
+       unsigned max_devs;
+};
+
+void _calc_trunk_info(struct exofs_layout *layout, u64 file_offset,
+                      struct _trunc_info *ti)
+{
+       unsigned stripe_unit = layout->stripe_unit;
+
+       _calc_stripe_info(layout, file_offset, &ti->si);
+
+       ti->prev_group_obj_off = ti->si.M * stripe_unit;
+       ti->next_group_obj_off = ti->si.M ? (ti->si.M - 1) * stripe_unit : 0;
+
+       ti->first_group_dev = ti->si.dev - (ti->si.dev % layout->group_width);
+       ti->nex_group_dev = ti->first_group_dev + layout->group_width;
+       ti->max_devs = layout->group_width * layout->group_count;
+}
+
+int exofs_truncate(struct exofs_layout *layout, struct exofs_components *comps,
+                  u64 size)
 {
-       struct exofs_sb_info *sbi = oi->vfs_inode.i_sb->s_fs_info;
        struct exofs_io_state *ios;
        struct exofs_trunc_attr {
                struct osd_attr attr;
                __be64 newsize;
        } *size_attrs;
-       struct _striping_info si;
+       struct _trunc_info ti;
        int i, ret;
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = exofs_get_io_state(layout, comps, &ios);
        if (unlikely(ret))
                return ret;
 
-       size_attrs = kcalloc(ios->layout->group_width, sizeof(*size_attrs),
+       _calc_trunk_info(ios->layout, size, &ti);
+
+       size_attrs = kcalloc(ti.max_devs, sizeof(*size_attrs),
                             GFP_KERNEL);
        if (unlikely(!size_attrs)) {
                ret = -ENOMEM;
                goto out;
        }
 
-       ios->obj.id = exofs_oi_objno(oi);
-       ios->cred = oi->i_cred;
+       ios->numdevs = ios->comps->numdevs;
 
-       ios->numdevs = ios->layout->s_numdevs;
-       _calc_stripe_info(ios, size, &si);
-
-       for (i = 0; i < ios->layout->group_width; ++i) {
+       for (i = 0; i < ti.max_devs; ++i) {
                struct exofs_trunc_attr *size_attr = &size_attrs[i];
                u64 obj_size;
 
-               if (i < si.dev)
-                       obj_size = si.obj_offset +
-                                       ios->layout->stripe_unit - si.unit_off;
-               else if (i == si.dev)
-                       obj_size = si.obj_offset;
-               else /* i > si.dev */
-                       obj_size = si.obj_offset - si.unit_off;
+               if (i < ti.first_group_dev)
+                       obj_size = ti.prev_group_obj_off;
+               else if (i >= ti.nex_group_dev)
+                       obj_size = ti.next_group_obj_off;
+               else if (i < ti.si.dev) /* dev within this group */
+                       obj_size = ti.si.obj_offset +
+                                     ios->layout->stripe_unit - ti.si.unit_off;
+               else if (i == ti.si.dev)
+                       obj_size = ti.si.obj_offset;
+               else /* i > ti.dev */
+                       obj_size = ti.si.obj_offset - ti.si.unit_off;
 
                size_attr->newsize = cpu_to_be64(obj_size);
                size_attr->attr = g_attr_logical_length;
                size_attr->attr.val_ptr = &size_attr->newsize;
 
+               EXOFS_DBGMSG("trunc(0x%llx) obj_offset=0x%llx dev=%d\n",
+                            _LLU(comps->comps->obj.id), _LLU(obj_size), i);
                ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1,
                                        &size_attr->attr);
                if (unlikely(ret))
@@ -801,3 +805,6 @@ out:
        exofs_put_io_state(ios);
        return ret;
 }
+
+const struct osd_attr g_attr_logical_length = ATTR_DEF(
+       OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);