summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/exofs/ios.c159
1 files changed, 99 insertions, 60 deletions
diff --git a/fs/exofs/ios.c b/fs/exofs/ios.c
index 263052c77f4..d28febdf54a 100644
--- a/fs/exofs/ios.c
+++ b/fs/exofs/ios.c
@@ -259,28 +259,46 @@ int exofs_check_io(struct exofs_io_state *ios, u64 *resid)
return acumulated_lin_err;
}
-/* 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)
+/*
+ * L - logical offset into the file
+ *
+ * U - The number of bytes in a full stripe
+ *
+ * U = stripe_unit * group_width
+ *
+ * N - The stripe number
+ *
+ * N = L / U
+ *
+ * C - The component index coresponding to L
+ *
+ * C = (L - (N*U)) / stripe_unit
+ *
+ * O - The component offset coresponding to L
+ *
+ * (N*stripe_unit)+(L%stripe_unit)
+ */
+
+struct _striping_info {
+ u64 obj_offset;
+ unsigned dev;
+ unsigned unit_off;
+};
+
+static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset,
+ struct _striping_info *si)
{
- 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);
+ u32 stripe_unit = ios->layout->stripe_unit;
+ u32 group_width = ios->layout->group_width;
+ u32 U = stripe_unit * group_width;
+
+ u32 LmodU;
+ u64 N = div_u64_rem(file_offset, U, &LmodU);
- *unit_off = stripe_mod % stripe_unit;
- *obj_offset = stripe_no * stripe_unit + *unit_off;
- *dev = stripe_mod / stripe_unit * ios->layout->mirrors_p1;
+ si->unit_off = LmodU % stripe_unit;
+ si->obj_offset = N * stripe_unit + si->unit_off;
+ si->dev = LmodU / stripe_unit;
+ si->dev *= ios->layout->mirrors_p1;
}
static int _add_stripe_unit(struct exofs_io_state *ios, unsigned *cur_pg,
@@ -327,65 +345,88 @@ static int _add_stripe_unit(struct exofs_io_state *ios, unsigned *cur_pg,
return 0;
}
-static int _prepare_for_striping(struct exofs_io_state *ios)
+static int _prepare_pages(struct exofs_io_state *ios,
+ struct _striping_info *si)
{
u64 length = ios->length;
- u64 offset = ios->offset;
unsigned stripe_unit = ios->layout->stripe_unit;
+ unsigned mirrors_p1 = ios->layout->mirrors_p1;
+ unsigned dev = si->dev;
unsigned comp = 0;
unsigned stripes = 0;
unsigned cur_pg = 0;
int ret = 0;
- if (!ios->pages) {
- 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, page_off;
+ unsigned cur_len, page_off = 0;
if (!per_dev->length) {
- unsigned unit_off;
+ per_dev->dev = dev;
+ if (dev < si->dev) {
+ per_dev->offset = si->obj_offset + stripe_unit -
+ si->unit_off;
+ cur_len = stripe_unit;
+ } else if (dev == si->dev) {
+ per_dev->offset = si->obj_offset;
+ cur_len = stripe_unit - si->unit_off;
+ page_off = si->unit_off & ~PAGE_MASK;
+ BUG_ON(page_off && (page_off != ios->pgbase));
+ } else { /* dev > si->dev */
+ per_dev->offset = si->obj_offset - si->unit_off;
+ cur_len = stripe_unit;
+ }
- _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;
- page_off = unit_off & ~PAGE_MASK;
- BUG_ON(page_off != ios->pgbase);
+
+ dev += mirrors_p1;
+ dev %= ios->layout->s_numdevs;
} else {
- cur_len = min_t(u64, stripe_unit, length);
- page_off = 0;
+ cur_len = stripe_unit;
}
+ if (cur_len >= length)
+ cur_len = length;
ret = _add_stripe_unit(ios, &cur_pg, page_off , per_dev,
cur_len);
if (unlikely(ret))
goto out;
- comp += ios->layout->mirrors_p1;
+ comp += mirrors_p1;
comp %= ios->layout->s_numdevs;
length -= cur_len;
}
out:
- ios->numdevs = stripes * ios->layout->mirrors_p1;
+ ios->numdevs = stripes * mirrors_p1;
return ret;
}
+static int _prepare_for_striping(struct exofs_io_state *ios)
+{
+ struct _striping_info si;
+
+ _calc_stripe_info(ios, ios->offset, &si);
+
+ if (!ios->pages) {
+ if (ios->kern_buff) {
+ struct exofs_per_dev_state *per_dev = &ios->per_dev[0];
+
+ per_dev->offset = si.obj_offset;
+ per_dev->dev = si.dev;
+
+ /* no cross device without page array */
+ BUG_ON((ios->layout->group_width > 1) &&
+ (si.unit_off + ios->length >
+ ios->layout->stripe_unit));
+ }
+ ios->numdevs = ios->layout->mirrors_p1;
+ return 0;
+ }
+
+ return _prepare_pages(ios, &si);
+}
+
int exofs_sbi_create(struct exofs_io_state *ios)
{
int i, ret;
@@ -648,9 +689,7 @@ int exofs_oi_truncate(struct exofs_i_info *oi, u64 size)
struct osd_attr attr;
__be64 newsize;
} *size_attrs;
- u64 this_obj_size;
- unsigned dev;
- unsigned unit_off;
+ struct _striping_info si;
int i, ret;
ret = exofs_get_io_state(&sbi->layout, &ios);
@@ -668,19 +707,19 @@ int exofs_oi_truncate(struct exofs_i_info *oi, u64 size)
ios->cred = oi->i_cred;
ios->numdevs = ios->layout->s_numdevs;
- _offset_dev_unit_off(ios, size, &this_obj_size, &dev, &unit_off);
+ _calc_stripe_info(ios, size, &si);
for (i = 0; i < ios->layout->group_width; ++i) {
struct exofs_trunc_attr *size_attr = &size_attrs[i];
u64 obj_size;
- if (i < dev)
- obj_size = this_obj_size +
- ios->layout->stripe_unit - unit_off;
- else if (i == dev)
- obj_size = this_obj_size;
- else /* i > dev */
- obj_size = this_obj_size - unit_off;
+ 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;
size_attr->newsize = cpu_to_be64(obj_size);
size_attr->attr = g_attr_logical_length;