exofs: Add offset/length to exofs_get_io_state

In future raid code we will need to know the IO offset/length
and if it's a read or write to determine some of the array
sizes we'll need.

So add a new exofs_get_rw_state() API for use when
writeing/reading. All other simple cases are left using the
old way.

The major change to this is that now we need to call
exofs_get_io_state later at inode.c::read_exec and
inode.c::write_exec when we actually know these things. So this
patch is kept separate so I can test things apart from other
changes.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h
index 9f62349..fd913dd 100644
--- a/fs/exofs/exofs.h
+++ b/fs/exofs/exofs.h
@@ -109,7 +109,7 @@
 }
 
 struct exofs_io_state;
-typedef void (*exofs_io_done_fn)(struct exofs_io_state *or, void *private);
+typedef void (*exofs_io_done_fn)(struct exofs_io_state *ios, void *private);
 
 struct exofs_io_state {
 	struct kref		kref;
@@ -137,6 +137,8 @@
 	unsigned		out_attr_len;
 	struct osd_attr 	*out_attr;
 
+	bool			reading;
+
 	/* Variable array of size numdevs */
 	unsigned numdevs;
 	struct exofs_per_dev_state {
@@ -218,6 +220,8 @@
 int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj,
 		    u64 offset, void *p, unsigned length);
 
+int  exofs_get_rw_state(struct exofs_layout *layout, bool is_reading,
+			u64 offset, u64 length, struct exofs_io_state **ios);
 int  exofs_get_io_state(struct exofs_layout *layout,
 			struct exofs_io_state **ios);
 void exofs_put_io_state(struct exofs_io_state *ios);
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index 8472c09..ba9f0be 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -110,13 +110,6 @@
 {
 	unsigned pages;
 
-	if (!pcol->ios) { /* First time allocate io_state */
-		int ret = exofs_get_io_state(&pcol->sbi->layout, &pcol->ios);
-
-		if (ret)
-			return ret;
-	}
-
 	/* TODO: easily support bio chaining */
 	pages =  exofs_max_io_pages(&pcol->sbi->layout, pcol->expected_pages);
 
@@ -269,17 +262,25 @@
 static int read_exec(struct page_collect *pcol)
 {
 	struct exofs_i_info *oi = exofs_i(pcol->inode);
-	struct exofs_io_state *ios = pcol->ios;
+	struct exofs_io_state *ios;
 	struct page_collect *pcol_copy = NULL;
 	int ret;
 
 	if (!pcol->pages)
 		return 0;
 
+	if (!pcol->ios) {
+		int ret = exofs_get_rw_state(&pcol->sbi->layout, true,
+					     pcol->pg_first << PAGE_CACHE_SHIFT,
+					     pcol->length, &pcol->ios);
+
+		if (ret)
+			return ret;
+	}
+
+	ios = pcol->ios;
 	ios->pages = pcol->pages;
 	ios->nr_pages = pcol->nr_pages;
-	ios->length = pcol->length;
-	ios->offset = pcol->pg_first << PAGE_CACHE_SHIFT;
 
 	if (pcol->read_4_write) {
 		exofs_oi_read(oi, pcol->ios);
@@ -507,13 +508,21 @@
 static int write_exec(struct page_collect *pcol)
 {
 	struct exofs_i_info *oi = exofs_i(pcol->inode);
-	struct exofs_io_state *ios = pcol->ios;
+	struct exofs_io_state *ios;
 	struct page_collect *pcol_copy = NULL;
 	int ret;
 
 	if (!pcol->pages)
 		return 0;
 
+	BUG_ON(pcol->ios);
+	ret = exofs_get_rw_state(&pcol->sbi->layout, false,
+				 pcol->pg_first << PAGE_CACHE_SHIFT,
+				 pcol->length, &pcol->ios);
+
+	if (unlikely(ret))
+		goto err;
+
 	pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL);
 	if (!pcol_copy) {
 		EXOFS_ERR("write_exec: Failed to kmalloc(pcol)\n");
@@ -523,10 +532,9 @@
 
 	*pcol_copy = *pcol;
 
+	ios = pcol->ios;
 	ios->pages = pcol_copy->pages;
 	ios->nr_pages = pcol_copy->nr_pages;
-	ios->offset = pcol_copy->pg_first << PAGE_CACHE_SHIFT;
-	ios->length = pcol_copy->length;
 	ios->done = writepages_done;
 	ios->private = pcol_copy;
 
diff --git a/fs/exofs/ios.c b/fs/exofs/ios.c
index fbb47ba..096405e5 100644
--- a/fs/exofs/ios.c
+++ b/fs/exofs/ios.c
@@ -69,8 +69,8 @@
 	return ret;
 }
 
-int exofs_get_io_state(struct exofs_layout *layout,
-		       struct exofs_io_state **pios)
+int  exofs_get_rw_state(struct exofs_layout *layout, bool is_reading,
+			u64 offset, u64 length, struct exofs_io_state **pios)
 {
 	struct exofs_io_state *ios;
 
@@ -87,10 +87,20 @@
 
 	ios->layout = layout;
 	ios->obj.partition = layout->s_pid;
+	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_io_state **ios)
+{
+	return exofs_get_rw_state(layout, true, 0, 0, ios);
+}
+
 void exofs_put_io_state(struct exofs_io_state *ios)
 {
 	if (ios) {