+/* REMOVEME: After review
+ Some quoteing from the standard
+
+ L = logical offset into the file
+ W = number of data components in a stripe
+ S = W * stripe_unit (S is Stripe length)
+ N = L / S (N is the stripe Number)
+ C = (L-(N*S)) / stripe_unit (C is the component)
+ O = (N*stripe_unit)+(L%stripe_unit) (O is the object's offset)
+*/
+
+static void _offset_dev_unit_off(struct exofs_io_state *ios, u64 file_offset,
+ u64 *obj_offset, unsigned *dev, unsigned *unit_off)
+{
+ unsigned stripe_unit = ios->layout->stripe_unit;
+ unsigned stripe_length = stripe_unit * ios->layout->group_width;
+ u64 stripe_no = file_offset;
+ unsigned stripe_mod = do_div(stripe_no, stripe_length);
+
+ *unit_off = stripe_mod % stripe_unit;
+ *obj_offset = stripe_no * stripe_unit + *unit_off;
+ *dev = stripe_mod / stripe_unit * ios->layout->mirrors_p1;
+}
+
+static int _add_stripe_unit(struct exofs_io_state *ios, unsigned *cur_bvec,
+ struct exofs_per_dev_state *per_dev, int cur_len)
+{
+ unsigned bv = *cur_bvec;
+ struct request_queue *q =
+ osd_request_queue(exofs_ios_od(ios, per_dev->dev));
+
+ per_dev->length += cur_len;
+
+ if (per_dev->bio == NULL) {
+ unsigned pages_in_stripe = ios->layout->group_width *
+ (ios->layout->stripe_unit / PAGE_SIZE);
+ unsigned bio_size = (ios->bio->bi_vcnt + pages_in_stripe) /
+ ios->layout->group_width;
+
+ per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size);
+ if (unlikely(!per_dev->bio)) {
+ EXOFS_DBGMSG("Faild to allocate BIO size=%u\n",
+ bio_size);
+ return -ENOMEM;
+ }
+ }
+
+ while (cur_len > 0) {
+ int added_len;
+ struct bio_vec *bvec = &ios->bio->bi_io_vec[bv];
+
+ BUG_ON(ios->bio->bi_vcnt <= bv);
+ cur_len -= bvec->bv_len;
+
+ added_len = bio_add_pc_page(q, per_dev->bio, bvec->bv_page,
+ bvec->bv_len, bvec->bv_offset);
+ if (unlikely(bvec->bv_len != added_len))
+ return -ENOMEM;
+ ++bv;
+ }
+ BUG_ON(cur_len);
+
+ *cur_bvec = bv;
+ return 0;
+}
+
+static int _prepare_for_striping(struct exofs_io_state *ios)
+{
+ u64 length = ios->length;
+ u64 offset = ios->offset;
+ unsigned stripe_unit = ios->layout->stripe_unit;
+ unsigned comp = 0;
+ unsigned stripes = 0;
+ unsigned cur_bvec = 0;
+ int ret;
+
+ if (!ios->bio) {
+ if (ios->kern_buff) {
+ struct exofs_per_dev_state *per_dev = &ios->per_dev[0];
+ unsigned unit_off;
+
+ _offset_dev_unit_off(ios, offset, &per_dev->offset,
+ &per_dev->dev, &unit_off);
+ /* no cross device without page array */
+ BUG_ON((ios->layout->group_width > 1) &&
+ (unit_off + length > stripe_unit));
+ }
+ ios->numdevs = ios->layout->mirrors_p1;
+ return 0;
+ }
+
+ while (length) {
+ struct exofs_per_dev_state *per_dev = &ios->per_dev[comp];
+ unsigned cur_len;
+
+ if (!per_dev->length) {
+ unsigned unit_off;
+
+ _offset_dev_unit_off(ios, offset, &per_dev->offset,
+ &per_dev->dev, &unit_off);
+ stripes++;
+ cur_len = min_t(u64, stripe_unit - unit_off, length);
+ offset += cur_len;
+ } else {
+ cur_len = min_t(u64, stripe_unit, length);
+ }
+
+ ret = _add_stripe_unit(ios, &cur_bvec, per_dev, cur_len);
+ if (unlikely(ret))
+ goto out;
+
+ comp += ios->layout->mirrors_p1;
+ comp %= ios->layout->s_numdevs;
+
+ length -= cur_len;
+ }
+out:
+ ios->numdevs = stripes * ios->layout->mirrors_p1;
+ return ret;
+}
+