Whamcloud - gitweb
Reworked to have a dirty inode list on superblock, dirty pages per inode.
[fs/lustre-release.git] / lustre / obdfs / rw.c
1 /*
2  * OBDFS Super operations
3  *
4  * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de>
5  * Copryright (C) 1999 Stelias Computing Inc, 
6  *                (author Peter J. Braam <braam@stelias.com>)
7  * Copryright (C) 1999 Seagate Technology Inc.
8  */
9
10
11 #include <linux/config.h>
12 #include <linux/kernel.h>
13 #include <linux/mm.h>
14 #include <linux/string.h>
15 #include <linux/stat.h>
16 #include <linux/errno.h>
17 #include <linux/locks.h>
18 #include <linux/unistd.h>
19
20 #include <asm/system.h>
21 #include <asm/uaccess.h>
22
23 #include <linux/fs.h>
24 #include <linux/stat.h>
25 #include <asm/uaccess.h>
26 #include <linux/vmalloc.h>
27 #include <asm/segment.h>
28 #include <linux/mm.h>
29 #include <linux/pagemap.h>
30 #include <linux/smp_lock.h>
31
32 #include <linux/obd_support.h>
33 #include <linux/obd_ext2.h>
34 #include <linux/obdfs.h>
35
36
37 int obdfs_flush_reqs(struct list_head *page_list, 
38                      int flush_inode, int check_time);
39
40
41 /* SYNCHRONOUS I/O for an inode */
42 static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create)
43 {
44         obd_count        num_oa = 1;
45         obd_count        oa_bufs = 1;
46         struct obdo     *oa;
47         char            *buf = (char *)page_address(page);
48         obd_size         count = PAGE_SIZE;
49         obd_off          offset = ((obd_off)page->index) << PAGE_SHIFT;
50         obd_flag         flags = create ? OBD_BRW_CREATE : 0;
51         int              err;
52
53         ENTRY;
54         oa = obdo_fromid(IID(inode), inode->i_ino, OBD_MD_FLNOTOBD);
55         if ( IS_ERR(oa) ) {
56                 EXIT;
57                 return PTR_ERR(oa);
58         }
59         obdfs_from_inode(oa, inode);
60
61         err = IOPS(inode, brw)(rw, IID(inode), num_oa, &oa, &oa_bufs, &buf,
62                                &count, &offset, &flags);
63
64         if ( !err )
65                 obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */
66
67         obdo_free(oa);
68         
69         EXIT;
70         return err;
71 } /* obdfs_brw */
72
73 /* returns the page unlocked, but with a reference */
74 int obdfs_readpage(struct dentry *dentry, struct page *page)
75 {
76         struct inode *inode = dentry->d_inode;
77         int rc;
78
79         ENTRY;
80         PDEBUG(page, "READ");
81         rc = obdfs_brw(READ, inode, page, 0);
82         if ( !rc ) {
83                 SetPageUptodate(page);
84                 UnlockPage(page);
85         } 
86         PDEBUG(page, "READ");
87         EXIT;
88         return rc;
89 } /* obdfs_readpage */
90
91 static kmem_cache_t *obdfs_pgrq_cachep = NULL;
92
93 int obdfs_init_pgrqcache(void)
94 {
95         ENTRY;
96         if (obdfs_pgrq_cachep == NULL) {
97                 CDEBUG(D_INODE, "allocating obdfs_pgrq_cache\n");
98                 obdfs_pgrq_cachep = kmem_cache_create("obdfs_pgrq",
99                                                       sizeof(struct obdfs_pgrq),
100                                                       0, SLAB_HWCACHE_ALIGN,
101                                                       NULL, NULL);
102                 if (obdfs_pgrq_cachep == NULL) {
103                         EXIT;
104                         return -ENOMEM;
105                 } else {
106                         CDEBUG(D_INODE, "allocated cache at %p\n",
107                                obdfs_pgrq_cachep);
108                 }
109         } else {
110                 CDEBUG(D_INODE, "using existing cache at %p\n",
111                        obdfs_pgrq_cachep);
112         }
113         EXIT;
114         return 0;
115 } /* obdfs_init_wreqcache */
116
117 inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq)
118 {
119                 list_del(&pgrq->rq_plist);
120                 kmem_cache_free(obdfs_pgrq_cachep, pgrq);
121 }
122
123 void obdfs_cleanup_pgrqcache(void)
124 {
125         ENTRY;
126         if (obdfs_pgrq_cachep != NULL) {
127                 CDEBUG(D_INODE, "destroying obdfs_pgrqcache at %p\n",
128                        obdfs_pgrq_cachep);
129                 if (kmem_cache_destroy(obdfs_pgrq_cachep))
130                         printk(KERN_INFO "obd_cleanup_pgrqcache: unable to free all of cache\n");
131         } else
132                 printk(KERN_INFO "obd_cleanup_pgrqcache: called with NULL cache pointer\n");
133
134         EXIT;
135 } /* obdfs_cleanup_wreqcache */
136
137
138 /*
139  * Find a specific page in the page cache.  If it is found, we return
140  * the write request struct associated with it, if not found return NULL.
141  */
142 static struct obdfs_pgrq *
143 obdfs_find_in_page_list(struct inode *inode, struct page *page)
144 {
145         struct list_head *page_list = obdfs_iplist(inode);
146         struct list_head *tmp;
147         struct obdfs_pgrq *pgrq;
148
149         ENTRY;
150         CDEBUG(D_INODE, "looking for inode %ld page %p\n", inode->i_ino, page);
151         if (list_empty(page_list)) {
152                 CDEBUG(D_INODE, "empty list\n");
153                 EXIT;
154                 return NULL;
155         }
156         tmp = page_list;
157         while ( (tmp = tmp->next) != page_list ) {
158                 pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist);
159                 CDEBUG(D_INODE, "checking page %p\n", pgrq->rq_page);
160                 if (pgrq->rq_page == page) {
161                         CDEBUG(D_INODE, "found page %p in list\n", page);
162                         EXIT;
163                         return pgrq;
164                 }
165         } 
166
167         EXIT;
168         return NULL;
169 } /* obdfs_find_in_page_list */
170
171
172 /* call and free pages from Linux page cache */
173 int obdfs_do_vec_wr(struct super_block *sb, obd_count num_io,
174                     obd_count num_obdos, struct obdo **obdos,
175                     obd_count *oa_bufs, struct page **pages, char **bufs,
176                     obd_size *counts, obd_off *offsets, obd_flag *flags)
177 {
178         struct obdfs_sb_info *sbi = (struct obdfs_sb_info *)&sb->u.generic_sbp;
179         int err;
180
181         ENTRY;
182         CDEBUG(D_INODE, "writing %d pages, %d obdos in vector\n",
183                num_io, num_obdos);
184         err = OPS(sb, brw)(WRITE, &sbi->osi_conn, num_obdos, obdos, oa_bufs,
185                                 bufs, counts, offsets, flags);
186
187         do {
188                 put_page(pages[--num_io]);
189         } while ( num_io > 0 );
190
191         EXIT;
192         return err;
193 }
194
195
196 /*
197  * Add a page to the write request cache list for later writing
198  * ASYNCHRONOUS write method.
199  */
200 static int obdfs_add_page_to_cache(struct inode *inode, struct page *page)
201 {
202         struct obdfs_pgrq *pgrq;
203
204         ENTRY;
205         pgrq = kmem_cache_alloc(obdfs_pgrq_cachep, SLAB_KERNEL);
206         CDEBUG(D_INODE, "adding inode %ld page %p, pgrq: %p\n",
207                inode->i_ino, page, pgrq);
208         if (!pgrq) {
209                 EXIT;
210                 return -ENOMEM;
211         }
212         memset(pgrq, 0, sizeof(*pgrq)); 
213
214         pgrq->rq_page = page;
215
216         get_page(pgrq->rq_page);
217
218         /* If this page isn't already in the inode page list, add it */
219         if ( !obdfs_find_in_page_list(inode, page) ) {
220                 CDEBUG(D_INODE, "adding page %p to inode list %p\n", page,
221                        obdfs_iplist(inode));
222                 list_add(&pgrq->rq_plist, obdfs_iplist(inode));
223         }
224
225         /* If inode isn't already on the superblock inodes list, add it */
226         if ( list_empty(obdfs_islist(inode)) ) {
227                 CDEBUG(D_INODE, "adding inode %p to superblock list %p\n",
228                        obdfs_islist(inode), obdfs_islist(inode));
229                 list_add(obdfs_islist(inode), obdfs_slist(inode));
230         }
231
232         EXIT;
233         /* XXX For testing purposes, we write out the page here.
234          *     In the future, a flush daemon will write out the page.
235         return 0;
236          */
237         return obdfs_flush_reqs(obdfs_slist(inode), 0, 0);
238 } /* obdfs_add_page_to_cache */
239
240
241 /* select between SYNC and ASYNC I/O methods */
242 int obdfs_do_writepage(struct inode *inode, struct page *page, int sync)
243 {
244         int err;
245
246         ENTRY;
247         PDEBUG(page, "WRITEPAGE");
248         if ( sync )
249                 err = obdfs_brw(WRITE, inode, page, 1);
250         else
251                 err = obdfs_add_page_to_cache(inode, page);
252                 
253         if ( !err )
254                 SetPageUptodate(page);
255         PDEBUG(page,"WRITEPAGE");
256         EXIT;
257         return err;
258 } /* obdfs_do_writepage */
259
260 /* returns the page unlocked, but with a reference */
261 int obdfs_writepage(struct dentry *dentry, struct page *page)
262 {
263         return obdfs_do_writepage(dentry->d_inode, page, 0);
264 }
265
266 /*
267  * This does the "real" work of the write. The generic routine has
268  * allocated the page, locked it, done all the page alignment stuff
269  * calculations etc. Now we should just copy the data from user
270  * space and write it back to the real medium..
271  *
272  * If the writer ends up delaying the write, the writer needs to
273  * increment the page use counts until he is done with the page.
274  *
275  * Return value is the number of bytes written.
276  */
277 int obdfs_write_one_page(struct file *file, struct page *page,
278                           unsigned long offset, unsigned long bytes,
279                           const char * buf)
280 {
281         struct inode *inode = file->f_dentry->d_inode;
282         int err;
283
284         ENTRY;
285         if ( !Page_Uptodate(page) ) {
286                 err = obdfs_brw(READ, inode, page, 1);
287                 if ( !err )
288                         SetPageUptodate(page);
289                 else
290                         return err;
291         }
292
293         if (copy_from_user((u8*)page_address(page) + offset, buf, bytes))
294                 return -EFAULT;
295
296         lock_kernel();
297         err = obdfs_writepage(file->f_dentry, page);
298         unlock_kernel();
299
300         return (err < 0 ? err : bytes);
301 } /* obdfs_write_one_page */
302
303 /* 
304    return an up to date page:
305     - if locked is true then is returned locked
306     - if create is true the corresponding disk blocks are created 
307     - page is held, i.e. caller must release the page
308
309    modeled on NFS code.
310 */
311 struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create, int locked)
312 {
313         struct page *page_cache;
314         struct page ** hash;
315         struct page * page;
316         int err;
317
318         ENTRY;
319
320         offset = offset & PAGE_CACHE_MASK;
321         CDEBUG(D_INODE, "\n");
322         
323         page = NULL;
324         page_cache = page_cache_alloc();
325         if ( ! page_cache ) {
326                 EXIT;
327                 return NULL;
328         }
329         CDEBUG(D_INODE, "page_cache %p\n", page_cache);
330
331         hash = page_hash(&inode->i_data, offset);
332         page = grab_cache_page(&inode->i_data, offset);
333
334         /* Yuck, no page */
335         if (! page) {
336             printk("grab_cache_page says no dice ...\n");
337             EXIT;
338             return 0;
339         }
340
341         PDEBUG(page, "GETPAGE: got page - before reading\n");
342         /* now check if the data in the page is up to date */
343         if ( Page_Uptodate(page)) { 
344                 if (!locked)
345                         UnlockPage(page);
346                 EXIT;
347                 return page;
348         } 
349
350         err = obdfs_brw(READ, inode, page, create);
351
352         if ( err ) {
353                 SetPageError(page);
354                 UnlockPage(page);
355                 EXIT;
356                 return page;
357         }
358
359         if ( !locked )
360                 UnlockPage(page);
361         SetPageUptodate(page);
362         PDEBUG(page,"GETPAGE - after reading");
363         EXIT;
364         return page;
365 } /* obdfs_getpage */
366
367